Get Started with Honeycomb for Applications | Honeycomb

Get Started with Honeycomb for Applications

Honeycomb is a fast analysis tool that helps you analyze your code’s performance and behavior to troubleshoot complex relationships within your system to solve problems faster.

To use Honeycomb, you first need to get your system’s observable external outputs–traces, metrics, and logs–into Honeycomb. These instructions will guide you through the process of sending trace data from an application in your local development environment to Honeycomb, customizing your instrumentation to get additional visibility into the inner workings of your business logic, and exploring your data in Honeycomb.

Note
Not ready to instrument and deploy an application, but want to see what Honeycomb can do for you? Check out this interactive demo that requires no setup, or learn what is possible from the guided tutorials in our Honeycomb sandbox!

Before You Begin 

Before you run the code, you’ll need to do a few things.

Create a Honeycomb Account 

Before you can use Honeycomb products, you’ll need to decide whether you would like Honeycomb to store your data in a US-based or EU-based location. Then, create a Honeycomb account in the US or create a Honeycomb account in the EU. Signup is free!

Create a Honeycomb Team 

Complete your account creation by giving us a team name. Honeycomb uses teams to organize groups of users, grant them access to data, and create a shared work history in Honeycomb.

Tip
We recommend using your company or organization name as your Honeycomb team name.

Get Your Honeycomb API Key 

To send data to Honeycomb, you’ll need your Honeycomb API Key. Once you create your team, you will be able to view or copy your API key. Make note of it; you will need it later!

You can also find your Honeycomb API Key any time in your Environment Settings.

Send Telemetry Data to Honeycomb 

Once you have your Honeycomb API key and have chosen an application, it’s time to send telemetry data to Honeycomb!

Note
This guide helps users who are new to observability get their trace data into Honeycomb using OpenTelemetry. If you already have an OpenTelemetry implementation and are switching to Honeycomb, read about OpenTelemetry Collector.

Choose Your Application 

Choose a single application or service that will send data to Honeycomb. To successfully complete this Quick Start, you should have access to modify your application’s source code. To test the application when you are finished, you must be able to run your application or service in a development environment.

Tip
Don’t have access to an application? Follow along using one of our example applications!

Add Automatic Instrumentation to Your Code 

The quickest way to start seeing your trace data in Honeycomb is to use OpenTelemetry, an open-source collection of tools, APIs, and SDKs, to automatically inject instrumentation code into your application without requiring explicit changes to your codebase.

Note
Automatic instrumentation works slightly differently within each language, but the general idea is that it attaches hooks into popular tools and frameworks and “watches” for certain functions to be called. When they’re called, the instrumentation automatically starts and completes trace spans on behalf of your application.

When you add automatic instrumentation to your code, OpenTelemetry will build spans, which represent units of work or operations within your application that you want to capture and analyze for observability purposes.

Note
This Quick Start uses the npm dependency manager. For instructions with yarn or if using TypeScript, read our OpenTelemetry Node.js documentation.

Acquire Dependencies 

Open your terminal, navigate to the location of your project on your drive, and install OpenTelemetry’s automatic instrumentation meta package:

npm install --save @opentelemetry/auto-instrumentations-node
Module Description
auto-instrumentations-node OpenTelemetry’s meta package that provides a way to add automatic instrumentation to any Node application to capture telemetry data from a number of popular libraries and frameworks, like express, dns, http, and more.

Alternatively, install individual instrumentation packages.

Initialize 

Create an initialization file, commonly known as the tracing.js file:

// Example filename: tracing.js
'use strict';

const opentelemetry = require('@opentelemetry/sdk-node');
const { OTLPTraceExporter } =  require('@opentelemetry/exporter-trace-otlp-http');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');

const sdk = new opentelemetry.NodeSDK({
    traceExporter: new OTLPTraceExporter(),
    instrumentations: [
        getNodeAutoInstrumentations({
            // we recommend disabling fs autoinstrumentation since it can be noisy
            // and expensive during startup
            '@opentelemetry/instrumentation-fs': {
                enabled: false,
            },
        }),
    ],
});

sdk.start();

Configure the OpenTelemetry SDK 

Use environment variables to configure the OpenTelemetry SDK:

