diff --git a/go.mod b/go.mod index 15304c9..dd93825 100644 --- a/go.mod +++ b/go.mod @@ -11,26 +11,36 @@ require ( github.com/labstack/echo/v4 v4.13.4 github.com/markbates/goth v1.81.0 github.com/mattn/go-sqlite3 v1.14.29 - golang.org/x/crypto v0.40.0 - golang.org/x/net v0.41.0 - golang.org/x/oauth2 v0.30.0 + go.opentelemetry.io/otel v1.39.0 + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.15.0 + go.opentelemetry.io/otel/log v0.15.0 + go.opentelemetry.io/otel/sdk v1.39.0 + go.opentelemetry.io/otel/sdk/log v0.15.0 + golang.org/x/crypto v0.44.0 + golang.org/x/net v0.47.0 + golang.org/x/oauth2 v0.32.0 maragu.dev/gomponents v1.1.0 maragu.dev/gomponents-htmx v0.6.1 ) require ( ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 // indirect - cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/bmatcuk/doublestar v1.3.4 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/go-chi/chi/v5 v5.1.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/inflect v0.19.0 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/mux v1.6.2 // indirect github.com/gorilla/securecookie v1.1.2 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect github.com/hashicorp/hcl/v2 v2.18.1 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -43,9 +53,17 @@ require ( github.com/valyala/fasttemplate v1.2.2 // indirect github.com/zclconf/go-cty v1.14.4 // indirect github.com/zclconf/go-cty-yaml v1.1.0 // indirect - golang.org/x/mod v0.25.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.34.0 // indirect - golang.org/x/text v0.27.0 // indirect - golang.org/x/tools v0.34.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/otel/metric v1.39.0 // indirect + go.opentelemetry.io/otel/trace v1.39.0 // indirect + go.opentelemetry.io/proto/otlp v1.9.0 // indirect + golang.org/x/mod v0.29.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/text v0.31.0 // indirect + golang.org/x/tools v0.38.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/grpc v1.77.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect ) diff --git a/logger.go b/logger.go index 0fb6304..0416fa7 100644 --- a/logger.go +++ b/logger.go @@ -5,13 +5,23 @@ import ( "strings" ) +var ErstellerLogger *LoggerImpl + func LogDebug(message string, a ...any) { - println(fmt.Sprintf(message, a...)) + if ErstellerLogger == nil { + println(fmt.Sprintf(message, a...)) + return + } + ErstellerLogger.LogDebug(message, a...) } func Debug(a ...any) { - stringValue := joinStrings(a) - println(stringValue) + if ErstellerLogger == nil { + stringValue := joinStrings(a) + println(stringValue) + return + } + ErstellerLogger.Debug(a) } func joinStrings(a []any) string { @@ -24,9 +34,17 @@ func joinStrings(a []any) string { } func LogError(message string, a ...any) { - println(fmt.Sprintf("Error: %v", fmt.Sprintf(message, a...))) + if ErstellerLogger == nil { + println(fmt.Sprintf("Error: %v", fmt.Sprintf(message, a...))) + return + } + ErstellerLogger.LogError(message, a...) + } func Error(a ...any) { - println(fmt.Sprint("Error: ", joinStrings(a))) + if ErstellerLogger == nil { + println(fmt.Sprint("Error: ", joinStrings(a))) + } + ErstellerLogger.Error(a) } diff --git a/open_telemetry_logger.go b/open_telemetry_logger.go new file mode 100644 index 0000000..511e5cc --- /dev/null +++ b/open_telemetry_logger.go @@ -0,0 +1,113 @@ +package ersteller + +import ( + "context" + "fmt" + "time" + + "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc" + "go.opentelemetry.io/otel/log" + sdklog "go.opentelemetry.io/otel/sdk/log" + "go.opentelemetry.io/otel/sdk/resource" + semconv "go.opentelemetry.io/otel/semconv/v1.37.0" +) + +type LoggerImpl struct { + logger log.Logger +} + +func NewLoggerImpl(name string, version string) *LoggerImpl { + // Create an OTLP exporter + logExporter, err := otlploggrpc.New(context.Background()) + if err != nil { + // Fall back to stdout if exporter creation fails + Error("Failed to create OTLP log exporter:", err) + return &LoggerImpl{} + } + + // Create a resource that identifies your application + res, err := resource.Merge( + resource.Default(), + resource.NewWithAttributes( + semconv.SchemaURL, + semconv.ServiceName(name), + semconv.ServiceVersion(version), + ), + ) + if err != nil { + Error("Failed to create resource:", err) + return &LoggerImpl{} + } + + // Create a batch processor with the exporter + batchProcessor := sdklog.NewBatchProcessor(logExporter) + + // Create a logger provider with the processor + provider := sdklog.NewLoggerProvider( + sdklog.WithProcessor(batchProcessor), + sdklog.WithResource(res), + ) + + // Create a logger + logger := provider.Logger("salezenify.logger") + + return &LoggerImpl{ + logger: logger, + } +} + +func (l *LoggerImpl) Debug(a ...any) { + message := joinStrings(a) + // If logger is not initialized, fallback to standard output + if l.logger == nil { + println(message) + return + } + + // Use OpenTelemetry logger + ctx := context.Background() + + // Create a Record and emit it + record := log.Record{} + record.SetSeverity(log.SeverityDebug) + record.SetSeverityText("DEBUG") + record.SetBody(log.StringValue(message)) + record.SetTimestamp(time.Now()) + record.SetObservedTimestamp(time.Now()) + + l.logger.Emit(ctx, record) +} + +func (l *LoggerImpl) Error(a ...any) { + // If logger is not initialized, fallback to standard output + if l.logger == nil { + errorMessage := "Error: " + joinStrings(a) + println(errorMessage) + return + } + + // Use OpenTelemetry logger + ctx := context.Background() + message := joinStrings(a) + + // Create a Record and emit it + record := log.Record{} + record.SetSeverity(log.SeverityError) + record.SetSeverityText("ERROR") + record.SetBody(log.StringValue(message)) + record.SetTimestamp(time.Now()) + record.SetObservedTimestamp(time.Now()) + + l.logger.Emit(ctx, record) +} + +func (l *LoggerImpl) LogDebug(message string, a ...any) { + // If logger is not initialized, fallback to standard output + formattedMessage := fmt.Sprintf(message, a...) + l.Debug(formattedMessage) +} + +func (l *LoggerImpl) LogError(message string, a ...any) { + formattedMessage := fmt.Sprintf(message, a...) + l.Error(formattedMessage) +}