Otelic Logo

What Are Trace Spans, and Why Are They Hierarchical?

Trace spans are the building blocks of a trace. Each span represents one specific step in a request, like a database query or an API call. They are hierarchical because spans are linked, showing how each part of the request depends on another. This hierarchy gives a clear picture of what happened in your app and helps you pinpoint issues faster.

1. What Is a Trace Span?

A span is a single operation in a trace. For example, if a user request involves a database query and an API call, there will be separate spans for each. Each span includes details like:

The operation name (e.g., "fetch-database").
Timestamps for when the operation started and ended.
Attributes like query details or API endpoint.

2. Why Are Spans Hierarchical?

Spans are hierarchical to show relationships between operations. Every span has a parent span (except the root span) and may have child spans. This hierarchy makes it easier to:

See how different parts of a request depend on one another.
Identify bottlenecks, like a slow database query.
Understand the complete path of a request.

3. How Does OpenTelemetry Capture Hierarchies?

OpenTelemetry automatically links spans together using context propagation. While OpenTelemetry is market's default way to instrument code, most popular libraries already has it inside automatically. Here’s an example of creating a root span and linking child spans in TypeScript:

1import { trace, context, SpanStatusCode } from '@opentelemetry/api';
2
3const tracer = trace.getTracer('example-service');
4
5// Create a root span
6const rootSpan = tracer.startSpan('process-request');
7
8// Propagate context so child spans inherit the trace ID and parent span
9context.with(trace.setSpan(context.active(), rootSpan), () => {
10  try {
11    // Create a child span for a database query
12    const dbSpan = tracer.startSpan('fetch-database', {
13      attributes: { query: 'SELECT * FROM users WHERE id = 123' },
14    });
15
16    // Simulate an error
17    const errorOccurred = false; // Change to true to simulate an error
18    if (errorOccurred) {
19      dbSpan.recordException(new Error('Database connection failed'));
20      dbSpan.setStatus({ code: SpanStatusCode.ERROR });
21    }
22
23    dbSpan.end();
24
25    // Create another child span for an API call
26    const apiSpan = tracer.startSpan('call-payment-api', {
27      attributes: { endpoint: '/payment', method: 'POST' },
28    });
29
30    apiSpan.end();
31  } catch (error) {
32    rootSpan.recordException(error);
33    rootSpan.setStatus({ code: SpanStatusCode.ERROR });
34  }
35});
36
37// End the root span
38rootSpan.end();
39

In this example, rootSpan represents the overall request, while dbSpan and apiSpan represent specific steps. Context propagation ensures they are all linked in a hierarchy.

4. Why Is Hierarchy Important for Debugging?

Hierarchical spans provide a clear timeline and structure for debugging. For example:

You can quickly find the root cause of slow requests.
Easily track how a single request moves across services.
Focus on specific spans instead of unrelated logs.

5. How Does Otelic.com Simplify This?

Otelic.com lets you visualize the entire span hierarchy in a user-friendly way. You can jump between spans and logs, ensuring no detail is missed. Combined with the market’s best pricing per GB, Otelic makes it affordable to keep more data for deeper insights without breaking your budget.

For support, contact us at support@otelic.com

© 2024 Otelic.com - All Rights Reserved.