🗃️

OpenTelemetry CollectorでSQL Queryしてログ取得かメトリクス化する

2023/10/13に公開

はじめに

たまに取り込みたいデータがDB内にある時がありますよね。
なんとOpenTelemetry CollectorはDBにクエリかけて取り込めもできちゃいます。

SQL Query receiver

これを使います。

https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/sqlqueryreceiver

特徴としてはこの辺りかと思います。

  • 任意のカラムの最終取り込み値を管理して差分取得(tracking)ができる
  • ログ直接取り込み、もしくはメトリクス化して取り込みができる

対応DB driverは現時点(2023年10月)だと以下のようです。

postgres, mysql, snowflake, sqlserver, hdb (SAP HANA), or oracle (Oracle DB).

まだMetricはAlpha、LogはDevelopmentなので将来の拡張に期待です。

やってみた

テストデータ

PostgreSQLでこんなデータを用意しました。裏側でスクリプト走らせて毎秒追加しています。

id timestamp alert_level message
10001 2023-10-13 04:42:17.4883+00 INFO Sample message at level INFO
10002 2023-10-13 04:42:18.490512+00 ERROR Sample message at level ERROR
10003 2023-10-13 04:42:19.49282+00 ERROR Sample message at level ERROR
・・・ ・・・ ・・・ ・・・

Otel設定

Otel Collectorには以下のような設定をします。

receivers:
  sqlquery/postgrestest:
    driver: postgres
    storage: file_storage  # Checkpoint保存先をファイルとする
    datasource: "host=localhost port=5432 user=<User Name> password=<Password> dbname=<DB name> sslmode=disable" # 定義方法は各DBによる。これはPostgreSQL用
    collection_interval: 60s # デフォルト10s
    queries:
      - sql: "SELECT id, row_to_json(t) FROM (SELECT * FROM alert_logs WHERE id > $$1 ORDER BY id) t;"
        tracking_start_value: 1 # tracking初期値。デフォルトは""。
        tracking_column: id # tracking用カラム名。デフォルトは""。
        logs:
          - body_column: row_to_json # 出力したいカラム名
      - sql: "select count(*) as count, alert_level from alert_logs group by alert_level"
        metrics: # これでメトリクス化できる
          - metric_name: alert.level
            value_column: "count"
            attribute_columns: ["alert_level"]
            static_attributes:
              dbinstance: dbdemo

extensions:
  file_storage:

# ログをSplunkに送る場合で、sourcetypeを変えたい場合。
processors:
  resource/sqlquery:
    attributes:
      - key: com.splunk.sourcetype
        value: "_json"
        action: upsert

service:
  extensions: [..., file_storage]
  pipelines:
    metrics:
      receivers: [..., sqlquery/postgrestest]

    logs/sqlquery:
      receivers: [sqlquery/postgrestest]
      processors: [resource/sqlquery] # ログをSplunkに送る場合で、sourcetypeを変えたい場合。

注意点としては以下の辺りかなと思います。

  • storageを定義すること。さもないとチェックポイントがメモリ内に保存されてOtel Collector再起動時に失われてしまう。
    ちなみにextensions.file_storageを指定するとデフォルト値で/var/lib/otelcol/file_storage/receiver_sqlquery_postgrestestに出力される。
    /var/lib/otelcol/file_storageをRead/Write権限与えて作成しておくこと。
  • trackingを行う場合、必ずSELECTで対象のカラムを出力すること。Trackingの詳細はこちら
  • ログとして出力するカラムは一つしか選べない。複数のカラムの値を送りたい場合は結合するかJSONにするとよい。

log

クエリと結果はこんなのです。
$$1はPostgreSQL用のプレースホルダ表記方法なのでDBに応じて変えてください。
上で書いた通り、カラムは今のところ一つしか選べないので複数のカラムをJSONでまとめました。

log用クエリ
SELECT id, row_to_json(t) FROM (SELECT * FROM alert_logs WHERE id > $$1 ORDER BY id) t;
id row_to_json
10001 {"id":10001,"timestamp":"2023-10-13T04:42:17.4883+00:00","alert_level":"INFO","message":"Sample message at level INFO"}

Splunkに投げてみました。
ちゃんとJSONを解析してくれていますね。
この画像からは見えないですが、ちゃんとクエリの度にTrackingにより差分だけ取れています。

metric

クエリと結果はこんなのです。
もちろん、こっちでもTracking使ってもいいです。

metric用クエリ
select count(*) as count, alert_level from alert_logs group by alert_level;
count alert_level
4453 ERROR
4271 WARNING
4297 INFO

これもSplunkに。
いいですね。
デフォルトはgaugeですが設定でdeltaにもできます

まとめ

Otel Collector、なんでもできちゃうねというお話の一つでした。

Discussion