Skip to content

Commit

Permalink
feat(instrumentation): use new config factory (#6834)
Browse files Browse the repository at this point in the history
### Summary

Use new config factory and remove redundant configuration possibilities from the upstream
  • Loading branch information
grandwizard28 authored and amlannandy committed Jan 21, 2025
1 parent a9dd1a1 commit 3675457
Show file tree
Hide file tree
Showing 9 changed files with 265 additions and 226 deletions.
5 changes: 2 additions & 3 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ import (
// This map contains the default values of all config structs
var (
defaults = map[string]signozconfmap.Config{
"instrumentation": &instrumentation.Config{},
"web": &web.Config{},
"cache": &cache.Config{},
"web": &web.Config{},
"cache": &cache.Config{},
}
)

Expand Down
33 changes: 0 additions & 33 deletions pkg/config/unmarshaler_test.go

This file was deleted.

59 changes: 43 additions & 16 deletions pkg/instrumentation/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ package instrumentation

import (
contribsdkconfig "go.opentelemetry.io/contrib/config"
"go.signoz.io/signoz/pkg/confmap"
"go.signoz.io/signoz/pkg/factory"
"go.uber.org/zap/zapcore"
)

// Config satisfies the confmap.Config interface
var _ confmap.Config = (*Config)(nil)

// Config holds the configuration for all instrumentation components.
type Config struct {
Logs LogsConfig `mapstructure:"logs"`
Expand All @@ -24,39 +21,69 @@ type Resource struct {

// LogsConfig holds the configuration for the logging component.
type LogsConfig struct {
Enabled bool `mapstructure:"enabled"`
Level zapcore.Level `mapstructure:"level"`
contribsdkconfig.LoggerProvider `mapstructure:",squash"`
Enabled bool `mapstructure:"enabled"`
Level zapcore.Level `mapstructure:"level"`
Processors LogsProcessors `mapstructure:"processors"`
}

type LogsProcessors struct {
Batch contribsdkconfig.BatchLogRecordProcessor `mapstructure:"batch"`
}

// TracesConfig holds the configuration for the tracing component.
type TracesConfig struct {
Enabled bool `mapstructure:"enabled"`
contribsdkconfig.TracerProvider `mapstructure:",squash"`
Enabled bool `mapstructure:"enabled"`
Processors TracesProcessors `mapstructure:"processors"`
Sampler contribsdkconfig.Sampler `mapstructure:"sampler"`
}

type TracesProcessors struct {
Batch contribsdkconfig.BatchSpanProcessor `mapstructure:"batch"`
}

// MetricsConfig holds the configuration for the metrics component.
type MetricsConfig struct {
Enabled bool `mapstructure:"enabled"`
contribsdkconfig.MeterProvider `mapstructure:",squash"`
Enabled bool `mapstructure:"enabled"`
Readers MetricsReaders `mapstructure:"readers"`
}

func (c *Config) NewWithDefaults() confmap.Config {
return &Config{
type MetricsReaders struct {
Pull contribsdkconfig.PullMetricReader `mapstructure:"pull"`
}

func NewConfigFactory() factory.ConfigFactory {
return factory.NewConfigFactory(factory.MustNewName("instrumentation"), newConfig)
}

func newConfig() factory.Config {
host := "0.0.0.0"
port := 9090

return Config{
Logs: LogsConfig{
Enabled: false,
Level: zapcore.InfoLevel,
Level: zapcore.DebugLevel,
},
Traces: TracesConfig{
Enabled: false,
},
Metrics: MetricsConfig{
Enabled: false,
Enabled: true,
Readers: MetricsReaders{
Pull: contribsdkconfig.PullMetricReader{
Exporter: contribsdkconfig.MetricExporter{
Prometheus: &contribsdkconfig.Prometheus{
Host: &host,
Port: &port,
},
},
},
},
},
}

}

func (c *Config) Validate() error {
func (c Config) Validate() error {
return nil
}
98 changes: 29 additions & 69 deletions pkg/instrumentation/instrumentation.go
Original file line number Diff line number Diff line change
@@ -1,85 +1,34 @@
package instrumentation

import (
"context"
"fmt"
"os"

contribsdkconfig "go.opentelemetry.io/contrib/config"
"go.opentelemetry.io/contrib/bridges/otelzap"
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.signoz.io/signoz/pkg/factory"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

// Instrumentation holds the core components for application instrumentation.
type Instrumentation struct {
LoggerProvider sdklog.LoggerProvider
Logger *zap.Logger
MeterProvider sdkmetric.MeterProvider
TracerProvider sdktrace.TracerProvider
// Instrumentation provides the core components for application instrumentation.
type Instrumentation interface {
// LoggerProvider returns the OpenTelemetry logger provider.
LoggerProvider() sdklog.LoggerProvider
// Logger returns the Zap logger.
Logger() *zap.Logger
// MeterProvider returns the OpenTelemetry meter provider.
MeterProvider() sdkmetric.MeterProvider
// TracerProvider returns the OpenTelemetry tracer provider.
TracerProvider() sdktrace.TracerProvider
// ToProviderSettings converts instrumentation to provider settings.
ToProviderSettings() factory.ProviderSettings
}

// 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 {
// Merges the input attributes with the resource attributes.
func mergeAttributes(input map[string]any, resource *sdkresource.Resource) map[string]any {
output := make(map[string]any)

for k, v := range input {
Expand All @@ -93,3 +42,14 @@ func attributes(input map[string]any, resource *sdkresource.Resource) map[string

return output
}

// newLogger creates a new Zap logger with the configured level and output.
// It combines a JSON encoder for stdout and an OpenTelemetry bridge.
func newLogger(cfg Config, provider sdklog.LoggerProvider) *zap.Logger {
core := zapcore.NewTee(
zapcore.NewCore(zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), zapcore.AddSync(os.Stdout), cfg.Logs.Level),
otelzap.NewCore("go.signoz.io/pkg/instrumentation", otelzap.WithLoggerProvider(provider)),
)

return zap.New(core, zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))
}
54 changes: 54 additions & 0 deletions pkg/instrumentation/instrumentationtest/instrumentation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package instrumentationtest

import (
sdklog "go.opentelemetry.io/otel/log"
nooplog "go.opentelemetry.io/otel/log/noop"
sdkmetric "go.opentelemetry.io/otel/metric"
noopmetric "go.opentelemetry.io/otel/metric/noop"
sdktrace "go.opentelemetry.io/otel/trace"
nooptrace "go.opentelemetry.io/otel/trace/noop"
"go.signoz.io/signoz/pkg/factory"
"go.signoz.io/signoz/pkg/instrumentation"
"go.uber.org/zap"
)

type noopInstrumentation struct {
logger *zap.Logger
loggerProvider sdklog.LoggerProvider
meterProvider sdkmetric.MeterProvider
tracerProvider sdktrace.TracerProvider
}

func New() instrumentation.Instrumentation {
return &noopInstrumentation{
logger: zap.NewNop(),
loggerProvider: nooplog.NewLoggerProvider(),
meterProvider: noopmetric.NewMeterProvider(),
tracerProvider: nooptrace.NewTracerProvider(),
}
}

func (i *noopInstrumentation) LoggerProvider() sdklog.LoggerProvider {
return i.loggerProvider
}

func (i *noopInstrumentation) Logger() *zap.Logger {
return i.logger
}

func (i *noopInstrumentation) MeterProvider() sdkmetric.MeterProvider {
return i.meterProvider
}

func (i *noopInstrumentation) TracerProvider() sdktrace.TracerProvider {
return i.tracerProvider
}

func (i *noopInstrumentation) ToProviderSettings() factory.ProviderSettings {
return factory.ProviderSettings{
LoggerProvider: i.LoggerProvider(),
ZapLogger: i.Logger(),
MeterProvider: i.MeterProvider(),
TracerProvider: i.TracerProvider(),
}
}
45 changes: 0 additions & 45 deletions pkg/instrumentation/logger.go

This file was deleted.

30 changes: 0 additions & 30 deletions pkg/instrumentation/meter.go

This file was deleted.

Loading

0 comments on commit 3675457

Please sign in to comment.