> ## Documentation Index
> Fetch the complete documentation index at: https://launchdarkly.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Recording traces

<View title="Developer" />

<View title="Federal docs" />

<View title="EU docs" />

This topic explains how to record traces through the SDK observability plugin.

You can view all traces sent to LaunchDarkly under **Traces** in the LaunchDarkly user interface. To learn more, read [Traces](/docs/home/observability/traces).

Details about each SDK's configuration are available in the SDK-specific sections below:

* [Client-side SDKs](#client-side-sdks)
* [Server-side SDKs](#server-side-sdks)

## Client-side SDKs

This feature is available in the observability plugin for the following client-side SDKs:

* [iOS](#ios)
* [Android](#android)
* [Flutter](#flutter)
* [JavaScript](#javascript)
* [React Native](#react-native)
* [React Web](#react-web)
* [Vue](#vue)

### iOS

<Accordion title="Expand iOS code sample">
  To build and start a new span:

  <CodeGroup>
    ```swift title="Start a new span" lines wrap theme={null}
      let span = LDObserve.shared.startSpan(name: "exampleSpan", attributes: attributes)
      // This span ends when you call span.end()
      span.end()
    ```
  </CodeGroup>

  The attributes argument should include the details to record with the span. To construct it, use `Attributes` from the [`@opentelemetry/api`](https://opentelemetry.io/docs/specs/semconv/general/attributes/).
</Accordion>

### Android

<Accordion title="Expand Android code sample">
  To start a new span:

  <CodeGroup>
    ```java title="Start a new span" lines wrap theme={null}
      LDObserve.startSpan("exampleSpan", attributes)
    ```
  </CodeGroup>

  The attributes argument should include the details to record with the span. To construct it, use `Attributes` from the [`@opentelemetry/api`](https://opentelemetry.io/docs/specs/semconv/general/attributes/).
</Accordion>

### Flutter

<Accordion title="Expand Flutter code sample">
  Use `LDObserve.startSpan` to create a span. Call `span.end()` when the operation completes:

  <CodeGroup>
    ```dart title="Start a span" lines wrap theme={null}
      final span = LDObserve.startSpan('api_request');
      span.setAttribute('endpoint', '/api/users');
      span.setAttribute('method', 'GET');
      span.addEvent('cache.miss');
      span.setStatus(SpanStatusCode.ok);
      span.end();
    ```
  </CodeGroup>

  `startSpan` automatically creates parent-child relationships. Each new span becomes a child of the currently active span.

  <CodeGroup>
    ```dart title="Nested spans" lines wrap theme={null}
      final parent = LDObserve.startSpan('ProcessOrder');
      final child = LDObserve.startSpan('ValidatePayment');
      // child is automatically nested under parent
      child.end();
      parent.end();
    ```
  </CodeGroup>

  End nested spans in reverse order of starting them. Calling `end()` again on a span that already ended does nothing.

  For asynchronous work, use `LDObserve.withSpan` instead. It runs a function inside a new span and ends the span when the function returns or its `Future` completes, and it keeps the span current across `await` boundaries:

  <CodeGroup>
    ```dart title="Scoped span" lines wrap theme={null}
      final orders = await LDObserve.withSpan('load-orders', (span) async {
        span.setAttribute('page', 1);
        return api.fetchOrders(page: 1);
      });
    ```
  </CodeGroup>

  If the function throws an error, or its future fails, the plugin records the error on the span, sets the span status to `SpanStatusCode.error`, and rethrows the error unchanged.
</Accordion>

### JavaScript

<Accordion title="Expand JavaScript code sample">
  The observability plugin provides two options for starting new spans:

  * `startSpan()` ends the span automatically after the callback function completes, whether it returns normally or throws an error
  * `startManualSpan()` ends the span when you call `span.end()`

  To start a new span:

  <CodeGroup>
    ```js title="Automatic span" lines wrap theme={null}
      // This span ends automatically after the callback completes
      LDObserve.startSpan('fetchData', (span) => {
        // Your code here
      });

    ```

    ```js title="Manual span" lines wrap theme={null}
      // This span ends when you call span.end()
      LDObserve.startManualSpan('fetchData', (span) => {
        // Your code here

        span.end()
      });
    ```
  </CodeGroup>

  To learn more, read [`startSpan`](https://launchdarkly.github.io/observability-sdk/packages/@launchdarkly/observability/interfaces/api_observe.Observe.html#startspan) and [`startManualSpan`](https://launchdarkly.github.io/observability-sdk/packages/@launchdarkly/observability/interfaces/api_observe.Observe.html#startmanualspan).
</Accordion>

### React Native

<Accordion title="Expand React Native code sample">
  The observability plugin provides a few options for starting new spans:

  * [`startSpan()`](https://launchdarkly.github.io/observability-sdk/sdk/@launchdarkly/observability-react-native/interfaces/Observe.html#startspan) starts a new span without making it active
  * [`startActiveSpan()`](https://launchdarkly.github.io/observability-sdk/sdk/@launchdarkly/observability-react-native/interfaces/Observe.html#startactivespan) starts a new span, makes it active, and runs a callback function within its context
  * [`startWithHeaders()`](https://launchdarkly.github.io/observability-sdk/sdk/@launchdarkly/observability-react-native/interfaces/Observe.html#startwithheaders) starts a new span with header context

  Here's an example:

  <CodeGroup>
    ```js title="Start an active span and run a callback" lines wrap theme={null}
      // This span ends automatically after the callback completes
      LDObserve.startActiveSpan('exampleSpan', (span) => {
        // Your callback function here
      });

    ```
  </CodeGroup>

  To learn more, read [`Observe`](https://launchdarkly.github.io/observability-sdk/sdk/@launchdarkly/observability-react-native/interfaces/Observe.html).
</Accordion>

### React Web

To start new spans with the React Web SDK, follow the example for [JavaScript](#javascript).

### Vue

To start new spans with the React Web SDK, follow the example for [JavaScript](#javascript).

## Server-side SDKs

This feature is available in the observability plugin for the following server-side SDKs:

* [.NET (server-side)](#net-server-side)
* [Go](#go)
* [Node.js (server-side)](#node-js-server-side)
* [Python](#python)

### .NET (server-side)

<Accordion title="Expand .NET (server-side) code sample">
  To start new spans within the observability plugin for .NET (server-side) SDK, use `StartActivity`. By default, it records any exceptions as error events on the span, and sets the span's status appropriately.

  Here's how:

  <CodeGroup>
    ```csharp title="Example: Starting a span" lines wrap theme={null}
            using (var activity = Observe.StartActivity("example-span", ActivityKind.Internal,
                       new Dictionary<string, object> { { "example-attribute", "example-value" } }))
            {
                activity.SetTag("added-attribute", "added-attribute-value");
                return "Hello world!";
            }
    ```
  </CodeGroup>

  This method requires the `Name` of the span. Optionally, you can pass in `attributes` and specify whether to record an exception or set the span's status if there is an exception. To construct the attributes argument, use `Attributes` from the [`@opentelemetry/api`](https://opentelemetry.io/docs/specs/semconv/general/attributes/).

  To learn more, read [`StartActivity`](https://launchdarkly.github.io/observability-sdk/sdk/@launchdarkly/observability-dotnet/api/LaunchDarkly.Observability.Observe.html#LaunchDarkly_Observability_Observe_StartActivity_System_String_System_Diagnostics_ActivityKind_System_Collections_Generic_IDictionary_System_String_System_Object__).
</Accordion>

### Go

<Accordion title="Expand Go code sample">
  To start new spans with in the observability plugin for the Go SDK, use `StartSpan()`. By default, this records any exceptions as error events on the span and sets the span's status appropriately.

  Here's how:

  <CodeGroup>
    ```go title="Example: Working with a span" lines wrap theme={null}
      _, span := ldobserve.StartSpan(ctx, "example-span", []trace.SpanStartOption{})
      span.SetAttributes(attribute.String("example-attribute", "example-value"))
      span.End()
    ```
  </CodeGroup>

  The `StartSpan` method requires a Go `context.Context`, the `name` of the span, and an array of the [OpenTelemetry options for starting a span](https://pkg.go.dev/go.opentelemetry.io/otel/trace#SpanStartOption). You can optionally pass an array of [attributes from the OpenTelemetry specification](https://pkg.go.dev/go.opentelemetry.io/otel/log#KeyValue).

  To learn more, read [`StartSpan`](https://pkg.go.dev/github.com/launchdarkly/observability-sdk/go#StartSpan).
</Accordion>

### Node.js (server-side)

<Accordion title="Expand Node.js (server-side) code sample">
  The Node.js (server-side) SDK's observability plugin uses the [OpenTelemetry Tracing API](https://opentelemetry.io/docs/specs/otel/trace/api/) to work with spans.

  Additionally, it provides the following functions for working with spans:

  * `setAttributes()` sets attributes on the active span
  * `startWithHeaders()` starts a span with information from the request headers
  * `runWithHeaders()` runs a callback with information from the request headers and returns the result

  Here's an example:

  <CodeGroup>
    ```js title="Example: Starting and running a span" expandable lines wrap theme={null}
      app.get("/start-span-example", (req: Request, res: Response) => {
        const {span} = LDObserve.startWithHeaders('example-span-a', req.headers);

        LDObserve.setAttributes({
          "example-attribute": "example-value",
        });

        res.send("Hello World");
        span.end();
      });

      app.get("/run-span-example", async (req: Request, res: Response) => {
        await LDObserve.runWithHeaders('example-span-b', req.headers, (span) => {
          LDObserve.setAttributes({
            "example-attribute": "example-value",
          });

          res.send("Hello World");
        });
      });
    ```
  </CodeGroup>

  To learn more, read [`Observe`](https://launchdarkly.github.io/observability-sdk/sdk/@launchdarkly/observability-node/interfaces/Observe.html).
</Accordion>

### Python

<Accordion title="Expand Python code sample">
  To start new spans with in the observability plugin for Python SDK, use `start_span`. This method is a context manager for creating a new span. By default, it records any exceptions as error events on the span, sets the span's status appropriately. Exiting the context manager calls the span's `end` method.

  Here's how:

  <CodeGroup>
    ```python title="Example: Starting a span" lines wrap theme={null}
        with observe.start_span("manual-span", attributes={"custom": "value"}) as span:
            span.set_attribute("my-attribute", "my-value")
            # Any user defined code I want to capture.
    ```
  </CodeGroup>

  This method requires the `name` of the span. Optionally, you can pass in `attributes` and specify whether to record an exception or set the span's status if there is an exception. To construct the attributes argument, use `Attributes` from the [`@opentelemetry/api`](https://opentelemetry.io/docs/specs/semconv/general/attributes/).

  To learn more, read [`start_span`](https://launchdarkly.github.io/observability-sdk/sdk/@launchdarkly/observability-python/ldobserve/observe.html#start_span).
</Accordion>
