Home
Softono

Slog Otel

Open source Apache-2.0 Go
140
Stars
10
Forks
0
Issues
1
Watchers
7 months
Last Commit

 About Slog Otel

Go slog's Handler implementation to ensure correlation with Open-Telemetry spans.

Platforms

Web Self-hosted

Languages

Go

Links

Need Help Installing Slog Otel?

We provide expert installation service for this software. Our team will install, configure, and secure Slog Otel on your server. plans start at just $30.

slog-otel

Go Report Card codebeat badge GoDoc License

Go package that provides an implementation of log/slog's Handler interface that ensures a strong correlation between log records and Open-Telemetry spans by...

  1. Adding span and trace IDs to the log record.
  2. Adding context baggage members to the log record (can be disabled).
  3. Adding log record as span event (can be disabled).
  4. Adding log record attributes to the span event (can be disabled).
  5. Setting span status based on slog record level (only if >= slog.LevelError).

Usage

import (
    "context"
    "log/slog"

    "go.opentelemetry.io/otel/baggage"
    "go.opentelemetry.io/otel/trace"

    sdktrace "go.opentelemetry.io/otel/sdk/trace"
    slogotel "github.com/remychantenay/slog-otel"
)

// 1. Configure slog.
slog.SetDefault(slog.New(slogotel.OtelHandler{
    Next: slog.NewJSONHandler(os.Stdout, nil),
}))

// 2. Set up your logger.
logger := slog.Default()
logger = logger.With("component", "server")

// 3. (Optional) Add baggage to your context.
m1, _ := baggage.NewMember("key_1", "value_1")
m2, _ := baggage.NewMember("key_2", "value_2")
bag, _ := baggage.New(m1, m2)
ctx := baggage.ContextWithBaggage(context.Background(), bag)

// 4. Start your span.
ctx, span := tracer.Start(ctx, "operation-name")
defer span.End()

// 5. Log.
logger.InfoContext(ctx, "Hello world!", "locale", "en_US")

Example

The following initial log:

{
    "time": "2023-09-11T08:28:02.77215605Z",
    "level": "INFO",
    "component": "server",
    "msg": "Hello world!",
    "locale": "en_US"
}

... will be written as:

{
    "time": "2023-09-11T08:28:02.77215605Z",
    "level": "INFO",
    "component": "server",
    "msg": "Hello world!",
    "locale": "en_US",
    "trace_id": "a9938fd7a6313e0f27f3fc87f574bff6",
    "span_id": "ed58f84d8971bf60",
    "key_1": "value_1",
    "key_2": "value_2"
}

and the related span will look like:

 {
 	"Name": "GET /resources",
 	"SpanContext": {
 		"TraceID": "a9938fd7a6313e0f27f3fc87f574bff6",
 		"SpanID": "ed58f84d8971bf60",
 		...
 	},
 	"Parent": {
 		...
 	},
 	"SpanKind": 2,
 	"StartTime": "2023-09-11T08:28:02.761992425Z",
 	"EndTime": "2023-09-11T08:28:02.773230425Z",
 	"Attributes": [{
 			"Key": "http.method",
 			"Value": {
 				"Type": "STRING",
 				"Value": "GET"
 			}
 		},
		...
 	],
 	"Events": [{
 		"Name": "log_record",
 		"Attributes": [{
 				"Key": "msg",
 				"Value": {
 					"Type": "STRING",
 					"Value": "Hello world!"
 				}
 			},
 			{
 				"Key": "level",
 				"Value": {
 					"Type": "STRING",
 					"Value": "INFO"
 				}
 			},
 			{
 				"Key": "time",
 				"Value": {
 					"Type": "STRING",
 					"Value": "2023-09-11T08:28:02.77215605Z"
 				}
 			},
 			{
 				"Key": "locale",
 				"Value": {
 					"Type": "STRING",
 					"Value": "en_US"
 				}
 			},
 			{
 				"Key": "component",
 				"Value": {
 					"Type": "STRING",
 					"Value": "server"
 				}
 			}
 		],
 	}],
 	...
 }

License

Apache License Version 2.0