Skip to content

Commit

Permalink
fix tracing otel sdk example
Browse files Browse the repository at this point in the history
  • Loading branch information
8naama committed Dec 19, 2024
1 parent cf9f44d commit 12ea906
Showing 1 changed file with 70 additions and 135 deletions.
205 changes: 70 additions & 135 deletions docs/shipping/Code/go.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ if err != nil {
l.Stop() // Drains the log buffer
```


## Metrics

:::note
Expand Down Expand Up @@ -502,185 +503,121 @@ Encounter an issue? See our [log shipping troubleshooting](https://docs.logz.io/
</TabItem>
</Tabs>


## Traces

<Tabs>
<TabItem value="opentelemetry" label="OpenTelemetry" default>

Deploy this integration to enable instrumentation of your Go application using OpenTelemetry.

### Manual configuration

This integration includes:

* Installing the OpenTelemetry Go instrumentation packages on your application host
* Installing the OpenTelemetry collector with Logz.io exporter
* Running your Go application in conjunction with the OpenTelemetry instrumentation

On deployment, the Go instrumentation automatically captures spans from your application and forwards them to the collector, which exports the data to your Logz.io account.


### Auto Instrumentation

Deploy this integration to enable instrumentation of your Go application using OpenTelemetry.

#### Setup instrumentation for your locally hosted Go application and send traces to Logz.io

**Before you begin, you'll need**:

* A Go application without instrumentation
* An active Logz.io account
* Port `4318` available on your host system
* A name defined for your tracing service. You will need it to identify the traces in Logz.io.


:::note
This integration uses OpenTelemetry Collector Contrib, not the OpenTelemetry Collector Core.
:::




##### Download the general instrumentation packages

These packages are required to enable instrumentation for your code regardless of the type of application that you need to instrument.

To download these packages, run the following command from the application directory:
#### Install dependencies

```shell
go get -u go.opentelemetry.io/otel
go get -u go.opentelemetry.io/otel/exporters/otlp
go get -u go.opentelemetry.io/otel
go get -u go.opentelemetry.io/otel/attribute
go get -u go.opentelemetry.io/otel/baggage
go get -u go.opentelemetry.io/otel/propagation
go get -u go.opentelemetry.io/otel/sdk/resource
go get -u go.opentelemetry.io/otel/sdk/trace
go get -u go.opentelemetry.io/otel/semconv/v1.4.0
go get -u go.opentelemetry.io/otel/trace
go get -u go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
go get -u go.opentelemetry.io/otel/sdk/trace
go get -u go.opentelemetry.io/otel/semconv/v1.26.0
```

#### Setup Tracer Provider
Create a new file `otel.go` and place the below code in it:

:::note
We recommend sending OTLP traces using HTTP. This is why we import the `otlptracehttp` package.
Change `<<SERVICE-NAME>>` to your own service name.
:::


##### Download the application specific instrumentation packages

Depending on the type of your application, you need to download instrumentation packages specific to your application. For example, if your application is a HTTP server, you will need the `opentelemetry.io/contrib/instrumentation/net/http/otelhttp` package. The full list of all available packages can be found in the [OpenTelemetry contrib directory](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/v0.22.0/instrumentation).

The example below is given for a HTTP server application:

```shell
go get -u go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
```

##### Add the instrumentation to the `import` function

Add all the packages downloaded in the previous steps to the `import` function of your application.

The example below is given for a HTTP server application:

```go
import (
"context"
"io"
"log"
"net/http"

"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"

"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/baggage"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
"go.opentelemetry.io/otel/trace"
"log"

"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
)
```

##### Add the `initProvider` function


Add the `initProvider` function to the application code as follows:

```go
func initProvider() func() {
ctx := context.Background()

res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceNameKey.String("test-service"),
func newTraceProvider() (*sdktrace.TracerProvider, error) {
// Ensure default SDK resources and the required service name are set.
r, err := resource.Merge(
resource.Default(),
resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName("<<SERVICE-NAME>>"),
),
)
handleErr(err, "failed to create resource")
if err != nil {
return nil, err
}

traceExporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithInsecure(),
exp, _ := otlptracehttp.New(context.Background(),
otlptracehttp.WithEndpoint("localhost:4318"),
)
handleErr(err, "failed to create trace exporter")
otlptracehttp.WithInsecure())

bsp := sdktrace.NewBatchSpanProcessor(traceExporter)
tracerProvider := sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.AlwaysSample()),
sdktrace.WithResource(res),
sdktrace.WithSpanProcessor(bsp),
)
otel.SetTracerProvider(tracerProvider)
otel.SetTextMapPropagator(propagation.TraceContext{})
return func() {
handleErr(tracerProvider.Shutdown(ctx), "failed to shutdown TracerProvider")
}
return sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exp),
sdktrace.WithResource(r),
), nil
}
```

##### Instrument the code in the `main` function
// setupOTelSDK bootstraps the OpenTelemetry logging pipeline.
func setupOTelSDK(ctx context.Context) (shutdown func(context.Context) error, err error) {
// setup trace provider
traceProvider, err := newTraceProvider()
if err != nil {
return nil, err
}

In the `main` function of your application, add the following code:
otel.SetTracerProvider(traceProvider)
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
propagation.TraceContext{}, propagation.Baggage{}))

// Return a shutdown function
shutdown = func(ctx context.Context) error {
err := traceProvider.Shutdown(ctx)
if err != nil {
log.Printf("Error during tracer provider shutdown: %v", err)
}
return err
}

```go
shutdown := initProvider()
defer shutdown()
return shutdown, nil
}
```

After this, you need to declare the instrumentation according to your application. The example below is given for a HTTP server application. The HTTP handler instructs the tracer to create spans on each request.
#### Call Tracer Provider from main function
Make sure the application will setup the instrumentation by calling `setupOTelSDK()` that was created in the previous step from your main function.

```go
uk := attribute.Key("username")

