Skip to content

Commit

Permalink
feat: extract autometer, autotracer
Browse files Browse the repository at this point in the history
  • Loading branch information
ernado committed Apr 16, 2023
1 parent 7eeb3a5 commit 962ea72
Show file tree
Hide file tree
Showing 6 changed files with 382 additions and 187 deletions.
1 change: 0 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ linters:
- staticcheck
- typecheck
- unconvert
- unparam
- unused
- whitespace
- gochecknoglobals
Expand Down
203 changes: 17 additions & 186 deletions internal/app/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package app

import (
"context"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"os"
Expand All @@ -15,29 +13,21 @@ import (
"github.com/go-faster/errors"
"github.com/go-logr/zapr"
promClient "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
"github.com/prometheus/client_golang/prometheus/promhttp"
"go.opentelemetry.io/contrib/instrumentation/runtime"
"go.opentelemetry.io/contrib/propagators/autoprop"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/exporters/prometheus"
"go.opentelemetry.io/otel/exporters/stdout/stdoutmetric"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/global"
"go.opentelemetry.io/otel/propagation"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/trace"
"go.uber.org/multierr"
"go.uber.org/zap"
"golang.org/x/sync/errgroup"

"github.com/go-faster/simon/sdk/autometer"
"github.com/go-faster/simon/sdk/autotracer"
)

// Metrics implement common basic metrics and infrastructure to it.
Expand Down Expand Up @@ -200,29 +190,6 @@ func prometheusAddr() string {
return net.JoinHostPort(host, port)
}

const (
writerStdout = "stdout"
writerStderr = "stderr"
)

func writerByName(name string) io.Writer {
switch name {
case writerStdout:
return os.Stdout
case writerStderr:
return os.Stderr
default:
return io.Discard
}
}

func getEnvOr(name, def string) string {
if v := os.Getenv(name); v != "" {
return v
}
return def
}

func newMetrics(ctx context.Context, lg *zap.Logger) (*Metrics, error) {
otel.SetLogger(zapr.NewLogger(lg.Named("otel")))

Expand Down Expand Up @@ -250,162 +217,26 @@ func newMetrics(ctx context.Context, lg *zap.Logger) (*Metrics, error) {
}

m.registerShutdown("http", m.srv.Shutdown)

// OTEL configuration from environment.
//
// See https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/
const (
expOTLP = "otlp"
expNone = "none" // no-op
expPrometheus = "prometheus"
expJaeger = "jaeger"

protoHTTP = "http"
protoGRPC = "grpc"
defaultProto = protoGRPC
)

// Metrics exporter.
switch exporter := strings.TrimSpace(getEnvOr("OTEL_METRICS_EXPORTER", expOTLP)); exporter {
case expPrometheus:
lg.Info("Using prometheus exporter")
reg := promClient.NewPedanticRegistry()
exp, err := prometheus.New(
prometheus.WithRegisterer(reg),
)
m.registerShutdown(exporter, exp.Shutdown)
{
provider, stop, err := autotracer.NewTracerProvider(ctx, autotracer.WithResource(res))
if err != nil {
return nil, errors.Wrap(err, "prometheus")
}
// Register legacy prometheus-only runtime metrics for backward compatibility.
reg.MustRegister(
collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}),
collectors.NewGoCollector(),
collectors.NewBuildInfoCollector(),
)
m.prometheus = reg
m.meterProvider = sdkmetric.NewMeterProvider(
sdkmetric.WithResource(res),
sdkmetric.WithReader(exp),
)
case expOTLP:
proto := os.Getenv("OTEL_EXPORTER_OTLP_PROTOCOL")
if proto == "" {
proto = os.Getenv("OTEL_EXPORTER_OTLP_METRICS_PROTOCOL")
}
if proto == "" {
proto = defaultProto
return nil, errors.Wrap(err, "tracer provider")
}
lg.Info("Using otlp metrics exporter", zap.String("protocol", proto))
switch proto {
case protoHTTP:
exp, err := otlpmetricgrpc.New(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to build grpc trace exporter")
}
m.registerShutdown("otlp.metrics.grpc", exp.Shutdown)
m.meterProvider = sdkmetric.NewMeterProvider(
sdkmetric.WithResource(res),
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exp)),
)
case protoGRPC:
exp, err := otlpmetrichttp.New(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to build http trace exporter")
}
m.registerShutdown("otlp.metrics.http", exp.Shutdown)
m.meterProvider = sdkmetric.NewMeterProvider(
sdkmetric.WithResource(res),
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exp)),
)
default:
return nil, fmt.Errorf("unsupported metric otlp protocol %q", proto)
}
case writerStdout, writerStderr:
lg.Info(fmt.Sprintf("Using %s periodic metric exporter", exporter))
enc := json.NewEncoder(writerByName(exporter))
exp, err := stdoutmetric.New(stdoutmetric.WithEncoder(enc))
if err != nil {
return nil, errors.Wrap(err, "stdout metric provider")
}
m.registerShutdown(exporter, exp.Shutdown)
m.meterProvider = sdkmetric.NewMeterProvider(
sdkmetric.WithResource(res),
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exp)),
)
case expNone:
lg.Info("No metrics exporter is configured by OTEL_METRICS_EXPORTER")
m.meterProvider = metric.NewNoopMeterProvider()
default:
return nil, errors.Errorf("unsupported OTEL_METRICS_EXPORTER %q", exporter)
m.tracerProvider = provider
m.registerShutdown("tracer", stop)
}

