84 lines
2.2 KiB
Go
84 lines
2.2 KiB
Go
package metrics
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
"go.opentelemetry.io/otel"
|
|
"go.opentelemetry.io/otel/exporters/prometheus"
|
|
otelmetric "go.opentelemetry.io/otel/metric"
|
|
"go.opentelemetry.io/otel/sdk/metric"
|
|
"go.opentelemetry.io/otel/sdk/resource"
|
|
|
|
"github.com/kanootoko/codevault/internal"
|
|
"github.com/kanootoko/codevault/internal/config"
|
|
"github.com/kanootoko/codevault/internal/observability"
|
|
"github.com/kanootoko/codevault/internal/utils/gshutdown"
|
|
)
|
|
|
|
// Configure starts a Prometheus server which serves metrics and finishes on context finish
|
|
func Configure(ctx context.Context, cfg config.MetricsConfig) error {
|
|
if cfg.Host == "" {
|
|
return nil
|
|
}
|
|
res, err := observability.GetOtelResource()
|
|
if err != nil {
|
|
return fmt.Errorf("cannot get OpenTelemetry resource: %w", err)
|
|
}
|
|
|
|
meterProvider, err := newMeterProvider(res)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot instanciate OpenTelemetry meter provider: %w", err)
|
|
}
|
|
|
|
otel.SetMeterProvider(meterProvider)
|
|
|
|
mux := http.NewServeMux()
|
|
mux.Handle("/metrics", promhttp.Handler())
|
|
server := http.Server{
|
|
Addr: fmt.Sprintf(":%d", cfg.Port),
|
|
Handler: mux,
|
|
ReadTimeout: time.Second * 20,
|
|
ReadHeaderTimeout: time.Second * 10,
|
|
WriteTimeout: time.Second * 20,
|
|
}
|
|
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", cfg.Host, cfg.Port))
|
|
if err != nil {
|
|
return fmt.Errorf("error on creating listener for prometheus metrics: %w", err)
|
|
}
|
|
go func() { _ = server.Serve(listener) }()
|
|
_ = gshutdown.SubtaskStarted(ctx, "prometheus")
|
|
go func() {
|
|
defer func() {
|
|
_ = listener.Close()
|
|
_ = gshutdown.SubtaskFinished(ctx, "prometheus")
|
|
}()
|
|
<-ctx.Done()
|
|
_ = server.Shutdown(context.Background())
|
|
}()
|
|
|
|
return nil
|
|
}
|
|
|
|
func GetMeter() otelmetric.Meter {
|
|
mp := otel.GetMeterProvider()
|
|
return mp.Meter(internal.PackageName, otelmetric.WithInstrumentationVersion(internal.Version))
|
|
}
|
|
|
|
func newMeterProvider(res *resource.Resource) (*metric.MeterProvider, error) {
|
|
metricExporter, err := prometheus.New()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
meterProvider := metric.NewMeterProvider(
|
|
metric.WithResource(res),
|
|
metric.WithReader(metricExporter),
|
|
)
|
|
return meterProvider, nil
|
|
}
|