Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add logging to Go getting-started example #4490

Merged
merged 6 commits into from
May 16, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 139 additions & 14 deletions content/en/docs/languages/go/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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"
)
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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
}
```
<!-- prettier-ignore-end -->

Expand Down Expand Up @@ -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, "/")
Expand Down Expand Up @@ -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
)

Expand All @@ -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))
Expand All @@ -400,11 +449,11 @@ export OTEL_RESOURCE_ATTRIBUTES="service.name=dice,service.version=0.1.0"
go run .
```

Open <http://localhost:8080/rolldice> in your web browser. When you send a
Open <http://localhost:8080/rolldice/Alice> 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.

<details>
<summary>View example output</summary>
Expand Down Expand Up @@ -571,7 +620,7 @@ it is a child of the previously mentioned span.
"Key": "http.route",
"Value": {
"Type": "STRING",
"Value": "/rolldice"
"Value": "/rolldice/Alice"
}
},
{
Expand Down Expand Up @@ -646,8 +695,83 @@ it is a child of the previously mentioned span.

</details>

Refresh the <http://localhost:8080/rolldice> 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.

<details>
<summary>View example output</summary>

```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
}
```

</details>

Refresh the <http://localhost:8080/rolldice/Alice> 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.
Expand Down Expand Up @@ -832,7 +956,7 @@ the instrumentation library.
"Key": "http.route",
"Value": {
"Type": "STRING",
"Value": "/rolldice"
"Value": "/rolldice/Alice"
}
},
{
Expand Down Expand Up @@ -899,7 +1023,7 @@ the instrumentation library.
"Key": "http.route",
"Value": {
"Type": "STRING",
"Value": "/rolldice"
"Value": "/rolldice/Alice"
}
},
{
Expand Down Expand Up @@ -966,7 +1090,7 @@ the instrumentation library.
"Key": "http.route",
"Value": {
"Type": "STRING",
"Value": "/rolldice"
"Value": "/rolldice/Alice"
}
},
{
Expand Down Expand Up @@ -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/