kmuto’s blog

はてな社でMackerel CREをやっています。料理と旅行といろんなIT技術

RubyのOTel metrics投稿をちょっと試してみた

メモ書きレベル。

OpenTelemetryのRubyライブラリは現状、traceのみがひとまず使える状態で、metricsについてはunder developmentな状態となっている。

一応metricsのコード自体は存在し、alphaでリリースしようなPRも出ていたので、試してみた。

GitHubのコードを展開し、PR#1641をマージして、metrics_apiとmetrics_sdkのgemを順にrake buildで作成してインストールする。 metricsのKind実装としてはCounter、UpDownCounter、Histogramの3つのみで、それ以外のGaugeなどは非対応だった。無駄に情報量が多いものの、Histogramでひとまず送るようにしてみる。ほぼサンプルどおり。

require 'opentelemetry-metrics-sdk'
require 'opentelemetry-exporter-otlp-metrics'

# デフォルト
#ENV['OTEL_EXPORTER_OTLP_METRICS_ENDPOINT'] = 'http://localhost:4318/v1/metrics'

OpenTelemetry::SDK.configure
console_metric_exporter = OpenTelemetry::Exporter::OTLP::MetricsExporter.new
OpenTelemetry.meter_provider.add_metric_reader(console_metric_exporter)
meter = OpenTelemetry.meter_provider.meter('mymetric')

histogram = meter.create_histogram('myhistogram', unit: 'smidgen', description: 'description')
histogram.record(123, attributes: {'foo' => 'bar'})

OpenTelemetry.meter_provider.metric_readers.each(&:pull)
OpenTelemetry.meter_provider.shutdown

デフォルトのエンドポイントはローカルホストのHTTP protobufに向けたhttp://localhost:4318/v1/metricsになっている。変更したいときには環境変数OTEL_EXPORTER_OTLP_METRICS_ENDPOINTを指定してやればいい。

RubyのOTLP Metrics Exporter実装はまだgRPCに対応していないので、gRPCしか受け付けないところに送るにはotel-collectorにまず集約する必要がある(traceのほうはgRPC対応しているので、参考にしながら実装はできるだろう)。どっちにしろデバッグ用途やバッチ処理を含めてotel-collectorを挟んだほうが安全そうではある。

受け口のotel-collectorを設定する。

receivers:
  otlp:
    protocols:
      http:

exporters:
  debug:
    verbosity: detailed

service:
  pipelines:
    metrics:
      receivers: [otlp]
      exporters: [debug]

Rubyコードから投稿してみる。

2024-06-24T00:01:46.280+0900 info    MetricsExporter {"kind": "exporter", "data_type": "metrics", "name": "debug", "resource metrics": 1, "metrics": 1, "data points": 1}
2024-06-24T00:01:46.280+0900    info    ResourceMetrics #0
Resource SchemaURL: 
Resource attributes:
     -> service.name: Str(unknown_service)
     -> process.pid: Int(899318)
     -> process.command: Str(otlp-metric.rb)
     -> process.runtime.name: Str(ruby)
     -> process.runtime.version: Str(3.1.2)
     -> process.runtime.description: Str(ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux-gnu])
     -> telemetry.sdk.name: Str(opentelemetry)
     -> telemetry.sdk.language: Str(ruby)
     -> telemetry.sdk.version: Str(1.4.1)
ScopeMetrics #0
ScopeMetrics SchemaURL: 
InstrumentationScope mymetric 
Metric #0
Descriptor:
     -> Name: myhistogram
     -> Description: description
     -> Unit: smidgen
     -> DataType: Histogram
     -> AggregationTemporality: Delta
HistogramDataPoints #0
Data point attributes:
     -> foo: Str(bar)
StartTimestamp: 2024-06-23 15:01:46.27934498 +0000 UTC
Timestamp: 2024-06-23 15:01:46.279463724 +0000 UTC
Count: 1
Sum: 123.000000
Min: 123.000000
Max: 123.000000
ExplicitBounds #0: 0.000000
ExplicitBounds #1: 5.000000
ExplicitBounds #2: 10.000000
ExplicitBounds #3: 25.000000
ExplicitBounds #4: 50.000000
ExplicitBounds #5: 75.000000
ExplicitBounds #6: 100.000000
ExplicitBounds #7: 250.000000
ExplicitBounds #8: 500.000000
ExplicitBounds #9: 1000.000000
Buckets #0, Count: 0
Buckets #1, Count: 0
Buckets #2, Count: 0
Buckets #3, Count: 0
Buckets #4, Count: 0
Buckets #5, Count: 0
Buckets #6, Count: 0
Buckets #7, Count: 1
Buckets #8, Count: 0
Buckets #9, Count: 0
Buckets #10, Count: 0
    {"kind": "exporter", "data_type": "metrics", "name": "debug"}

ちゃんと出ていそう。service.nameが空なのはRuby側のどこかで設定する必要があるな。

エクスポート先のテストとしてMackerelを使ってみよう。MackerelのOTLPはgRPCのみの受け付けなので、受け取ったものをotel-collector経由で渡す。

receivers:
  otlp:
    protocols:
      http:

exporters:
  otlp/mackerel:
    endpoint: otlp.mackerelio.com:4317
    compression: gzip
    headers:
      Mackerel-Api-Key: ${env:MACKEREL_APIKEY}
  debug:
    verbosity: detailed


service:
  pipelines:
    metrics:
      receivers: [otlp]
      exporters: [otlp/mackerel, debug]

Mackerelのクエリグラフでもmyhistogramが出ることを確認。