Prometheus

概要

PrometheusはPull方式でアプリケーションのメトリクスを公開します。

機能

1. メトリクスエクスポート機能

メトリクスエクスポート機能はアプリケーションのメトリクスをオブザーバビリティバックエンドへ公開します。

Prometheusは、Pull方式でメトリクスを公開します。この時、PrometheusエクスポータがハンドラとしてHTTPサーバに登録され、エンドポイントを通じてアクセスできる必要があります。 Prometheusバックエンドはエンドポイントにアクセスし、メトリクスを収集します。

graph LR
  Client --> Application["Application</br>(Prometheus exporter)"]
  Backend["Prometheus</br>Backend"] --"Pull metrics"--> Application

以下の実装例は、簡単なアクセスログとともにPrometheusによりメトリクスを公開する例です。

package main

import (
	"log"
	"net/http"
	"time"

	"github.com/aileron-projects/aileron-observability/metrics/prom"
)

func main() {
	p, _ := prom.New(&prom.Config{})

	log.Println("server listening on localhost:8080")
	svr := &http.Server{
		Addr: ":8080",
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			log.Println(r.Method, r.URL.Path) // Simple access log.
			p.ServeHTTP(w, r)
		}),
		ReadTimeout: 10 * time.Second,
	}
	if err := svr.ListenAndServe(); err != nil {
		panic(err)
	}
}

2. APIリクエスト統計取得機能

APIリクエスト統計取得機能はAPIコールに関するメトリクスを取得する機能です。 この機能はサーバサイドミドルウェア、あるいはクライアントサイドミドルウェアとして機能します。

APIコールは以下の項目によりグルーピングされ、カウントされます。

  • method: HTTPメソッド
  • host: ホスト名
  • path: URLパス
  • code: ステータスコード

サーバサイドのAPIメトリクスを取得するにはサーバサイドミドルウェアを利用します。 クライアントサイドのAPIメトリクスを取得するにはクライアントサイドミドルウェアを利用します。

セキュリティに関する特記事項

メトリクスのエンドポイントに適切なアクセス制御を行ってください。

性能に関する特記事項

性能に関する特記事項は特にありません。

実装例・使い方

メトリクス公開

PrometheusはPull方式でメトリクスを公開します。 以下の実装例の通り、Prometheusエクスポータ(ハンドラ)をサーバに登録することで利用できます。

package main

import (
	"log"
	"net/http"
	"time"

	"github.com/aileron-projects/aileron-observability/metrics/prom"
)

func main() {
	p, _ := prom.New(&prom.Config{})

	log.Println("server listening on localhost:8080")
	svr := &http.Server{
		Addr: ":8080",
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			log.Println(r.Method, r.URL.Path) // Simple access log.
			p.ServeHTTP(w, r)
		}),
		ReadTimeout: 10 * time.Second,
	}
	if err := svr.ListenAndServe(); err != nil {
		panic(err)
	}
}

公開されているエンドポイントを通して、メトリクスを取得します。

以下にサンプルのdocker-composeとprometheusのconfigファイルを示します。

{ { % code source="ex_basic/docker-compose.yaml" % } }
{ { % code source="ex_basic/prometheus.yaml" % } }

サーバサイドAPIメトリクス

サーバサイドでAPIコールのメトリクスを取得するにはサーバサイドミドルウェアを利用します。 以下に簡単な利用例を示します。

package main

import (
	"log"
	"net/http"
	"time"

	"github.com/aileron-projects/aileron-observability/metrics/prom"
)

func main() {
	p, _ := prom.New(&prom.Config{})
	h := p.ServerMiddleware(p) // Apply server-side API call counting.

	log.Println("server listening on localhost:8080")
	svr := &http.Server{
		Addr: ":8080",
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			log.Println(r.Method, r.URL.Path) // Simple access log.
			h.ServeHTTP(w, r)
		}),
		ReadTimeout: 10 * time.Second,
	}
	if err := svr.ListenAndServe(); err != nil {
		panic(err)
	}
}

クライアントサイドAPIメトリクス

クライアントサイドでAPIコールのメトリクスを取得するにはクライアントサイドミドルウェアを利用します。 以下に簡単な利用例を示します。

package main

import (
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
	"time"

	"github.com/aileron-projects/aileron-observability/metrics/prom"
)

func main() {
	p, _ := prom.New(&prom.Config{})
	http.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) {
		log.Println(r.Method, r.URL.Path) // Simple access log.
		p.ServeHTTP(w, r)
	})

	rt := http.DefaultTransport // A http client.
	rt = p.ClientMiddleware(rt) // Apply client-side API call counting.

	target, _ := url.Parse("http://httpbin.org")
	proxy := httputil.NewSingleHostReverseProxy(target)
	proxy.Transport = rt

	log.Println("server listening on localhost:8080")
	svr := &http.Server{
		Addr:        ":8080",
		Handler:     proxy,
		ReadTimeout: 10 * time.Second,
	}
	if err := svr.ListenAndServe(); err != nil {
		panic(err)
	}
}