export OTEL_SERVICE_NAME="your-service-name"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.honeycomb.io:443" # US instance
#export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.eu1.honeycomb.io:443" # EU instance
export OTEL_EXPORTER_OTLP_HEADERS="your-api-key"
Variable Description
OTEL_SERVICE_NAME Service name. When you send data, Honeycomb creates a dataset in which to store your data and uses this as the name. Can be any string.
OTEL_EXPORTER_OTLP_PROTOCOL The data format that the SDK uses to send telemetry to Honeycomb. For more on data format configuration options, read Choosing between gRPC and HTTP.
OTEL_EXPORTER_OTLP_ENDPOINT Honeycomb endpoint to which you want to send your data.
OTEL_EXPORTER_OTLP_HEADERS Adds your Honeycomb API Key to the exported telemetry headers for authorization. Learn how to find your Honeycomb API Key.
Note

If you use Honeycomb Classic, you must also specify the Dataset using the x-honeycomb-dataset header.

export OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=your-api-key,x-honeycomb-dataset=your-dataset"
Note
If you are sending data directly to Honeycomb, you must configure the API key and service name. If you are using an OpenTelemetry Collector, configure your API key at the Collector level instead.

Run Your Application 

Run the Node.js app and include the initialization file you created:

node -r ./tracing.js YOUR_APPLICATION_NAME.js

Be sure to replace YOUR_APPLICATION_NAME with the name of your application’s main file.

Alternatively, you can import the initialization file as the first step in your application lifecycle.

In Honeycomb’s UI, you should now see your application’s incoming requests and outgoing HTTP calls generate traces.

Note
This Quick Start uses the pip package manager. For instructions with poetry, read our OpenTelemetry Python documentation.

Acquire Dependencies 

  1. Install the opentelemetry-distro and exporter packages:

    python -m pip install opentelemetry-distro \
        opentelemetry-exporter-otlp
    
  2. Install instrumentation libraries for the packages used by your application. We recommend using the opentelemetry-bootstrap tool that comes with the OpenTelemetry SDK to scan your application packages and print out a list of available instrumentation libraries. You should then add these libraries to your requirements.txt file:

    opentelemetry-bootstrap >> requirements.txt
    pip install -r requirements.txt
    

    If you do not use a requirements.txt file, you can install the libraries directly in your current environment:

    opentelemetry-bootstrap --action=install
    

Configure the OpenTelemetry SDK 

Use environment variables to configure the OpenTelemetry SDK:

export OTEL_SERVICE_NAME="your-service-name"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.honeycomb.io:443" # US instance
#export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.eu1.honeycomb.io:443" # EU instance
export OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=<your-api-key>"
Variable Description
OTEL_SERVICE_NAME Service name. When you send data, Honeycomb creates a dataset in which to store your data and uses this as the name. Can be any string.
OTEL_EXPORTER_OTLP_PROTOCOL The data format that the SDK uses to send telemetry to Honeycomb. For more on data format configuration options, read Choosing between gRPC and HTTP.
OTEL_EXPORTER_OTLP_ENDPOINT Honeycomb endpoint to which you want to send your data.
OTEL_EXPORTER_OTLP_HEADERS Adds your Honeycomb API Key to the exported telemetry headers for authorization. Learn how to find your Honeycomb API Key.

To learn more about configuration options, visit Agent Configuration in the OpenTelemetry documentation.

Note

If you use Honeycomb Classic, you must also specify the Dataset using the x-honeycomb-dataset header.

export OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=your-api-key,x-honeycomb-dataset=your-dataset"
Note
If you are sending data directly to Honeycomb, you must configure the API key and service name. If you are using an OpenTelemetry Collector, configure your API key at the Collector level instead.

Run Your Application 

Run your Python application using the OpenTelemetry Python automatic instrumentation tool opentelemetry-instrument, which configures the OpenTelemetry SDK:

opentelemetry-instrument python YOUR_APPLICATION_NAME.py

Be sure to replace YOUR_APPLICATION_NAME with the name of your application’s main file.

In Honeycomb’s UI, you should now see your application’s incoming requests and outgoing HTTP calls generate traces.

Acquire Dependencies 

The automatic instrumentation agent for Honeycomb OpenTelemetry Java will automatically generate trace data from your application. The agent is packaged as a JAR file and is run alongside your app.

In order to use the automatic instrumentation agent, you must first download it:

