Send OpenTelemetry data to Axiom

OpenTelemetry (otel) is a set of APIs, libraries, and agents to capture distributed traces and metrics from your application. It's a Cloud Native Computing Foundation (CNCF) project that was started to create a unified solution for service and application performance monitoring.

The OpenTelemetry project has published strong specifications for the three main pillars of observability: logs, traces, and metrics. These schemas are supported by all tools and services that support interacting with OpenTelemetry. Axiom supports OpenTelemetry natively on an API level, allowing you to connect any existing OpenTelemetry shipper, library, or tool to Axiom for sending data.

OpenTelemetry-compatible events flow into Axiom, where they are organized into datasets for easy segmentation. Users can create a dataset to receive OpenTelemetry data and obtain an API token for ingestion. Axiom provides comprehensive observability through browsing, querying, dashboards, and alerting of OpenTelemetry data.


Otel traces, and Otel logs support is already live, and we're continually enhancing it to serve our customers' needs better, and we are excited to announce that we will soon be extending our support to OpenTelemetry Metrics (OTel Metrics). This featuure is under active development and will be available soon.

OpenTelemetry ComponentCurrently Supported
TracesYes
LogsYes
MetricsNo (Coming Soon)

OpenTelemetry Collector

Configuring the OpenTelemetry collector is as simple as creating an http exporter that sends data to the Axiom API together with headers to set the dataset and API token:

exporters:
  otlphttp:
    compression: gzip
    endpoint: https://api.axiom.co
    headers:
      authorization: Bearer <YOUR_API_TOKEN>
      x-axiom-dataset: <YOUR_DATASET>

service:
  pipelines:
    traces:
      receivers:
        - otlp
      processors:
        - memory_limiter
        - batch
      exporters:
        - otlphttp

When using the OTLP/HTTP endpoint for traces and logs, the following endpoint URLs should be used in your SDK exporter Otel configuration.

  • Traces: https://api.axiom.co/v1/traces
  • Logs: https://api.axiom.co/v1/logs

OpenTelemetry for Go

Below is an example that configures an golang application using the OpenTelemetry SDK for Go to send OpenTelemetry data to Axiom.

package main

import (
	// standard imports...
)

func main() {
	ctx := context.Background()

  // Setup the otel client to export to Axiom
	driver := otlptracehttp.NewClient(
		otlptracehttp.WithEndpoint("https://api.axiom.co"),
		otlptracehttp.WithHeaders(map[string]string{
			"authorization": "Bearer " + os.Getenv("AXIOM_API_TOKEN"),
			"x-axiom-dataset": os.Getenv("AXIOM_DATASET"),
		}),
	)

	ctx, cancel := context.WithTimeout(ctx, time.Second*10)
	defer cancel()
	if err := driver.Start(ctx); err != nil {
		log.Fatalf("Failed to start trace driver: %v", err)
	}

  // Create a trace
	exp, err := otlptracehttp.New(ctx, driver)
	if err != nil {
		log.Fatalf("Failed to create trace exporter: %v", err)
	}

	hostname, _ := os.Hostname() // get the hostname

	r := resource.NewWithAttributes(semconv.SchemaURL,
		attribute.String("service.name", "my-service"),
		attribute.String(semconv.HostNameKey.String(), hostname),
	)

	tp := sdktrace.NewTracerProvider(
		sdktrace.WithBatcher(exp),
		sdktrace.WithResource(r),
	)

	otel.SetTracerProvider(tp)
	otel.SetTextMapPropagator(propagation.TraceContext{})

	tracer := otel.Tracer("sample-app")
	var span trace.Span
	ctx, span = tracer.Start(ctx, "operation")
	time.Sleep(time.Second)
	span.End()

	// Shutdown will flush any remaining spans
	if err := tp.Shutdown(ctx); err != nil {
		log.Fatalf("failed to shut down TracerProvider: %v", err)
	}
}

OpenTelemetry for Ruby

To send traces to an OpenTelemetry Collector using the OTLP over HTTP in Ruby, you will need to use the opentelemetry-exporter-otlp-http gem provided by the OpenTelemetry project.

require 'opentelemetry/sdk'
require 'opentelemetry/exporter/otlp/http'
require 'opentelemetry/resource/detectors'

OpenTelemetry::SDK.configure do |c|
  c.service_name = 'my-service'
  c.service_version = '1.0'
  c.resource = OpenTelemetry::Resource::Detectors::AutoDetector.detect
  c.add_span_processor(
    OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
      OpenTelemetry::Exporter::OTLP::HTTP::SpanExporter.new(
        endpoint: 'http://your-opentelemetry-collector:4318',
        headers: {
          'authorization' => 'Bearer <YOUR_API_TOKEN>'
          'x-axiom-dataset' => '<YOUR_DATASET>'
        }
      )
    )
  )
end

OpenTelemetry for Java

Here is a basic configuration for a Java application that sends traces to an OpenTelemetry Collector using OTLP over HTTP using the OpenTelemetry Java SDK:

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
import io.opentelemetry.exporter.otlp.trace.OtlpHttpSpanExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;

public class Application {
    public static void main(String[] args) {
        // Configure the OtlpHttpSpanExporter
        OtlpHttpSpanExporter spanExporter = OtlpHttpSpanExporter.builder()
                .setEndpoint("https://api.axiom.co")
                .addHeader("Authorization", "Bearer YOUR_API_TOKEN") // replace "your-api-token" with your actual token
                .addHeader("X-AXIOM-DATASET", "YOUR_DATASET") // replace "your-dataset" with your actual dataset
                .build();
        // Add the span processor to the TracerProvider
        OpenTelemetrySdk.getGlobalTracerManagement()
                .addSpanProcessor(BatchSpanProcessor.builder(spanExporter).build());
        // Get a tracer
        Tracer tracer = OpenTelemetry.getGlobalTracer("myTracerName");
        // Start a span
        Span span = tracer.spanBuilder("mySpanName").startSpan();
        try (Scope scope = span.makeCurrent()) {
            // Your work here
            // Add an attribute to the span
            span.setAttribute("exampleKey", "exampleValue");
        } finally {
            // End the span
            span.end();
        }
    }
}

OpenTelemetry for .NET

You can send traces to Axiom using the OpenTelemetry .NET SDK by configuring an OTLP HTTP exporter in your .NET application. Here is a simple example:

// standard imports...

public class Program
{
    public static void Main()
    {
        // Create a tracer provider with the OTLP exporter
        using var tracerProvider = Sdk.CreateTracerProviderBuilder()
            .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("my-service-name"))
            .AddSource("my-source-name")
            .AddOtlpExporter(otlpOptions =>
            {
                otlpOptions.Endpoint = new Uri("https://api.axiom.co");
                otlpOptions.Headers = new Metadata
                {
                    {"Authorization", "YOUR_AXIOM_API_TOKEN"},
                    {"X-Axiom-Dataset", "YOUR_AXIOM_DATASET"},
                };
            })
            .Build();

        // Get a tracer
        var tracer = tracerProvider.GetTracer("my-source-name");

        // Start a span and do some work
        using (var scope = tracer.StartActiveSpan("my-span-name", out var span))
        {
            try
            {
                // Your work here
                // Simulating work with a delay
                Thread.Sleep(1000);

                // Optionally, you can add events or attributes onto your span
                span.AddEvent("An event in my span");
            }
            catch (Exception ex)
            {
                // If there's an error, record the exception into the span
                span.RecordException(ex);
                throw; // rethrow the exception
            }
            finally
            {
                // End the span
                span.End();
            }
        }
    }
}

OpenTelemetry for Python

You can send traces to Axiom using the OpenTelemetry Python SDK by configuring an OTLP HTTP exporter in your Python application. Here is a simple example:

from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

resource = Resource(attributes={
    "service.name": "my-service"
})

# Create a TracerProvider and configure it to use the OTLP exporter
trace.set_tracer_provider(TracerProvider(resource=resource))
tracer = trace.get_tracer(__name__)

# Set the OTLP exporter to use HTTP and point it to the Axiom URL
otlp_exporter = OTLPSpanExporter(
    endpoint="https://api.axiom.co",
    headers={
        "Authorization": "Bearer your-axiom-api-token",
        "X-Axiom-Dataset": "your-axiom-dataset"  # Add your dataset here
    }
)

# Configure the tracer to use the BatchSpanProcessor with the OTLP exporter
span_processor = BatchSpanProcessor(otlp_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)

# Now you can create spans
with tracer.start_as_current_span("foo"):
    print("Axiom, tracing!")

# Clean up before exit
span_processor.shutdown()

OpenTelemetry for Node

You can send traces to Axiom using the OpenTelemetry Node SDK by configuring an OTLP HTTP exporter in your Node application. Here is a simple example:

const { NodeTracerProvider } = require('@opentelemetry/node');
const { BatchSpanProcessor } = require('@opentelemetry/tracing');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');

// Create a tracer provider
const tracerProvider = new NodeTracerProvider({
  resource: Resource.default().merge(new Resource({
    "service.name": "my-service"
  })),
});

// Configure the span processor to send spans to the exporter
const exporter = new OTLPTraceExporter({
  url: 'https://api.axiom.co',
  headers: {
    'Authorization': 'Bearer YOUR_AXIOM_API_TOKEN',
    'X-Axiom-Dataset': 'YOUR_AXIOM_DATASET',
  },
});
tracerProvider.addSpanProcessor(new BatchSpanProcessor(exporter));

// Initialize the OpenTelemetry APIs to use the NodeTracerProvider bindings
tracerProvider.register();

// Now, you can start and use a span
const tracer = tracerProvider.getTracer('example-tracer-http');
const mainSpan = tracer.startSpan('main');

// simulate some work for 1s
setTimeout(() => {
  mainSpan.end();
  // You should see the span in Axiom after a short delay
}, 1000);

Was this page helpful?