helloHandler := func(w http.ResponseWriter, req *http.Request) {
ctx := req.Context()
span := trace.SpanFromContext(ctx)
bag := baggage.FromContext(ctx)
span.AddEvent("handling this...", trace.WithAttributes(uk.String(bag.Member("username").Value())))

_, _ = io.WriteString(w, "Hello, world!\n")
}

otelHandler := otelhttp.NewHandler(http.HandlerFunc(helloHandler), "Hello")

http.Handle("/hello", otelHandler)
err := http.ListenAndServe(":7777", nil)
if err != nil {
panic(err)
}
// Set up OpenTelemetry.
otelShutdown, err := setupOTelSDK(ctx)
if err != nil {
return
}
func handleErr(err error, message string) {
if err != nil {
log.Fatalf("%s: %v", message, err)
}
// Handle shutdown properly so nothing leaks.
defer func() {
err = errors.Join(err, otelShutdown(context.Background()))
}()
```

#### Setup OpenTelemetry Collector

##### Download and configure OpenTelemetry collector
Create a dedicated directory on the host of your Go application and download the [OpenTelemetry collector](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases/tag/v0.70.0) that is relevant to the operating system of your host.
Create a dedicated directory on the host of your Go application and download the [OpenTelemetry collector](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases/tag/v0.116.0) that is relevant to the operating system of your host.

After downloading the collector, create a configuration file `config.yaml` with the following parameters:

Expand All @@ -689,8 +626,7 @@ After downloading the collector, create a configuration file `config.yaml` with
{@include: ../../_include/tracing-shipping/replace-tracing-token.html}


##### Start the collector
#### Start OpenTelemetry Collector
Run the following command from the directory of your application file:

```shell
Expand All @@ -699,18 +635,17 @@ Run the following command from the directory of your application file:
* Replace `<path/to>` with the path to the directory where you downloaded the collector.
* Replace `<VERSION-NAME>` with the version name of the collector applicable to your system, e.g. `otelcontribcol_darwin_amd64`.

##### Run the application

Run the application to generate traces:
##### Check Logz.io for your traces

```shell
go run <YOUR-APPLICATION-FILE-NAME>.go
```
Run the application after building it with the new Instrumentation.
Give your traces some time to get from your system to ours, and then open [Tracing](https://app.logz.io/#/dashboard/jaeger).


##### Check Logz.io for your traces
### Manual Instrumentation

If you're using specific libararies and want to be specific or precise with instrumentation, you can opt to[instrument your code manually](https://opentelemetry.io/docs/languages/go/instrumentation/#traces).

Give your traces some time to get from your system to ours, and then open [Tracing](https://app.logz.io/#/dashboard/jaeger).

</TabItem>
<TabItem value="lambda-otel" label="Lambda via OpenTelemetry">
Expand Down

0 comments on commit 12ea906

Please sign in to comment.