This Quick Start guide shows you how to add OpenTelemetry to your Java, Node.js, Python, or Go application in just two steps.

Using a different language? You can still get started quickly.

Configure

To report data to Lightstep, you’ll need:

Configure OpenTelemetry with the name of the service that you’d like to report tracing data from, an access token, and optionally the satellite endpoint.

Start tabs

Public Satellites

1
2
export LS_SERVICE_NAME=your_service_name
export LS_ACCESS_TOKEN=your_access_token

On-Premise Satellites

1
2
3
4
5
6
7
8
9
export LS_SERVICE_NAME=your_service_name
# The access token can be omitted for satellites running in single-project mode.
export LS_ACCESS_TOKEN=your_access_token
# The span endpoint defaults to ingest.lightstep.com:443 for all languages except Node.js.
# Node.js sends data over HTTP so the path must be included in the endpoint:
# https://ingest.lightstep.com:443/api/v2/otel/trace
export OTEL_EXPORTER_OTLP_SPAN_ENDPOINT=your_satellite_endpoint
# If your satellites don't have TLS enabled, uncomment the following line.
# export OTEL_EXPORTER_OTLP_SPAN_INSECURE=true

Developer Mode

1
2
3
4
5
export LS_SERVICE_NAME=your_service_name
# For Node.js, instead use:
# export OTEL_EXPORTER_OTLP_SPAN_ENDPOINT="http://localhost:8360/api/v2/otel/trace"
export OTEL_EXPORTER_OTLP_SPAN_ENDPOINT="localhost:8360"
export OTEL_EXPORTER_OTLP_SPAN_INSECURE=true

End code tabs

Install Instrumentation

Start by installing the Lightstep OpenTelemetry launcher for your language. Lightstep’s launchers package all of the necessary OpenTelemetry dependencies with a configuration layer to ease setup.

Then begin collecting traces! In Java, Javascript, and Python, OpenTelemetry has built-in instrumentation for popular libraries, so that you can get tracing data without needing to add any tracing code.

Start tabs

Java

1
2
3
4
# Install the OpenTelemetry Java Agent
curl -L "https://github.com/lightstep/otel-launcher-java/releases/download/0.8.0/lightstep-opentelemetry-javaagent-0.8.0.jar" > lightstep-opentelemetry-javaagent-0.8.0.jar
# Run your application with the agent
java -javaagent:path/to/lightstep-opentelemetry-javaagent-0.8.0.jar -jar myapp.jar

Node.js

1
2
3
4
5
6
7
8
9
10
11
// In a shell, run:
// $ npm install lightstep-opentelemetry-launcher-node --save

// In your application code:
const { lightstep, opentelemetry } = require("lightstep-opentelemetry-launcher-node");
      
lightstep.configureOpenTelemetry().start().then(() => {
  // All of your application code and any imports that should
  // leverage OpenTelemetry instrumentation must go here; e.g.,
  // const express = require('express');
});

Python

1
2
3
4
5
6
7
8
9
# This install requires gcc and gcc-c++, which you may need to install if you're
# running a slim version of Linux (e.g., CentOS):
# yum -y install python3-devel
# yum -y install gcc-c++
pip3 install opentelemetry-launcher
# Detect installed libraries and install relevant instrumentation.
opentelemetry-bootstrap -a install
# Run your application
opentelemetry-instrument python3 your_app.py

Go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// In a shell, run:
// $ go get 'github.com/lightstep/otel-launcher-go/launcher'

// In your application code:
import (
   "context"
   "github.com/lightstep/otel-launcher-go/launcher"
   "go.opentelemetry.io/otel/api/global"
)

otel := launcher.ConfigureOpentelemetry()
defer otel.Shutdown()

tracer := global.Tracer("example")
_, span := tracer.Start(context.Background(), "main")
defer span.End()

End code tabs

To view traces in your Lightstep project, click explorer in the left navigation bar, and then click on any span in the Trace Analysis table.

Next Steps

Add application-level tags (e.g., service version)

Once you’ve set up tracing, the first tag we recommend adding is the service’s version (e.g., a git hash) so that you can view deployments in the service directory and correlate performance regressions to deployments:

1
export LS_SERVICE_VERSION="v4.5.6"

You may want to set additional resource attributes. Resource attributes are tags that will be applied to every span that is emitted from your application (under the hood, LS_SERVICE_NAME and LS_SERVICE_VERSION are added as resource attributes). For example, to add resource attributes for the hostname, Kubernetes region, and the deployment:

1
export OTEL_RESOURCE_ATTRIBUTES="host.hostname=server1.mydomain.com,kube_region=us-central1,deployment.environment=canary"

OpenTelemetry provides conventions for many of these resource names, which makes your system’s traces easier to analyze by ensuring consistency. Resources will appear in the “Details” tab in the trace view.