// Traces exporter.
switch exporter := strings.TrimSpace(getEnvOr("OTEL_TRACES_EXPORTER", expOTLP)); exporter {
case expJaeger:
lg.Info("Using jaeger exporter")
var jaegerOptions []jaeger.AgentEndpointOption
jaegerOptions = append(jaegerOptions,
jaeger.WithLogger(zap.NewStdLog(lg.Named("jaeger"))),
)
exp, err := jaeger.New(jaeger.WithAgentEndpoint(jaegerOptions...))
if err != nil {
return nil, errors.Wrap(err, "jaeger")
}
m.registerShutdown(exporter, exp.Shutdown)
m.tracerProvider = sdktrace.NewTracerProvider(
sdktrace.WithResource(res),
sdktrace.WithBatcher(exp),
{
provider, stop, err := autometer.NewMeterProvider(ctx,
autometer.WithResource(res),
autometer.WithOnPrometheusRegistry(func(reg *promClient.Registry) {
m.prometheus = reg
}),
)
case expOTLP:
proto := os.Getenv("OTEL_EXPORTER_OTLP_PROTOCOL")
if proto == "" {
proto = os.Getenv("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL")
}
if proto == "" {
proto = defaultProto
}
lg.Info("Using otlp traces exporter", zap.String("protocol", proto))
switch proto {
case protoGRPC:
exp, err := otlptracegrpc.New(ctx)
if err != nil {
return nil, fmt.Errorf("failed to create trace exporter: %w", err)
}
m.registerShutdown("otlp.traces", exp.Shutdown)
m.tracerProvider = sdktrace.NewTracerProvider(
sdktrace.WithResource(res),
sdktrace.WithBatcher(exp),
)
case protoHTTP:
exp, err := otlptracehttp.New(ctx)
if err != nil {
return nil, fmt.Errorf("failed to create trace exporter: %w", err)
}
m.registerShutdown("otlp.traces", exp.Shutdown)
m.tracerProvider = sdktrace.NewTracerProvider(
sdktrace.WithResource(res),
sdktrace.WithBatcher(exp),
)
default:
return nil, fmt.Errorf("unsupported traces otlp protocol %q", proto)
}
case writerStdout, writerStderr:
lg.Info(fmt.Sprintf("Using %s traces exporter", exporter))
exp, err := stdouttrace.New(stdouttrace.WithWriter(writerByName(exporter)))
if err != nil {
return nil, errors.Wrap(err, "stdout")
return nil, errors.Wrap(err, "meter provider")
}
m.registerShutdown(exporter, exp.Shutdown)
m.tracerProvider = sdktrace.NewTracerProvider(
sdktrace.WithResource(res),
sdktrace.WithBatcher(exp),
)
case expNone:
lg.Info("No traces exporter is configured by OTEL_TRACES_EXPORTER")
m.tracerProvider = trace.NewNoopTracerProvider()
default:
return nil, errors.Errorf("unsupported OTEL_TRACES_EXPORTER %q", exporter)
m.meterProvider = provider
m.registerShutdown("meter", stop)
}

// Automatically composited from the OTEL_PROPAGATORS environment variable.
Expand Down
Loading

0 comments on commit 962ea72

Please sign in to comment.