diff --git a/example/main.go b/example/main.go index 860dedf..e4b4576 100644 --- a/example/main.go +++ b/example/main.go @@ -10,8 +10,7 @@ import ( "git.ma-al.com/gora_filip/observer/pkg/tracer" "git.ma-al.com/gora_filip/pkg/attr" - "git.ma-al.com/gora_filip/pkg/combined_exporter" - "git.ma-al.com/gora_filip/pkg/console_exporter" + "git.ma-al.com/gora_filip/pkg/exporters" "git.ma-al.com/gora_filip/pkg/fiber_tracing" "git.ma-al.com/gora_filip/pkg/level" "github.com/gofiber/fiber/v2" @@ -26,19 +25,17 @@ func main() { StreamRequestBody: true, }) - lvl := level.DEBUG - exporter := combined_exporter.NewExporter( - console_exporter.NewExporter( - console_exporter.ExporterOptions{ - FilterOnLevel: &lvl, - //EmitOnlyOnError: true, - }, - )) + exps := make([]exporters.ExporterWithConfig, 2) + exps = append(exps, exporters.DevConsoleExporter()) + gelfExp, err := exporters.GelfExporter() + if err == nil { + exps = append(exps, gelfExp) + } main.Use(fiber_tracing.NewMiddleware(fiber_tracing.Config{ AppName: "example", Version: "0.0.0", ServiceProvider: "maal", - Exporter: exporter, + Exporters: exps, })) defer fiber_tracing.ShutdownTracer() diff --git a/pkg/combined_exporter/combined_exporter.go b/pkg/combined_exporter/combined_exporter.go deleted file mode 100644 index ff2249b..0000000 --- a/pkg/combined_exporter/combined_exporter.go +++ /dev/null @@ -1,40 +0,0 @@ -package combined_exporter - -import ( - "context" - "fmt" - "go.opentelemetry.io/otel/sdk/trace" -) - -type Exporter struct { - exporters []trace.SpanExporter -} - -func NewExporter(exporters ...trace.SpanExporter) trace.SpanExporter { - return &Exporter{ - exporters: exporters, - } -} - -// Implements [trace.SpanExporter] -func (e *Exporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan) error { - for _, exp := range e.exporters { - exp.ExportSpans(ctx, spans) - } - return nil -} - -// Implements [trace.SpanExporter] -func (e *Exporter) Shutdown(ctx context.Context) error { - var errs []error - for _, exp := range e.exporters { - err := exp.Shutdown(ctx) - if err != nil { - errs = append(errs, err) - } - } - if len(errs) > 0 { - return fmt.Errorf("multiple erros have occured: %#v", errs) - } - return nil -} diff --git a/pkg/console_exporter/console_exporter.go b/pkg/exporters/console_exporter/console_exporter.go similarity index 87% rename from pkg/console_exporter/console_exporter.go rename to pkg/exporters/console_exporter/console_exporter.go index ea8262a..e7c228e 100644 --- a/pkg/console_exporter/console_exporter.go +++ b/pkg/exporters/console_exporter/console_exporter.go @@ -46,6 +46,21 @@ type Exporter struct { stopped bool } +// NOTE: The configuration might change in future releases +func DefaultConsoleExporter() trace.SpanExporter { + lvl := level.DEBUG + fmt := NewEventsOnlyFormatter() + return NewExporter(ExporterOptions{ + FilterFromEnvVar: nil, + FilterOnLevel: &lvl, + FilterOutFields: []attribute.Key{}, + EmitEventsOnly: false, + EmitTraceId: true, + EmitOnlyOnError: false, + TraceFormatter: &fmt, + }) +} + func NewExporter(opts ExporterOptions) trace.SpanExporter { var formatter TraceFormatter var lvl level.SeverityLevel diff --git a/pkg/console_exporter/event_only_formatter.go b/pkg/exporters/console_exporter/event_only_formatter.go similarity index 97% rename from pkg/console_exporter/event_only_formatter.go rename to pkg/exporters/console_exporter/event_only_formatter.go index ea90baa..34827d4 100644 --- a/pkg/console_exporter/event_only_formatter.go +++ b/pkg/exporters/console_exporter/event_only_formatter.go @@ -14,6 +14,10 @@ import ( "go.opentelemetry.io/otel/semconv/v1.25.0" ) +func NewEventsOnlyFormatter() TraceFormatter { + return &EventsOnlyFormatter{} +} + // A formatter that will print only events using a multiline format with colors. // It uses attributes from the [attr] and [semconv] packages. type EventsOnlyFormatter struct{} diff --git a/pkg/exporters/exporters.go b/pkg/exporters/exporters.go new file mode 100644 index 0000000..6fc138d --- /dev/null +++ b/pkg/exporters/exporters.go @@ -0,0 +1,58 @@ +package exporters + +import ( + "context" + "time" + + "git.ma-al.com/gora_filip/pkg/exporters/console_exporter" + gelf_exporter "git.ma-al.com/gora_filip/pkg/exporters/gelf_exporter" + otlphttp_exporter "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +func NewWithConfig(exporter sdktrace.SpanExporter) ExporterWithConfig { + return ExporterWithConfig{ + exporter: exporter, + } +} + +// Combined exporter with batch processor config +type ExporterWithConfig struct { + exporter sdktrace.SpanExporter + config []sdktrace.BatchSpanProcessorOption +} + +func (ecfg ExporterWithConfig) Add(opt sdktrace.BatchSpanProcessorOption) ExporterWithConfig { + ecfg.config = append(ecfg.config, opt) + return ecfg +} + +func (ecfg ExporterWithConfig) IntoTraceProviderOption() sdktrace.TracerProviderOption { + return sdktrace.WithBatcher(ecfg.exporter, ecfg.config...) +} + +// An exporter printing to console with very small delay +func DevConsoleExporter(opts ...console_exporter.ExporterOptions) ExporterWithConfig { + batchTimeout := (time.Millisecond * 250) + exportTimeout := (time.Millisecond * 250) + var exporter ExporterWithConfig + if len(opts) > 0 { + exporter = NewWithConfig(console_exporter.NewExporter(opts[0])) + } else { + exporter = NewWithConfig(console_exporter.DefaultConsoleExporter()) + } + return exporter.Add(sdktrace.WithBatchTimeout(batchTimeout)).Add(sdktrace.WithExportTimeout(exportTimeout)) +} + +// Default exporter to Graylog. +func GelfExporter(opts ...gelf_exporter.Option) (ExporterWithConfig, error) { + gelfExp, err := gelf_exporter.New(opts...) + return NewWithConfig(gelfExp), err +} + +// Exporter for traces over HTTP. Can be used with Jaeger. +// See documentation of [otlhttp_exporter] for details. +func OtlpHTTPExporter(opts ...otlphttp_exporter.Option) (ExporterWithConfig, error) { + otlpExp, err := otlphttp_exporter.New(context.Background(), opts...) + return NewWithConfig(otlpExp), err +} diff --git a/pkg/gelf_exporter/config.go b/pkg/exporters/gelf_exporter/config.go similarity index 100% rename from pkg/gelf_exporter/config.go rename to pkg/exporters/gelf_exporter/config.go diff --git a/pkg/gelf_exporter/gelf.go b/pkg/exporters/gelf_exporter/gelf.go similarity index 100% rename from pkg/gelf_exporter/gelf.go rename to pkg/exporters/gelf_exporter/gelf.go diff --git a/pkg/gelf_exporter/trace.go b/pkg/exporters/gelf_exporter/trace.go similarity index 100% rename from pkg/gelf_exporter/trace.go rename to pkg/exporters/gelf_exporter/trace.go diff --git a/pkg/fiber_tracing/fiber_tracing.go b/pkg/fiber_tracing/fiber_tracing.go index ed5f117..177a2d3 100644 --- a/pkg/fiber_tracing/fiber_tracing.go +++ b/pkg/fiber_tracing/fiber_tracing.go @@ -4,6 +4,7 @@ import ( "context" "log" + "git.ma-al.com/gora_filip/pkg/exporters" "github.com/gofiber/fiber/v2" fiberOpentelemetry "github.com/psmarcin/fiber-opentelemetry/pkg/fiber-otel" "go.opentelemetry.io/otel" @@ -20,10 +21,11 @@ var ( ) type Config struct { - AppName string - Version string + AppName string + Version string + // Name of an organization providing the service ServiceProvider string - Exporter trc.SpanExporter + Exporters []exporters.ExporterWithConfig } func newResource(config Config) *resource.Resource { @@ -39,7 +41,9 @@ func newResource(config Config) *resource.Resource { func NewMiddleware(config Config) func(*fiber.Ctx) error { var tracerProviders []trc.TracerProviderOption - tracerProviders = append(tracerProviders, trc.WithBatcher(config.Exporter)) + for _, exp := range config.Exporters { + tracerProviders = append(tracerProviders, exp.IntoTraceProviderOption()) + } tracerProviders = append(tracerProviders, trc.WithResource(newResource(config))) TP = *trc.NewTracerProvider(tracerProviders...)