🦔

GoアプリケーションでOpenMetrics形式のメトリクスを出力させてみた

2022/09/17に公開

1. OpenMetricsとは

OpenMetricsは、Prometheus exposition formatを標準化することを目的として[1]、Prometheus exposition formatをベースに、ほぼ100%の後方互換性を保ちつつ慎重に拡張された仕様です[2]
そして、Prometheus exposition formatとは、Prometheusで使用されているテキストベースのメトリクス形式のことで、生成・取得・人間が理解しやすいよう設計されたフォーマットになります[3]

以下にOpenMetricsの一例[4]を示します。例からわかるように、このフォーマットは行指向となっており、各行は区切り文字(\n)によって改行され、最終行も区切り文字(\n)となっています。また、行内は空白orタブ区切りで記述されています[5]

# HELP http_requests_total The total number of HTTP requests.
# TYPE http_requests_total counter
http_requests_total{method="post",code="200"} 1027 1395066363000
http_requests_total{method="post",code="400"}    3 1395066363000

OpenMetricsでは、#から始まる行はコメントを表しますが、#直後のトークンがHELPTYPEの場合には特別な意味を持ちます。#直後のトークンがHELPの場合は、その後にメトリクス名とそのメトリクスについての説明が記述され、#直後のトークンがTYPEの場合には、メトリクス名とそのメトリクスの型が記述されます[6]

メトリクスの型はGauge, Counter, Info, StateSet, Summary, Histogram, GaugeHistogram, Unknownの8種類が用意されており[7]、Prometheus exposition formatで用意されていたGauge, Counter, Summary, Histogram, Unknownの5種類[8]から拡張されているようです。メトリクスの型に関する詳細説明はOpenMetricsの公式ドキュメントPrometheusの公式ドキュメントに記載がありますので、そちらをご参照ください。

また、例の中にあるhttp_requests_total{method="post",code="200"}{}内はラベルを表しています。つまり、この例の場合はPOSTリクエストを受けて200コードを返したリクエストの総数を意味しています。

2. GoアプリケーションでOpenMetricsを出力するには

Go言語用のPrometheusクライアントライブラリを利用することで、簡単にOpenMetrics形式のメトリクスが出力できるようになります[9]。やることは、クライアントライブラリのパッケージの一つであるpromhttpgo getし、以下のようにコードを記述して/metricsエンドポイントを用意するだけです[10]

package main

import (
        "net/http"

        "github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {
        http.Handle("/metrics", promhttp.Handler())
        http.ListenAndServe(":2112", nil)
}

上記のようにして作成したエンドポイントにGETリクエストを送ることで、以下のようなメトリクスがデフォルトで取得できます。

# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 7
# HELP go_info Information about the Go environment.
# TYPE go_info gauge
go_info{version="go1.18.6"} 1
# HELP go_memstats_alloc_bytes Number of bytes allocated and still in use.
# TYPE go_memstats_alloc_bytes gauge
go_memstats_alloc_bytes 2.437504e+06
# HELP go_memstats_alloc_bytes_total Total number of bytes allocated, even if freed.
# TYPE go_memstats_alloc_bytes_total counter
go_memstats_alloc_bytes_total 2.437504e+06
# HELP go_memstats_buck_hash_sys_bytes Number of bytes used by the profiling bucket hash table.
# TYPE go_memstats_buck_hash_sys_bytes gauge
go_memstats_buck_hash_sys_bytes 4416
# HELP go_memstats_frees_total Total number of frees.
# TYPE go_memstats_frees_total counter
go_memstats_frees_total 171
# HELP go_memstats_gc_sys_bytes Number of bytes used for garbage collection system metadata.
# TYPE go_memstats_gc_sys_bytes gauge
go_memstats_gc_sys_bytes 3.641408e+06
# HELP go_memstats_heap_alloc_bytes Number of heap bytes allocated and still in use.
# TYPE go_memstats_heap_alloc_bytes gauge
go_memstats_heap_alloc_bytes 2.437504e+06
# HELP go_memstats_heap_idle_bytes Number of heap bytes waiting to be used.
# TYPE go_memstats_heap_idle_bytes gauge
go_memstats_heap_idle_bytes 1.236992e+06
# HELP go_memstats_heap_inuse_bytes Number of heap bytes that are in use.
# TYPE go_memstats_heap_inuse_bytes gauge
go_memstats_heap_inuse_bytes 2.465792e+06
# HELP go_memstats_heap_objects Number of allocated objects.
# TYPE go_memstats_heap_objects gauge
go_memstats_heap_objects 14055
# HELP go_memstats_heap_released_bytes Number of heap bytes released to OS.
# TYPE go_memstats_heap_released_bytes gauge
go_memstats_heap_released_bytes 1.236992e+06
# HELP go_memstats_heap_sys_bytes Number of heap bytes obtained from system.
# TYPE go_memstats_heap_sys_bytes gauge
go_memstats_heap_sys_bytes 3.702784e+06
# HELP go_memstats_last_gc_time_seconds Number of seconds since 1970 of last garbage collection.
# TYPE go_memstats_last_gc_time_seconds gauge
go_memstats_last_gc_time_seconds 0
# HELP go_memstats_lookups_total Total number of pointer lookups.
# TYPE go_memstats_lookups_total counter
go_memstats_lookups_total 0
# HELP go_memstats_mallocs_total Total number of mallocs.
# TYPE go_memstats_mallocs_total counter
go_memstats_mallocs_total 14226
# HELP go_memstats_mcache_inuse_bytes Number of bytes in use by mcache structures.
# TYPE go_memstats_mcache_inuse_bytes gauge
go_memstats_mcache_inuse_bytes 2400
# HELP go_memstats_mcache_sys_bytes Number of bytes used for mcache structures obtained from system.
# TYPE go_memstats_mcache_sys_bytes gauge
go_memstats_mcache_sys_bytes 15600
# HELP go_memstats_mspan_inuse_bytes Number of bytes in use by mspan structures.
# TYPE go_memstats_mspan_inuse_bytes gauge
go_memstats_mspan_inuse_bytes 37128
# HELP go_memstats_mspan_sys_bytes Number of bytes used for mspan structures obtained from system.
# TYPE go_memstats_mspan_sys_bytes gauge
go_memstats_mspan_sys_bytes 48960
# HELP go_memstats_next_gc_bytes Number of heap bytes when next garbage collection will take place.
# TYPE go_memstats_next_gc_bytes gauge
go_memstats_next_gc_bytes 4.194304e+06
# HELP go_memstats_other_sys_bytes Number of bytes used for other system allocations.
# TYPE go_memstats_other_sys_bytes gauge
go_memstats_other_sys_bytes 568928
# HELP go_memstats_stack_inuse_bytes Number of bytes in use by the stack allocator.
# TYPE go_memstats_stack_inuse_bytes gauge
go_memstats_stack_inuse_bytes 491520
# HELP go_memstats_stack_sys_bytes Number of bytes obtained from system for stack allocator.
# TYPE go_memstats_stack_sys_bytes gauge
go_memstats_stack_sys_bytes 491520
# HELP go_memstats_sys_bytes Number of bytes obtained from system.
# TYPE go_memstats_sys_bytes gauge
go_memstats_sys_bytes 8.473616e+06
# HELP go_threads Number of OS threads created.
# TYPE go_threads gauge
go_threads 9
# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 0.02
# HELP process_max_fds Maximum number of open file descriptors.
# TYPE process_max_fds gauge
process_max_fds 1.048576e+06
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
process_open_fds 9
# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes 1.13664e+07
# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1.66324054887e+09
# HELP process_virtual_memory_bytes Virtual memory size in bytes.
# TYPE process_virtual_memory_bytes gauge
process_virtual_memory_bytes 7.33581312e+08
# HELP process_virtual_memory_max_bytes Maximum amount of virtual memory available in bytes.
# TYPE process_virtual_memory_max_bytes gauge
process_virtual_memory_max_bytes 1.8446744073709552e+19
# HELP promhttp_metric_handler_requests_in_flight Current number of scrapes being served.
# TYPE promhttp_metric_handler_requests_in_flight gauge
promhttp_metric_handler_requests_in_flight 1
# HELP promhttp_metric_handler_requests_total Total number of scrapes by HTTP status code.
# TYPE promhttp_metric_handler_requests_total counter
promhttp_metric_handler_requests_total{code="200"} 0
promhttp_metric_handler_requests_total{code="500"} 0
promhttp_metric_handler_requests_total{code="503"} 0

注意点としては、Prometheusサーバーが行ったHTTPリクエストの総数を表していたメトリクス名がhandler_requests_totalからpromhttp_metric_handler_requests_totalへ変更されていることでしょうか[11]。記事が古い場合だと、PromQLを使ってhandler_requests_totalメトリクスを取得してみましょうと記述されているのですが、今は取得できないので注意が必要です。私はこれに結構ハマりました^^;

3. まとめ

GoアプリケーションでOpenMetrics形式のメトリクスを出力させてみたので、これを実装するにあたって調べたことを記事にまとめてみました。Prometheusの勉強を始めたばかりなのですが、まだまだ情報がまとまった記事が少なくて入門するのにハードルを感じたので、調べたことをまとめた次第です。誰かの何かのお役に立てれば幸いです^^

脚注
  1. "Prometheus (software)". wikipedia. 2022-9-17 ↩︎

  2. "OpenObservability/OpenMetrics#OpenMetrics". GitHub. 2022-9-17 ↩︎

  3. "OpenObservability/OpenMetrics#Introduction". GitHub. 2022-9-17 ↩︎

  4. "EXPOSITION FORMATS#Text format example - Prometheus". prometheus.io. 2022-9-17 ↩︎

  5. "EXPOSITION FORMATS#Line format - Prometheus". prometheus.io. 2022-9-17 ↩︎

  6. "EXPOSITION FORMATS#Comments, help text, and type information - Prometheus". prometheus.io. 2022-9-17 ↩︎

  7. OpenObservability/OpenMetrics#Metric types. GitHub. 2022-9-17 ↩︎

  8. "EXPOSITION FORMATS#Comments, help text, and type information - Prometheus". prometheus.io. 2022-9-17 ↩︎

  9. "CLIENT LIBRARIES - Prometheus". prometheus.io. 2022-9-17 ↩︎

  10. "INSTRUMENTING A GO APPLICATION FOR PROMETHEUS - Prometheus". prometheus.io. 2022-9-17 ↩︎

  11. "Replace http_requests_total metric". GitHub. Pull Request. ↩︎

Discussion