signoz/pkg/instrumentation/instrumentation.go

96 lines
2.7 KiB
Go

package instrumentation
import (
"context"
"fmt"
contribsdkconfig "go.opentelemetry.io/contrib/config"
sdklog "go.opentelemetry.io/otel/log"
sdkmetric "go.opentelemetry.io/otel/metric"
sdkresource "go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
sdktrace "go.opentelemetry.io/otel/trace"
"go.signoz.io/signoz/pkg/version"
"go.uber.org/zap"
)
// Instrumentation holds the core components for application instrumentation.
type Instrumentation struct {
LoggerProvider sdklog.LoggerProvider
Logger *zap.Logger
MeterProvider sdkmetric.MeterProvider
TracerProvider sdktrace.TracerProvider
}
// New creates a new Instrumentation instance with configured providers.
// It sets up logging, tracing, and metrics based on the provided configuration.
func New(ctx context.Context, build version.Build, cfg Config) (*Instrumentation, error) {
// Set default resource attributes if not provided
if cfg.Resource.Attributes == nil {
cfg.Resource.Attributes = map[string]any{
string(semconv.ServiceNameKey): build.Name,
string(semconv.ServiceVersionKey): build.Version,
}
}
// Create a new resource with default detectors.
// The upstream contrib repository is not taking detectors into account.
// We are, therefore, using some sensible defaults here.
resource, err := sdkresource.New(
ctx,
sdkresource.WithContainer(),
sdkresource.WithFromEnv(),
sdkresource.WithHost(),
)
if err != nil {
return nil, err
}
// Prepare the resource configuration by merging
// resource and attributes.
sch := semconv.SchemaURL
configResource := contribsdkconfig.Resource{
Attributes: attributes(cfg.Resource.Attributes, resource),
Detectors: nil,
SchemaUrl: &sch,
}
loggerProvider, err := newLoggerProvider(ctx, cfg, configResource)
if err != nil {
return nil, fmt.Errorf("cannot create logger provider: %w", err)
}
tracerProvider, err := newTracerProvider(ctx, cfg, configResource)
if err != nil {
return nil, fmt.Errorf("cannot create tracer provider: %w", err)
}
meterProvider, err := newMeterProvider(ctx, cfg, configResource)
if err != nil {
return nil, fmt.Errorf("cannot create meter provider: %w", err)
}
return &Instrumentation{
LoggerProvider: loggerProvider,
TracerProvider: tracerProvider,
MeterProvider: meterProvider,
Logger: newLogger(cfg, loggerProvider),
}, nil
}
// attributes merges the input attributes with the resource attributes.
func attributes(input map[string]any, resource *sdkresource.Resource) map[string]any {
output := make(map[string]any)
for k, v := range input {
output[k] = v
}
kvs := resource.Attributes()
for _, kv := range kvs {
output[string(kv.Key)] = kv.Value
}
return output
}