Expandable end

Add attributes and events

It’s often useful to add information specific to your application to the automatically instrumented traces. The code below shows how to get the current span and add attributes and events. Optionally, you can add attributes to events as shown below in the last parameter to the addEvent call.

Start tabs

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// To use OpenTelemetry in your Java code, you'll need to add the dependency to your POM file:
// <dependency>
//   <groupId>io.opentelemetry</groupId>
//   <artifactId>opentelemetry-extension-auto-annotations</artifactId>
//   <version>0.7.0</version>
// </dependency>
// <dependency>
//   <groupId>io.opentelemetry</groupId>
//   <artifactId>opentelemetry-api</artifactId>
//   <version>0.7.0</version>
// </dependency>

import io.opentelemetry.OpenTelemetry;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.Tracer;

Tracer tracer = OpenTelemetry.getTracer(System.getenv("LS_SERVICE_NAME"));
Span span = tracer.getCurrentSpan();
span.setAttribute("customer_id", "3615");
span.addEvent("finished reading data from GCS");

Node.js

1
2
3
4
5
6
const { opentelemetry } = require("lightstep-opentelemetry-launcher-node");
const tracer = opentelemetry.trace.getTracer('launcher-node-example');
const span = tracer.getCurrentSpan();

span.setAttribute('customer_id', '3615');
span.addEvent('finished reading data from GCS', {'compression': 'gzip'});

Python

1
2
3
4
5
from opentelemetry import trace

span = trace.get_current_span()
span.set_attribute("customer_id", "3615")
span.add_event("finished reading data from GCS", {"compression": "gzip"})

Go

1
2
3
span := trace.SpanFromContext(ctx)
span.SetAttribute("customer_id", "3615");
span.AddEvent(ctx, "finished reading data from GCS", label.String("compression", "gzip"));

End code tabs

Many operations represent well-known protocols like HTTP or database calls. OpenTelemetry defines a schema for the attributes that describe these common operations. These standards are called Semantic Conventions and are defined in the OpenTelemetry Specification. Adhering to these conventions increases the value of tracing by providing consistent attributes to analyze across your system.

The following semantic conventions are defined for tracing:

  • General: General semantic attributes that may be used in describing different kinds of operations.
  • HTTP: Spans for HTTP client and server.
  • Database: Spans for SQL and NoSQL client calls.
  • RPC/RMI: Spans for remote procedure calls (e.g., gRPC).
  • Messaging: Spans for interaction with messaging systems (queues, publish/subscribe, etc.).
  • FaaS: Spans for Function as a Service (e.g., AWS Lambda).

Expandable end

Make your own spans

You may want to create your own spans to describe behavior in your system. The examples below show how to create a span, set it as the currently active span, and then create a new child span. By default, the parent of a new span is the currently active span.

Start tabs

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// To use OpenTelemetry in your Java code, you'll need to add the dependency to your POM file:
// <dependency>
//   <groupId>io.opentelemetry</groupId>
//   <artifactId>opentelemetry-extension-auto-annotations</artifactId>
//   <version>0.7.0</version>
// </dependency>
// <dependency>
//   <groupId>io.opentelemetry</groupId>
//   <artifactId>opentelemetry-api</artifactId>
//   <version>0.7.0</version>
// </dependency>

import io.opentelemetry.OpenTelemetry;
import io.opentelemetry.context.Scope;
import io.opentelemetry.extensions.auto.annotations.WithSpan;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.Tracer;

// You can annotate methods to create a span for the duration of the method call.
@WithSpan
public static void myMethod() {
  // Do something.
}

// You can also manually get a tracer and create a span.
Tracer tracer = OpenTelemetry.getTracer(System.getenv("LS_SERVICE_NAME"));
Span span = tracer.spanBuilder("testSpan").startSpan();
try (Scope scope = tracer.withSpan(span)) {
  myMethod();
}
span.end();

Node.js

1
2
3
4
5
6
7
8
9
10
const { opentelemetry } = require('lightstep-opentelemetry-launcher-node');

// Ensure this code is inside the sdk.start().then() code block
const tracer = opentelemetry.trace.getTracer('launcher-node-example');
const span = tracer.startSpan('testSpan');
tracer.withSpan(span, () => {
  const childSpan = tracer.startSpan('childSpan');
  childSpan.end();
});
span.end();

Python

1
2
3
4
5
6
from opentelemetry import trace

tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("testSpan") as span:
  child_span = tracer.start_span("child")
  child_span.end()

Go

1
2
3
4
5
6
7
8
9
10
11
12
import (
   "github.com/lightstep/otel-launcher-go/launcher"
   "go.opentelemetry.io/otel/api/global"
)

