Skip to main content

Send Telemetry to Datadog from WebAssembly in Go

Observability in Datadog from WebAssembly

Overview

Enables the extraction of traces/spans from Wasm modules executing in a Golang program/application and emits them to a Datadog agent.

Installation

Install the Datadog adapter from GitHub:

go get github.com/dylibso/observe-sdk/go/adapter/datadog@latest

Example

A basic Go program that loads a Wasm module and executes it using the Wazero WebAssembly runtime.

package main

import (
"bytes"
"context"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"

"github.com/dylibso/observe-sdk/go/adapter/datadog"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
)

func main() {
// create a context
ctx := context.Background()

// create a new Datadog Adapater with config
// the default config assumes you have a datadog agent running on localhost
ddconf := datadog.DefaultDatadogConfig()
adapter := datadog.NewDatadogAdapter(ddconf)

// start the Observe SDK adapter
adapter.Start(ctx)
defer adapter.Stop(true)


// load some Wasm from disk
wasm, err := os.ReadFile(os.Args[1])
if err != nil {
log.Panicln(err)
}

// setup a new Wazero runtime with config
wacfg := wazero.NewRuntimeConfig().WithCustomSections(true)
rt := wazero.NewRuntimeWithConfig(ctx, wacfg)

// apply the Observe SDK adapter to the Wazero runtime
traceCtx, err := adapter.NewTraceCtx(ctx, rt, wasm, nil)
if err != nil {
log.Panicln(err)
}

wasi_snapshot_preview1.MustInstantiate(ctx, rt)

// create a new Wazero configuration
modconfig := wazero.NewModuleConfig().
WithStdin(os.Stdin).
WithStdout(os.Stdout).
WithStderr(os.Stderr).
WithArgs(os.Args[1:]...).
WithStartFunctions("_start")

// instantiate the Wasm module
mod, err := rt.InstantiateWithConfig(ctx, wasm, modconfig)
if err != nil {
log.Println("module instance error:", err)
return
}
defer mod.Close(ctx)

// setup some test metadata for Datadog to associate with the trace
resourceName := "my-resource"
httpUrl := "https://example.com/my-endpoint"
httpStatusCode := 200
spanKind := datadog.Server
httpClientIp := "192.168.1.0"

meta := datadog.DatadogMetadata{
ResourceName: &resourceName,
HttpUrl: &httpUrl,
HttpStatusCode: &httpStatusCode,
SpanKind: &spanKind,
HttpClientIp: &httpClientIp,
}
traceCtx.Metadata(meta)

// stop the trace
traceCtx.Finish()
}

Adapter Configuration

You may modify the behavior of your adapter by passing in a configuration when initializing the adapter. A configuration has the following fields:

config := &DatadogConfig{
// the URL of the Datadog agent
AgentHost: "http://localhost:8126",
// the service name to group your observability data under
ServiceName: "my-wasm-service",
// default metadata that apply to every trace
DefaultTags: nil,
// the type of trace being captured
TraceType: datadog_formatter.Web,
// how often to send traces to the agent
FlushPeriod: 1 * time.Second,
// the maximum number of traces to send to the agent per request
BatchSize: 100,
}
adapter := NewDatadogAdapter(config)