curl -LO https://github.com/honeycombio/honeycomb-opentelemetry-java/releases/download/v1.7.0/honeycomb-opentelemetry-javaagent-1.7.0.jar

Configure the Honeycomb Distro 

Choose from one of the following configuration options:

Use environment variables:

# US instance
HONEYCOMB_API_ENDPOINT=https://api.honeycomb.io:443
# EU instance
#HONEYCOMB_API_ENDPOINT=https://api.eu1.honeycomb.io:443
SERVICE_NAME=my-favorite-service
HONEYCOMB_API_KEY=my-api-key
HONEYCOMB_METRICS_DATASET=my-metrics # optional

Or, use system properties:

# US instance
honeycomb.api.endpoint=https://api.honeycomb.io:443
# EU instance
#honeycomb.api.endpoint=https://api.eu1.honeycomb.io:443
sample.rate=2
service.name=my-favorite-service
honeycomb.api.key=my-api-key
honeycomb.metrics.dataset=my-metrics

and set an environment variable with a path to your properties file:

HONEYCOMB_CONFIG_FILE=/path/to/properties/file

Run Your Application 

Run your application with the automatic instrumentation agent as a sidecar:

java -javaagent:honeycomb-opentelemetry-javaagent-1.7.0.jar -jar /path/to/myapp.jar

You can also include configuration values with an invocation of your application:

java \
-Dhoneycomb.config.file=/path/to/properties/file \
-javaagent:honeycomb-opentelemetry-javaagent-1.7.0.jar -jar /path/to/myapp.jar

For more configuration options, read Honeycomb OpenTelemetry Distribution for Java.

In Honeycomb’s UI, you should now see your application’s incoming requests and outgoing HTTP calls generate traces.

Note
This Quick Start uses ASP.NET Core. For other .NET configuration options, read our OpenTelemetry .NET documentation on programmatic and ASP.NET (.NET Framework) configuration.

Acquire Dependencies 

Install the Honeycomb.OpenTelemetry NuGet package.

For example, with the .NET CLI, use:

dotnet add package Honeycomb.OpenTelemetry
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package Honeycomb.OpenTelemetry.CommonInstrumentations --prerelease

Initialize 

Initialize your ASP.NET Core app to use the Honeycomb OpenTelemetry Distribution for .NET:

  1. In your appsettings.json file, add a Honeycomb section:

    {
      "Honeycomb": {
        "ServiceName": "my-app",
        "ApiKey": "{apikey}"
      }
    }
    

    By default, the data you send will be stored in our US data location (https://api.honeycomb.io:443). If you would like to store your data in our EU location, configure the Endpoint as well:

    {
      "Honeycomb": {
        "Endpoint": "https://api.eu1.honeycomb.io:443",
        "ServiceName": "my-app",
        "ApiKey": "{apikey}"
      }
    }
    
  2. Get HoneycombOptions from configuration and use these options to configure the OpenTelemetry SDK in your application startup code:

    using OpenTelemetry.Trace;
    
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddControllers();
    
    var honeycombOptions = builder.Configuration.GetHoneycombOptions();
    
    // Set up OpenTelemetry Tracing
    builder.Services.AddOpenTelemetry().WithTracing(otelBuilder =>
    {
        otelBuilder
            .AddHoneycomb(honeycombOptions)
            .AddCommonInstrumentations();
    });
    
    // Register a Tracer, so it can be injected into other components (for example, Controllers)
    builder.Services.AddSingleton(TracerProvider.Default.GetTracer(honeycombOptions.ServiceName));
    
    var app = builder.Build();
    
    app.MapGet("/", (Tracer tracer) =>
    {
        using var span = tracer.StartActiveSpan("app.manual-span");
        span.SetAttribute("app.manual-span.message", "Adding custom spans is also super easy!");
    });
    
    await app.RunAsync();
    

Run 

Run your application. You will see the incoming requests and outgoing HTTP calls generate traces.

dotnet run

To see all configuration options and ways to run your application, read Honeycomb OpenTelemetry Distribution for .NET.

In Honeycomb’s UI, you should now see your application’s incoming requests and outgoing HTTP calls generate traces.

Acquire Dependencies 

Install OpenTelemetry Go packages:

go get \
  go.opentelemetry.io/otel \
  go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc \
  go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp

Initialize 

Prepare your application to send spans to Honeycomb.

Open or create a file called main.go:

package main

import (
  "context"
  "fmt"
  "log"
  "net/http"

  "go.opentelemetry.io/otel"
  "go.opentelemetry.io/otel/exporters/otlp/otlptrace"
  "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
  "go.opentelemetry.io/otel/propagation"
  "go.opentelemetry.io/otel/sdk/trace"

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

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

  // Configure a new OTLP exporter using environment variables for sending data to Honeycomb over gRPC
  client := otlptracegrpc.NewClient()
  exp, err := otlptrace.New(ctx, client)
  if err != nil {
    log.Fatalf("failed to initialize exporter: %e", err)
  }

  // Create a new tracer provider with a batch span processor and the otlp exporter
  tp := trace.NewTracerProvider(
    trace.WithBatcher(exp),
  )

  // Handle shutdown to ensure all sub processes are closed correctly and telemetry is exported
  defer func() {
    _ = exp.Shutdown(ctx)
    _ = tp.Shutdown(ctx)
  }()

  // Register the global Tracer provider
  otel.SetTracerProvider(tp)

  // Register the W3C trace context and baggage propagators so data is propagated across services/processes
  otel.SetTextMapPropagator(
    propagation.NewCompositeTextMapPropagator(
      propagation.TraceContext{},
      propagation.Baggage{},
    ),
  )

  // Implement an HTTP handler func to be instrumented
  handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World")
  })

  // Setup handler instrumentation
  wrappedHandler := otelhttp.NewHandler(handler, "hello")
  http.Handle("/hello", wrappedHandler)

  // Start web server
  log.Fatal(http.ListenAndServe(":3030", nil))
}