tracer := global.Tracer("example")
_, span := tracer.Start(context.Background(), "testSpan")
defer span.End()

ctx = trace.ContextWithSpan(ctx, span)
childSpan := trace.SpanFromContext(ctx)
childSpan.End()

End code tabs

Expandable end

Look at example applications

Examples of using OpenTelemetry in a simple application with a client and server are available in our examples repository. Look in the launcher folder for each language for example code that leverages Lightstep’s launchers.

Expandable end

Troubleshooting

Run the launcher in debug mode

Set an environment variable to run the OpenTelemetry launcher in debug mode, where it logs details about the configuration and emitted spans:

1
export OTEL_LOG_LEVEL=debug

The output may be very verbose with some benign errors. Early in the console output, look for logs about the configuration and check that your access token is correct. Next, look for lines like the ones below, which are emitted when spans are emitted to Lightstep.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Span {
  attributes: {},
  links: [],
  events: [],
  status: { code: 0 },
  endTime: [ 1597810686, 885498645 ],
  _ended: true,
  _duration: [ 0, 43333 ],
  name: 'bar',
  spanContext: {
    traceId: 'eca3cc297720bd705e734f4941bca45a',
    spanId: '891016e5f8c134ad',
    traceFlags: 1,
    traceState: undefined
  },
  parentSpanId: 'cff3a2c6bfd4bbef',
  kind: 0,
  startTime: [ 1597810686, 885455312 ],
  resource: Resource { labels: [Object] },
  instrumentationLibrary: { name: 'example', version: '*' },
  _logger: ConsoleLogger {
    debug: [Function],
    info: [Function],
    warn: [Function],
    error: [Function]
  },
  _traceParams: {
    numberOfAttributesPerSpan: 32,
    numberOfLinksPerSpan: 32,
    numberOfEventsPerSpan: 128
  },
  _spanProcessor: MultiSpanProcessor { _spanProcessors: [Array] }
},

Expandable end

Node.js: No spans are appearing in a short example application

If you’re using a short example application, you may need to explicitly shutdown the tracer to ensure that all spans are flushed:

1
opentelemetry.trace.getTracer('your_tracer_name').getActiveSpanProcessor().shutdown()

Expandable end

Java: Check that the exporter was installed

If the Java agent was correctly installed, the following lines are printed to the console:

1
2
3
[opentelemetry.auto.trace 2020-08-13 22:15:24:244 -0700] [main] INFO io.opentelemetry.auto.tooling.TracerInstaller - Installed span exporter: io.opentelemetry.exporters.otlp.OtlpGrpcSpanExporter
[opentelemetry.auto.trace 2020-08-13 22:15:24:250 -0700] [main] INFO io.opentelemetry.auto.tooling.PropagatorsInitializer - Added io.opentelemetry.extensions.trace.propagation.B3Propagator@7c0777b5 propagator
[opentelemetry.auto.trace 2020-08-13 22:15:24:252 -0700] [main] INFO io.opentelemetry.auto.tooling.VersionLogger - opentelemetry-javaagent - version: 0.7.0-SNAPSHOT~b659ee822

If the agent was not successfully installed, an error message similar to the below is printed near the beginning of the console output:

1
2
3
SEVERE: Invalid configuration: service name missing. Set environment variable LS_SERVICE_NAME.
Agent is not installed. Invalid configuration: service name missing. Set environment variable LS_SERVICE_NAME.

Expandable end

Check for multiple versions of OpenTelemetry

If multiple versions of OpenTelemetry are installed, traces are not created or propagated correctly. Check your dependencies to ensure that only a single version of OpenTelemetry is installed.

Expandable end

Check that security is configured correctly

Lightstep’s public satellites only accept spans via a secure endpoint. If you see security related errors (e.g., Netty TLS errors with Java), you may not have the necessary root certificate installed on the machine where the tracer is running. To add a root certificate, see the documentation about encrypted connections.

Expandable end

Python: gcc errors are appearing at installation

Compiling the grpc packages requires gcc and gcc-c++, which may need to be installed manually:

1
2
$ yum -y install python3-devel
$ yum -y install gcc-c++

Expandable end

Watch out for magic quotes

Sometimes, when configuring the start command in a text editor, regular quotation marks “” can be replaced with unicode quotation marks “”. This will cause the command to fail.

For example, the following command will fail due to several quotation marks being switched to unicode.

1
2
3
4
export LS_ACCESS_TOKEN="my-access-token"
export LIGHTSTEP_SERVICE_NAME=“pet-sounds”
java -javaagent:path/to/lightstep-opentelemetry-javaagent-<version>.jar \
-jar my_application.jar

Expandable end

More Information

Want more information about using OpenTelemetry? Check out our OpenTelemetry site and these language-specific guides: