Nik Afiq 657b6aeb22 feat: implement initial application structure with health and hello endpoints
- Add bootstrap package to initialize application components including logger, tracer, and HTTP server.
- Create config package to load runtime settings from environment variables.
- Implement observability features including logging, metrics, and tracing.
- Add health check and hello use cases with corresponding HTTP handlers.
- Introduce middleware for request ID, access logging, metrics, and recovery.
- Set up HTTP router with defined routes for health and hello endpoints.
- Include tests for health and hello endpoints to ensure proper functionality.
- Add OpenTelemetry collector configuration for trace exporting.
2026-03-05 21:22:43 +09:00

60 lines
1.6 KiB
Go

package observability
import (
"context"
"log/slog"
"strings"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
"go.opentelemetry.io/otel/trace"
)
func NewTracerProvider(ctx context.Context, logger *slog.Logger, serviceName, environment, otlpEndpoint string) (*sdktrace.TracerProvider, error) {
res, err := resource.New(
ctx,
resource.WithAttributes(
semconv.ServiceName(serviceName),
semconv.DeploymentEnvironmentName(environment),
),
)
if err != nil {
return nil, err
}
providerOptions := []sdktrace.TracerProviderOption{sdktrace.WithResource(res)}
endpoint := strings.TrimSpace(otlpEndpoint)
if endpoint != "" {
exporter, err := otlptracegrpc.New(
ctx,
otlptracegrpc.WithEndpoint(endpoint),
otlptracegrpc.WithInsecure(),
)
if err != nil {
return nil, err
}
providerOptions = append(providerOptions, sdktrace.WithBatcher(exporter))
logger.Info("otlp tracing exporter enabled", slog.String("endpoint", endpoint))
} else {
logger.Info("otlp endpoint not set, traces will not be exported")
}
tp := sdktrace.NewTracerProvider(providerOptions...)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(
propagation.NewCompositeTextMapPropagator(
propagation.TraceContext{},
propagation.Baggage{},
),
)
return tp, nil
}
func NewTracer(tp *sdktrace.TracerProvider, serviceName string) trace.Tracer {
return tp.Tracer(serviceName)
}