Configure the OpenTelemetry SDK 

Once you have acquired the necessary dependencies, you can configure your SDK to send events to Honeycomb, and then run your application to see traces.

export OTEL_SERVICE_NAME="your-service-name"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.honeycomb.io:443" # US instance
#export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.eu1.honeycomb.io:443" # EU instance
export OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=your-api-key"
Variable Description
OTEL_EXPORTER_OTLP_ENDPOINT Honeycomb endpoint to which you want to send your data.
OTEL_EXPORTER_OTLP_HEADERS Header containing x-honeycomb-team=, plus your API Key generated in Honeycomb.
OTEL_SERVICE_NAME Service name. When you send data, Honeycomb creates a dataset in which to store your data and uses this as the name. Can be any string.

Run Your Application 

Run your application:

go run YOUR_APPLICATION_NAME.go

Be sure to replace YOUR_APPLICATION_NAME with the name of your application’s main file.

In Honeycomb’s UI, you should now see your application’s incoming requests and outgoing HTTP calls generate traces.

Acquire Dependencies 

Add these gems to your Gemfile:

gem 'opentelemetry-sdk'
gem 'opentelemetry-exporter-otlp'
gem 'opentelemetry-instrumentation-all'
Gem Description
opentelemetry-sdk Required to create spans
opentelemetry-exporter-otlp An exporter to send data in the OTLP format
opentelemetry-instrumentation-all A meta package that provides instrumentation for Rails, Sinatra, several HTTP libraries, and more

Install the gems using your terminal:

bundle install

Initialize 

Initialize OpenTelemetry early in your application lifecycle. For Rails applications, we recommend that you use a Rails initializer. For other Ruby services, initialize as early as possible in the startup process.

# config/initializers/opentelemetry.rb
require 'opentelemetry/sdk'
require 'opentelemetry/exporter/otlp'
require 'opentelemetry/instrumentation/all'

OpenTelemetry::SDK.configure do |c|
    c.use_all() # enables all instrumentation!
end

Configure the OpenTelemetry SDK 

Use environment variables to configure OpenTelemetry to send events to Honeycomb:

export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.honeycomb.io" # US instance
#export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.eu1.honeycomb.io" # EU instance
export OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=your-api-key"
export OTEL_SERVICE_NAME="your-service-name"
Variable Description
OTEL_EXPORTER_OTLP_ENDPOINT Base endpoint to which you want to send your telemetry data.
OTEL_EXPORTER_OTLP_HEADERS List of headers to apply to all outgoing telemetry data. Place your API Key generated in Honeycomb in the x-honeycomb-team header. Learn how to find your Honeycomb API Key.
OTEL_SERVICE_NAME Service name. When you send data, Honeycomb creates a dataset in which to store your data and uses this as the name. Can be any string.

