Skip to content

Commit b673f39

Browse files
committed
Add OTEL instrumentation docs for Go
Signed-off-by: Han Verstraete (OpenFaaS Ltd) <[email protected]>
1 parent 8342185 commit b673f39

File tree

3 files changed

+122
-2
lines changed

3 files changed

+122
-2
lines changed

docs/edge/open-telemetry.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,4 @@ Checkout the docs for more details on [how to configure Grafana Alloy to collect
7676

7777
Functions and services deployed on OpenFaaS Edge can use the service name when configuring the telemetry collection endpoint e,g. `alloy:4317` or `alloy:4318`.
7878

79-
For more info on how to instrument and configure telemetry for functions checkout our language guides for: [Python](/languages/python/#opentelemetry-zero-code-instrumentation) or [Node.js](/languages/node/#opentelemetry-zero-code-instrumentation).
79+
For more info on how to instrument and configure telemetry for functions checkout our language guides for: [Python](/languages/python/#opentelemetry-zero-code-instrumentation), [Node.js](/languages/node/#opentelemetry-zero-code-instrumentation) or [Go](/languages/go/#opentelemetry-instrumentation)

docs/languages/go.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,3 +406,123 @@ func Handle(w http.ResponseWriter, r *http.Request) {
406406
}
407407
```
408408

409+
## OpenTelemetry instrumentation
410+
411+
We have a separate golang template `golang-otel` that has built-in support OpenTelemetry traces. The template is based on the `golang-middleware` template and allows you to get traces for Golang functions with minimal code changes.
412+
413+
Some of the key benefits of using the `golang-otel` template are:
414+
415+
- **No boilerplate** - Avoid boilerplate code to configure providers and traces in Go functions. No need to fork and maintain your own version of the golang templates.
416+
- **Configuration using environment variables** - Simplify configuration with environment-based settings, reducing the need for code changes.
417+
- **HTTP instrumentation** - Incoming HTTP requests to the function handler are automatically instrumented.
418+
- **Extensibility with custom traces** - Easily add custom spans using the [OpenTelemetry Go Trace API](https://pkg.go.dev/go.opentelemetry.io/otel) without much boilerplate code.
419+
420+
Create a new function with the `golang-otel` template:
421+
422+
```sh
423+
faas-cli new echo --lang golang-otel
424+
```
425+
426+
Use environment variables to configure the traces exporter for the function.
427+
428+
```diff
429+
functions:
430+
echo:
431+
lang: golang-otel
432+
handler: ./echo
433+
image: echo:latest
434+
+ environment:
435+
+ OTEL_TRACES_EXPORTER: console,otlp
436+
+ OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-collector:4317}
437+
```
438+
439+
The `golang-otel` template supports a subset of [OTEL SDK environment variables](https://opentelemetry.io/docs/languages/sdk-configuration/) to configure the exporter.
440+
441+
- `OTEL_TRACES_EXPORTER` specifies which tracer exporter to use. In this example traces are exported to `console` (stdout) and with `otlp` to send traces to an endpoint that accepts OTLP via gRPC.
442+
- `OTEL_EXPORTER_OTLP_ENDPOINT` sets the endpoint where telemetry is exported to.
443+
- `OTEL_SERVICE_NAME` sets the name of the service associated with the telemetry and is used to identify telemetry for a specific function. By default `<fn-name>.<fn-namespace>` is used as the service name on Kubernetes or `<fn-name>` when running the function with OpenFaaS Edge, or locally with `faas-cli local-run`.
444+
- `OTEL_EXPORTER_OTLP_TRACES_INSECURE` can be set to true to disable TLS if that is not supported by the OpenTelemetry collector.
445+
446+
The template can be used as a drop-in replacement for functions that already use the `golang-middleware` template to get HTTP invocation traces for your existing functions without any code changes. All that is required is to change the `lang` field in the `stack.yaml` configuration.
447+
448+
```diff
449+
version: 1.0
450+
provider:
451+
name: openfaas
452+
gateway: http://127.0.0.1:8080
453+
functions:
454+
echo:
455+
- lang: golang-middleware
456+
+ lang: golang-otel
457+
handler: ./echo
458+
image: echo:latest
459+
```
460+
461+
### Creating custom traces in the function handler
462+
463+
here may be cases where an instrumentation library is not available or you may want to add custom tracing data for some of your own functions and methods.
464+
465+
When using the `golang-otel` template the registered global trace provider can be retrieved to add custom spans in the function handler. A span represents a unit of work or operation. Spans are the building blocks of traces.
466+
467+
> Check out the [OpenTelemetry docs](https://opentelemetry.io/docs/languages/go/instrumentation/#creating-spans) for more information on how to work with spans.
468+
469+
On your code you can call the [otel.Tracer](https://pkg.go.dev/go.opentelemetry.io/otel#Tracer) function to get a named tracer and start a new span.
470+
471+
Make sure to add the required packages to the function handler:
472+
473+
```sh
474+
go get "go.opentelemetry.io/otel"
475+
```
476+
477+
Add custom spans in the function handler:
478+
479+
```go
480+
package function
481+
482+
import (
483+
"fmt"
484+
"io"
485+
"net/http"
486+
"sync"
487+
488+
"go.opentelemetry.io/otel"
489+
)
490+
491+
func callOpenAI(ctx context.Context, input []byte) {
492+
// Get a tracer and create a new span
493+
ctx, span := otel.Tracer("function").Start(ctx, "call-openAI")
494+
defer span.End()
495+
496+
// Sleep for 2 seconds to simulate some work.
497+
time.Sleep(time.Second * 2)
498+
}
499+
500+
501+
func Handle(w http.ResponseWriter, r *http.Request) {
502+
var input []byte
503+
504+
if r.Body != nil {
505+
defer r.Body.Close()
506+
507+
body, _ := io.ReadAll(r.Body)
508+
509+
input = body
510+
}
511+
512+
// Call function with the request context to pass on any parent spans.
513+
callOpenAI(r.Context(), input)
514+
515+
w.WriteHeader(http.StatusOK)
516+
fmt.Fprintf(w, "Done processing.")
517+
}
518+
```
519+
520+
To create a new span with a tracer, you’ll need a handle on a `context.Context` instance. These will typically come from the request object and may already contain a parent span from an [instrumentation library](https://opentelemetry.io/docs/languages/go/libraries/).
521+
522+
You can now add [attributes](https://opentelemetry.io/docs/languages/go/instrumentation/#span-attributes) and [events](https://opentelemetry.io/docs/languages/go/instrumentation/#events), [set the status](https://opentelemetry.io/docs/languages/go/instrumentation/#set-span-status) and [record errors](https://opentelemetry.io/docs/languages/go/instrumentation/#record-errors) on the span as required.
523+
524+
## OpenTelemetry zero-code instrumentation
525+
526+
The beta Release for [zero-code instrumentation](https://opentelemetry.io/docs/concepts/instrumentation/zero-code/) of Go applications [has recently been announced](https://opentelemetry.io/blog/2025/go-auto-instrumentation-beta/).
527+
528+
Go auto-instrumentation has not been tested with OpenFaaS functions yet. The easiest way to try it out on Kubernetes is probably by using the [Opentelemetry Operator for Kubernetes](https://opentelemetry.io/docs/platforms/kubernetes/operator/automatic/).

docs/languages/python.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ functions:
446446
+ OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-collector:4317}
447447
```
448448

449-
- `OTEL_SERVICE_NAME` sets the name of the service associated with the telemetry and is used to identify telemetry for a specific function. It can be set to any value you want be we recommend using the clear function identifier `<fn-name>.<fn-namespace>`.
449+
- `OTEL_SERVICE_NAME` sets the name of the service associated with the telemetry and is used to identify telemetry for a specific function. It can be set to any value you want but we recommend using the clear function identifier `<fn-name>.<fn-namespace>`.
450450
- `OTEL_TRACES_EXPORTER` specifies which tracer exporter to use. In this example traces are exported to `console` (stdout) and with `otlp`. The `otlp` option tells `opentelemetry-instrument` to send the traces to an endpoint that accepts OTLP via gRPC.
451451
- setting `OTEL_METRICS_EXPORTER` and `OTEL_LOGS_EXPORTER` to `none` we disable the metrics and logs exporters. You can enable them if desired.
452452
- `OTEL_EXPORTER_OTLP_ENDPOINT` sets the endpoint where telemetry is exported to.

0 commit comments

Comments
 (0)