pomerium/internal/zero/telemetry/reporter/healthcheck.go
Caleb Doxsey d062f9d68d
core/logs: remove warnings (#5235)
* core/logs: remove warnings

* switch to error
2024-08-27 09:38:50 -06:00

92 lines
2.6 KiB
Go

package reporter
import (
"context"
"errors"
"fmt"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
export_grpc "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/sdk/resource"
trace_sdk "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/trace"
"google.golang.org/grpc"
"github.com/pomerium/pomerium/internal/log"
"github.com/pomerium/pomerium/pkg/health"
)
type healthCheckReporter struct {
resource *resource.Resource
exporter *otlptrace.Exporter
provider *trace_sdk.TracerProvider
tracer trace.Tracer
}
// NewhealthCheckReporter creates a new unstarted health check healthCheckReporter
func newHealthCheckReporter(
conn *grpc.ClientConn,
resource *resource.Resource,
) *healthCheckReporter {
exporter := export_grpc.NewUnstarted(export_grpc.WithGRPCConn(conn))
processor := trace_sdk.NewBatchSpanProcessor(exporter)
provider := trace_sdk.NewTracerProvider(
trace_sdk.WithResource(resource),
trace_sdk.WithSampler(trace_sdk.AlwaysSample()),
trace_sdk.WithSpanProcessor(processor),
)
tracer := provider.Tracer(serviceName)
return &healthCheckReporter{
resource: resource,
exporter: exporter,
tracer: tracer,
provider: provider,
}
}
func (r *healthCheckReporter) Run(ctx context.Context) error {
err := r.exporter.Start(ctx)
if err != nil {
// this should not happen for the gRPC exporter as its non-blocking
return fmt.Errorf("error starting health check exporter: %w", err)
}
<-ctx.Done()
return nil
}
func (r *healthCheckReporter) Shutdown(ctx context.Context) error {
return errors.Join(
r.provider.Shutdown(ctx),
r.exporter.Shutdown(ctx),
)
}
// ReportOK implements health.Provider interface
func (r *healthCheckReporter) ReportOK(check health.Check, attr ...health.Attr) {
ctx := context.Background()
log.Ctx(ctx).Debug().Str("check", string(check)).Msg("health check ok")
_, span := r.tracer.Start(ctx, string(check))
span.SetStatus(codes.Ok, "")
setAttributes(span, attr...)
span.End()
}
// ReportError implements health.Provider interface
func (r *healthCheckReporter) ReportError(check health.Check, err error, attr ...health.Attr) {
ctx := context.Background()
log.Ctx(ctx).Error().Str("check", string(check)).Err(err).Msg("health check error")
_, span := r.tracer.Start(ctx, string(check))
span.SetStatus(codes.Error, err.Error())
setAttributes(span, attr...)
span.End()
}
func setAttributes(span trace.Span, attr ...health.Attr) {
for _, a := range attr {
span.SetAttributes(attribute.String(a.Key, a.Value))
}
}