Run Your Application 

Run your Ruby application.

In Honeycomb’s UI, you should now see your application’s incoming requests and outgoing HTTP calls generate traces.

Refer to Honeycomb for Kubernetes Overview for a Quick Start and all configuration options to get Kubernetes metrics, logs, events, as well as Kubernetes attributes added to application traces, logs, and metrics in Honeycomb.

If your preferred language is not covered here, you can find relevant instrumentation information in the OpenTelemetry community documentation.

Tip
For Rust, we recommend you use the opentelemetry and opentelemetry-otlp crates to send data to Honeycomb over OTLP.

For any required configuration values, see Using the Honeycomb OpenTelemetry Endpoint.

Generate Automated Data 

Now that you have added automatic instrumentation to your application and have it running in your development environment, interact with your application by making a few requests. Making requests to your service will generate telemetry data and send it to Honeycomb where it will appear in the Honeycomb UI within seconds.

Tip
If you have made several service requests in your development environment and after several minutes, you still do not see any data, reach out for help in our Pollinators Community Slack.

View an Example Trace 

Before you move on, take a look at the data that you have generated using automatic instrumentation by viewing an example trace, which is a visual diagram that represents the complete journey of a request or transaction as it traverses a distributed system.

Traces provide a way to visualize and understand the flow of execution and the interactions between various components involved in serving a request. They can help you find the source of errors in a system, identify the slowest processes, and break down the user experience in great detail.

While Honeycomb helps you analyze all of your outputs, where we particularly shine is when working with traces to give you a visual representation of where requests spend time in your system. In this example, we want to see a count of events, an average latency for those events, and a heatmap of latency.

To see your trace:

  1. Depending on where you created your account, either log in to Honeycomb US or log in to Honeycomb EU using your Honeycomb account.
  2. From the left sidebar, navigate to Query.
  3. In the VISUALIZE clause, add HEATMAP(duration_ms)
  4. Select Run Query.
  5. In the heatmap results, click on a dot to get a trace.

We generated the following examples after adding automatic instrumentation to a simple greeting service application written in Node.js. You can see the code in our GitHub repository.

Here’s our example heatmap:

Heatmap for our automatically-instrumented example application, showing three dots, each of which represents a trace

And here is our example trace:

First trace for our automatically-instrumented example application

In this trace, you can see:

  • the spans within the trace
  • how long each span took
  • which spans contain errors (none, in this example)

All of this is useful information, but more information will allow us to dig even more deeply. To do this, we need to enhance our automatic instrumentation by customizing it.

Customize Your Instrumentation 

To get the most insight into your system, you should customize your instrumentation. For example, if you have an application or service that handles users, you probably want to associate the user with the span created by automatic instrumentation. Additionally, because automatic instrumentation doesn’t know your business logic–it only knows about frameworks and languages–you’ll want to explicitly add instrumentation code surrounding your business logic.

Tip
When deciding what to instrument, we recommend thinking of this as an exploratory process and part of the core analysis loop. You don’t need to add your custom instrumentation to everything all at once. Consider your top interests and instrument them, then analyze your results and add additional code as necessary.

Acquire Dependencies 

Before you can customize your instrumentation, you must install any required dependencies. These will vary depending on your chosen programming language.

To continue, you must install OpenTelemetry’s API package. Once you have installed the API package, you can use it to add instrumentation for everything you care about in your application.

Note
This Quick Start uses the npm dependency manager. For instructions with yarn or if using TypeScript, read our OpenTelemetry Node.js documentation.
npm install --save @opentelemetry/api

To continue, you must install OpenTelemetry’s API package. Once you have installed the API package, you can use it to add instrumentation for everything you care about in your application.

Note
This Quick Start uses the pip package manager. For instructions with poetry, read our OpenTelemetry Python documentation.
python -m pip install opentelemetry-api

To continue, you must install Honeycomb’s OpenTelemetry SDK, which provides access to the OpenTelemetry APIs. Once you have installed the SDK, you can use it to add instrumentation for everything you care about in your application.

Note
This Quick Start uses the Gradle build tool. For instructions with Maven, read our OpenTelemetry Java documentation.
dependencies {
  implementation('io.honeycomb:honeycomb-opentelemetry-sdk:1.7.0')
}
Note
This Quick Start uses ASP.NET Core. For other .NET configuration options, read our OpenTelemetry .NET documentation on programmatic and ASP.NET (.NET Framework) configuration.

Because you already installed all necessary dependencies when implementing automatic instrumentation, you can skip this step.

Because you already installed all necessary dependencies when implementing automatic instrumentation, you can skip this step.

Because you already installed all necessary dependencies when implementing automatic instrumentation, you can skip this step.

If your preferred language is not covered here, you can find relevant instrumentation information in the OpenTelemetry community documentation.

Add Contextual Information to Existing Spans 

To enhance the understanding of your telemetry data, you can attach contextual information to the spans generated by automatic instrumentation. Contextual information includes attributes, which are arbitrary key-value pairs that you can add to provide additional data about the span, such as a specific database query being executed or an HTTP request being made.

In this example, you will enhance your automatic instrumentation by associating a span created automatically when a user queries your service with the user’s ID, which will be saved in an attribute called user.id. Once this attribute is added, you will be able to use it to query your data in Honeycomb.

const opentelemetry = require("@opentelemetry/api");

//...

function handleUser(user) {
  // Gets the active span from the context
  let activeSpan = opentelemetry.trace.getActiveSpan();
  // Sets an attribute that contains the user ID
  activeSpan.setAttribute("user.id", user.getId());
}
from opentelemetry import trace

#...

# Gets the active span from the context
span = trace.get_current_span()
# Sets an attribute that contains the user ID
span.set_attribute("user.id", user.id())
import io.opentelemetry.api.trace.Span;

//...

// Gets the active span from the context
Span span = Span.current();
// Sets an attribute that contains the user ID
span.setAttribute("user.id", user.getId());
using OpenTelemetry.Trace;

//...

// Gets the active span from the context
var currentSpan = Tracer.CurrentSpan;
// Sets an attribute that contains the user ID
currentSpan.SetAttribute("user.id", User.GetUserId())

This example assumes you are writing a web application with the net/http package.

import (
  // ...
  "go.opentelemetry.io/otel/attribute"
  "go.opentelemetry.io/otel/trace"
  // ...
)

// ...
handler := func(w http.ResponseWriter, r *http.Request) {
  // Gets the currently logged in user
  user := someServiceCall()
  ctx := r.Context()
  // Gets the active span from the context
  span := trace.SpanFromContext(ctx)
  // Sets an attribute that contains the user ID
  span.SetAttributes(attribute.Int("user.id", user.getID()))
}
// ...
# Somewhere within the service, the SDK has been required and configured
require 'opentelemetry/sdk'
OpenTelemetry::SDK.configure do ... end

# ...

def handle_user(user)
  # Gets the active span from the context
  current_span = OpenTelemetry::Trace.current_span
  # Sets an attribute that contains the user ID
  current_span.set_attribute("user.id", user.id)
end

If your preferred language is not covered here, you can find relevant instrumentation information in the OpenTelemetry community documentation.

Create Custom Spans 

To further enhance the understanding of your telemetry data, you’ll want to generate custom spans. Automatic instrumentation can show the shape of requests to your system, but only you know the truly important parts. To get the full picture, you should manually add spans to areas of interest. In OpenTelemetry, this is called manual instrumentation.

Initialize a Tracer 

Before you can create a custom span, you must initialize a tracer. In OpenTelemetry, a tracer is used to instrument your code and generate telemetry data. The tracer provides the interface for capturing spans, which represent individual units of work in your code.

const opentelemetry = require("@opentelemetry/api");

// Creates the tracer and names it.
// Choose a name that matches the appropriate scope for your trace.
// For example, if you have one tracer for each service, then use
// the service name. If you have multiple tracers that live in
// different "layers" of your application, then user the name that
// corresponds to the appropriate "layer".
const tracer = opentelemetry.trace.getTracer("your.tracer.name");
from opentelemetry import trace

#...

# Creates the tracer and names it.
# Choose a name that matches the appropriate scope for your trace.
# For example, if you have one tracer for each service, then use
# the service name. If you have multiple tracers that live in
# different "layers" of your application, then user the name that
# corresponds to the appropriate "layer".
tracer = trace.get_tracer("tracer.name.here")
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Tracer;

//...

// Creates the tracer and names it.
// Choose a name that matches the appropriate scope for your trace.
// For example, if you have one tracer for each service, then use
// the service name. If you have multiple tracers that live in
// different "layers" of your application, then user the name that
// corresponds to the appropriate "layer".
Tracer tracer = GlobalOpenTelemetry.getTracer("tracer.name.here");
using OpenTelemetry.Trace;

//...

// Creates the tracer and names it.
// Choose a name that matches the appropriate scope for your trace.
// For example, if you have one tracer for each service, then use
// the service name. If you have multiple tracers that live in
// different "layers" of your application, then user the name that
// corresponds to the appropriate "layer".
var tracer = TracerProvider.Default.GetTracer("tracer.name.here");

Then, inject the Tracer instance with ASP.NET Core dependency injection or manage its lifecycle manually.

import (
  // ...
  "go.opentelemetry.io/otel"
  // ...
)

//...

// Creates the tracer and names it.
// Choose a name that matches the appropriate scope for your trace.
// For example, if you have one tracer for each service, then use
// the service name. If you have multiple tracers that live in
// different "layers" of your application, then user the name that
// corresponds to the appropriate "layer".
tracer := otel.Tracer("tracer.name.here")
require "opentelemetry/sdk"

#...

# Creates the tracer and names it.
# Choose a name that matches the appropriate scope for your trace.
# For example, if you have one tracer for each service, then use
# the service name. If you have multiple tracers that live in
# different "layers" of your application, then user the name that
# corresponds to the appropriate "layer".
tracer = OpenTelemetry.tracer_provider.tracer("tracer.name.here")

If your preferred language is not covered here, you can find relevant instrumentation information in the OpenTelemetry community documentation.

Create Your Span 

Get the tracer from the OpenTelemetry API and use it to create your custom span.

const opentelemetry = require("@opentelemetry/api");

const tracer = opentelemetry.trace.getTracer("my-service-tracer");

function runQuery() {
  tracer.startActiveSpan("expensive-query", (span) => {
    // Do cool stuff
    span.end();
  });
}
from opentelemetry import trace

tracer = trace.get_tracer("tracer.name.here")
with tracer.start_as_current_span("some-long-running-handler"):
    # Prepare to auth

    with tracer.start_as_current_span("what-it-takes-to-authorize-handling"):
        # Perform auth

    # Do the authorized long-running handling of cool stuff
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;

...

Tracer tracer = GlobalOpenTelemetry.getTracer("my-service");
Span span = tracer.spanBuilder("expensive-query").startSpan();

// ... Do cool stuff

span.end();
using OpenTelemetry.Trace;

//...

using var span = TracerProvider.Default.GetTracer("my-service").StartActiveSpan("expensive-query")
// ... Do cool stuff
import (
  // ...
  "go.opentelemetry.io/otel"
  // ...
)

// ...
tracer := otel.Tracer("my-app") // If not already in scope
ctx, span := tracer.Start(ctx, "expensive-operation")
defer span.End()
// ...
# Somewhere within the service, the SDK has been required and configured
require 'opentelemetry/sdk'
OpenTelemetry::SDK.configure do ... end

# ...

def run_query
  tracer = OpenTelemetry.tracer_provider.tracer('my-tracer')
  tracer.in_span("expensive-query") do |span|
    # ... Do cool stuff
    span.set_attribute('coolness', 100)
  end
end

If your preferred language is not covered here, you can find relevant instrumentation information in the OpenTelemetry community documentation.

Analyze Your Results 

Now that you have customized your instrumentation, take a look at your trace again.

We generated the following examples after adding additional custom spans (a note to indicate where we are in the process, plus person name and message) to our simple greeting service application written in Node.js. You can see the code in our GitHub repository.

Here’s our example trace:

Trace showing custom spans implemented in our example application

In this trace, you can see the additional spans:

  • note indicating we are preparing the greeting
  • call name
  • call message

If you look in the Fields section of the UI, you would also see new attributes, such as the name of the person and the message that was sent.

What’s Next? 

Excellent work! If you made it this far, you should now have telemetry data from your application flowing into Honeycomb. You can deploy to production and start gaining new insights on real traffic!

But there is so much more to explore! To learn more about what you can do with Honeycomb, check out: