diff --git a/content/en/docs/languages/go/getting-started.md b/content/en/docs/languages/go/getting-started.md index 768eb94403ad..3a044b22f6a6 100644 --- a/content/en/docs/languages/go/getting-started.md +++ b/content/en/docs/languages/go/getting-started.md @@ -11,13 +11,20 @@ cSpell:ignore: chan fatalln funcs intn itoa khtml otelhttp rolldice stdouttrace This page will show you how to get started with OpenTelemetry in Go. You will learn how you can instrument a simple application manually, in such a -way that [traces][] and [metrics][] are emitted to the console. +way that [traces][], [metrics][], and [logs][] are emitted to the console. + +{{% alert title="Note" %}} + +The logs signal is still experimental. Breaking changes may be introduced in +future versions. + +{{% /alert %}} ## Prerequisites Ensure that you have the following installed locally: -- [Go](https://go.dev/) +- [Go](https://go.dev/) 1.22 or greater ## Example application @@ -135,9 +142,12 @@ import ( "time" "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/stdout/stdoutlog" "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" + "go.opentelemetry.io/otel/log/global" "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/log" "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/trace" ) @@ -186,6 +196,15 @@ func setupOTelSDK(ctx context.Context) (shutdown func(context.Context) error, er shutdownFuncs = append(shutdownFuncs, meterProvider.Shutdown) otel.SetMeterProvider(meterProvider) + // Set up logger provider. + loggerProvider, err := newLoggerProvider() + if err != nil { + handleErr(err) + return + } + shutdownFuncs = append(shutdownFuncs, loggerProvider.Shutdown) + global.SetLoggerProvider(loggerProvider) + return } @@ -224,6 +243,18 @@ func newMeterProvider() (*metric.MeterProvider, error) { ) return meterProvider, nil } + +func newLoggerProvider() (*log.LoggerProvider, error) { + logExporter, err := stdoutlog.New() + if err != nil { + return nil, err + } + + loggerProvider := log.NewLoggerProvider( + log.WithProcessor(log.NewBatchProcessor(logExporter)), + ) + return loggerProvider, nil +} ``` @@ -318,7 +349,8 @@ func newHTTPHandler() http.Handler { } // Register handlers. - handleFunc("/rolldice", rolldice) + handleFunc("/rolldice/", rolldice) + handleFunc("/rolldice/{player}", rolldice) // Add HTTP instrumentation for the whole server. handler := otelhttp.NewHandler(mux, "/") @@ -348,14 +380,23 @@ import ( "net/http" "strconv" + "go.opentelemetry.io/contrib/bridges/otelslog" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/sdk/instrumentation" ) +const name = "rolldice" + var ( - tracer = otel.Tracer("rolldice") - meter = otel.Meter("rolldice") + tracer = otel.Tracer(name) + meter = otel.Meter(name) + logger = otelslog.NewLogger( + otelslog.WithInstrumentationScope(instrumentation.Scope{ + Name: name, + }), + ) rollCnt metric.Int64Counter ) @@ -375,6 +416,14 @@ func rolldice(w http.ResponseWriter, r *http.Request) { roll := 1 + rand.Intn(6) + var msg string + if player := r.PathValue("player"); player != "" { + msg = fmt.Sprintf("%s is rolling the dice", player) + } else { + msg = "Anonymous player is rolling the dice" + } + logger.InfoContext(ctx, msg, "result", roll) + rollValueAttr := attribute.Int("roll.value", roll) span.SetAttributes(rollValueAttr) rollCnt.Add(ctx, 1, metric.WithAttributes(rollValueAttr)) @@ -400,11 +449,11 @@ export OTEL_RESOURCE_ATTRIBUTES="service.name=dice,service.version=0.1.0" go run . ``` -Open in your web browser. When you send a +Open in your web browser. When you send a request to the server, you'll see two spans in the trace emitted to the console. The span generated by the instrumentation library tracks the lifetime of a -request to the `/rolldice` route. The span called `roll` is created manually and -it is a child of the previously mentioned span. +request to the `/rolldice/{player}` route. The span called `roll` is created +manually and it is a child of the previously mentioned span.
View example output @@ -571,7 +620,7 @@ it is a child of the previously mentioned span. "Key": "http.route", "Value": { "Type": "STRING", - "Value": "/rolldice" + "Value": "/rolldice/Alice" } }, { @@ -646,8 +695,83 @@ it is a child of the previously mentioned span.
-Refresh the page a few times, and then either -wait for a little bit or terminate the app and you'll see metrics as in the +Along with the trace, log messages are emitted to the console. + +
+View example output + +```json +{ + "Timestamp": "2023-09-25T12:42:05.177136776+02:00", + "ObservedTimestamp": "2023-09-25T12:42:06.809396011+02:00", + "Severity": 9, + "SeverityText": "", + "Body": { + "Type": "String", + "Value": "Alice is rolling the dice" + }, + "Attributes": [ + { + "Key": "result", + "Value": { + "Type": "Int64", + "Value": 6 + } + } + ], + "TraceID": "829fb7ceb787403c96eac3caf285c965", + "SpanID": "8b6b408b6c1a35e5", + "TraceFlags": "01", + "Resource": [ + { + "Key": "service.name", + "Value": { + "Type": "STRING", + "Value": "dice" + } + }, + { + "Key": "service.version", + "Value": { + "Type": "STRING", + "Value": "0.1.0" + } + }, + { + "Key": "telemetry.sdk.language", + "Value": { + "Type": "STRING", + "Value": "go" + } + }, + { + "Key": "telemetry.sdk.name", + "Value": { + "Type": "STRING", + "Value": "opentelemetry" + } + }, + { + "Key": "telemetry.sdk.version", + "Value": { + "Type": "STRING", + "Value": "1.19.0-rc.1" + } + } + ], + "Scope": { + "Name": "rolldice", + "Version": "", + "SchemaURL": "" + }, + "DroppedAttributes": 0 +} +``` + +
+ +Refresh the page a few times, and then +either wait a little or terminate the app and you'll see metrics as in the console output. You'll see the `dice.rolls` metric emitted to the console, with separate counts for each roll value, as well as the HTTP metrics generated by the instrumentation library. @@ -832,7 +956,7 @@ the instrumentation library. "Key": "http.route", "Value": { "Type": "STRING", - "Value": "/rolldice" + "Value": "/rolldice/Alice" } }, { @@ -899,7 +1023,7 @@ the instrumentation library. "Key": "http.route", "Value": { "Type": "STRING", - "Value": "/rolldice" + "Value": "/rolldice/Alice" } }, { @@ -966,7 +1090,7 @@ the instrumentation library. "Key": "http.route", "Value": { "Type": "STRING", - "Value": "/rolldice" + "Value": "/rolldice/Alice" } }, { @@ -1041,3 +1165,4 @@ If you'd like to explore a more complex example, take a look at the [traces]: /docs/concepts/signals/traces/ [metrics]: /docs/concepts/signals/metrics/ +[logs]: /docs/concepts/signals/logs/