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 2 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
149 changes: 133 additions & 16 deletions content/en/docs/languages/go/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ way that [traces][] and [metrics][] are emitted to the console.

Ensure that you have the following installed locally:

- [Go](https://go.dev/)
- [Go](https://go.dev/) `1.22` or greater
MrAlias marked this conversation as resolved.
Show resolved Hide resolved

## Example application

Expand Down Expand Up @@ -135,9 +135,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 +189,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 +236,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 +342,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 +373,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 +409,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 +442,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 +613,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,11 +688,86 @@ 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
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.
Along with the trace, a log messages will be emitted to the console.
MrAlias marked this conversation as resolved.
Show resolved Hide resolved

<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 for a little bit or terminate the app and you'll see metrics as in
MrAlias marked this conversation as resolved.
Show resolved Hide resolved
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.

<details>
<summary>View example output</summary>
Expand Down Expand Up @@ -832,7 +949,7 @@ the instrumentation library.
"Key": "http.route",
"Value": {
"Type": "STRING",
"Value": "/rolldice"
"Value": "/rolldice/Alice"
}
},
{
Expand Down Expand Up @@ -899,7 +1016,7 @@ the instrumentation library.
"Key": "http.route",
"Value": {
"Type": "STRING",
"Value": "/rolldice"
"Value": "/rolldice/Alice"
}
},
{
Expand Down Expand Up @@ -966,7 +1083,7 @@ the instrumentation library.
"Key": "http.route",
"Value": {
"Type": "STRING",
"Value": "/rolldice"
"Value": "/rolldice/Alice"
}
},
{
Expand Down