> ## 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.

# Using the New Relic Python agent with LaunchDarkly

<View title="Developer" />

<View title="Federal docs">
  <Danger>
    **Observability is not available in federal environments**

    To learn more, read <a href="/docs/home/infrastructure/federal">LaunchDarkly in federal environments</a>.
  </Danger>
</View>

<View title="EU docs" />

This topic explains how to use the LaunchDarkly [Python observability plugin](/docs/sdk/observability/python) with the [New Relic Python agent](https://docs.newrelic.com/docs/apm/agents/python-agent/getting-started/introduction-new-relic-python/) to send traces with feature flag evaluation data to LaunchDarkly.

If your application already uses the New Relic Python agent, you can turn on the LaunchDarkly integration that the agent includes. The integration connects the agent to the LaunchDarkly Python SDK and its observability plugin. The agent continues to send data to New Relic. It also adds feature flag evaluation data to the span that was active when your application evaluated a flag, and sends a copy of each span to LaunchDarkly through the observability plugin. This telemetry is available on the [Traces](/docs/home/observability/traces) page and in other observability features in the LaunchDarkly UI.

<Note>
  **This integration is in preview**

  The LaunchDarkly integration in the New Relic Python agent is a preview feature, available in `newrelic` version 14.0.0 and later. It is turned off by default. Its configuration and behavior may change in later agent releases.

  LaunchDarkly observability features are publicly available in early access. Enable observability in the billing page.
</Note>

## Prerequisites

To complete this procedure, you need:

* LaunchDarkly observability enabled for your project.
* A Python application running Python 3.10 or higher.
* The [New Relic Python agent](https://pypi.org/project/newrelic/), version 14.0.0 or later, configured with your New Relic license key.
* The LaunchDarkly [Python SDK](/docs/sdk/server-side/python), version 9.12.0 or later.
* The LaunchDarkly [Python SDK observability plugin](/docs/sdk/observability/python).

## How the integration works

When you turn on the integration, the New Relic Python agent and the LaunchDarkly SDKs work together in the following ways:

* When your application creates the LaunchDarkly SDK `Config`, the agent adds a New Relic hook to it. You do not need to register the hook yourself. To learn more, read [Hooks](/docs/sdk/features/hooks).
* After each flag evaluation, the hook adds feature flag attributes to the New Relic span that is active at the time of the evaluation.
* When a New Relic transaction finishes, the agent sends its spans to LaunchDarkly using the tracer from the LaunchDarkly observability plugin. The agent skips spans that came from OpenTelemetry instrumentation, because the observability plugin already exports those spans.

The hook only adds attributes when a flag evaluation happens inside a New Relic transaction, such as a web request or a background task that the agent instruments.

## Install the packages

To install the New Relic agent, the LaunchDarkly SDK, and the observability plugin:

<CodeGroup>
  ```bash title="Shell" lines wrap theme={null}
  pip install "newrelic>=14.0.0" launchdarkly-server-sdk launchdarkly-observability
  ```
</CodeGroup>

## Turn on the integration

The integration requires two New Relic agent settings: the LaunchDarkly integration setting and the agent's OpenTelemetry setting. The agent only sends spans to LaunchDarkly when both settings are `true`.

You can set them with environment variables:

<CodeGroup>
  ```bash title="Environment variables" lines wrap theme={null}
  export NEW_RELIC_LAUNCH_DARKLY_ENABLED=true
  export NEW_RELIC_OPENTELEMETRY_ENABLED=true
  ```
</CodeGroup>

Or you can set them in your `newrelic.ini` configuration file:

<CodeGroup>
  ```ini title="newrelic.ini" lines wrap theme={null}
  [newrelic]
  license_key = YOUR_NEW_RELIC_LICENSE_KEY
  app_name = example-service

  launch_darkly_integration.enabled = true
  opentelemetry.enabled = true
  ```
</CodeGroup>

The integration also uses New Relic distributed tracing and span events. Both are turned on by default in the New Relic Python agent. If you have turned either one off, turn it back on.

## Initialize the SDK and the observability plugin

The New Relic agent must start before your application imports `ldclient`, so that the agent can add its hook to the SDK configuration. You can start the agent with the `newrelic-admin` wrapper script, or by calling `newrelic.agent.initialize()` at the top of your application's entry point.

Then, initialize the LaunchDarkly SDK with the observability plugin. The plugin must be registered for the integration to work. If the integration is turned on and the plugin is not registered, the agent logs a warning when the SDK client starts.

Here is an example Flask application:

<CodeGroup>
  ```python title="app.py" lines wrap theme={null}
  import newrelic.agent

  # Start the New Relic agent before importing ldclient
  newrelic.agent.initialize("newrelic.ini")

  import ldclient
  from ldclient import Context
  from ldclient.config import Config
  from ldobserve import ObservabilityConfig, ObservabilityPlugin
  from flask import Flask

  plugin = ObservabilityPlugin(
      ObservabilityConfig(
          service_name="example-service",
          # We recommend setting service_version to the latest deployed git SHA
          service_version="example-sha",
      )
  )

  ldclient.set_config(Config("YOUR_SDK_KEY", plugins=[plugin]))
  client = ldclient.get()

  app = Flask(__name__)


  @app.route("/")
  def index():
      context = Context.builder("user-key-123abc").kind("user").build()
      # The New Relic hook adds flag data to the span for this request
      if client.variation("new-checkout-flow", context, False):
          return "New checkout flow"
      return "Current checkout flow"
  ```
</CodeGroup>

If you start the agent with the wrapper script instead, remove the `newrelic.agent.initialize()` call and run your application like this:

<CodeGroup>
  ```bash title="Shell" lines wrap theme={null}
  NEW_RELIC_CONFIG_FILE=newrelic.ini newrelic-admin run-program flask --app app run
  ```
</CodeGroup>

To learn more about plugin options, read [Configuration for server-side observability](/docs/sdk/features/observability-config-server-side).

## Review feature flag attributes

The New Relic hook adds the following attributes to the active span for each flag evaluation:

<table>
  <thead>
    <tr>
      <th>Attribute</th>
      <th>Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td><code>feature\_flag.key</code></td>
      <td>The key of the evaluated flag.</td>
    </tr>

    <tr>
      <td><code>feature\_flag.provider.name</code></td>
      <td>Set to <code>LaunchDarkly</code>.</td>
    </tr>

    <tr>
      <td><code>feature\_flag.context.id</code></td>
      <td>The key of the LaunchDarkly context used in the evaluation.</td>
    </tr>

    <tr>
      <td><code>feature\_flag.result.value</code></td>
      <td>The evaluation result. The hook omits this attribute when the result is a falsy value, such as <code>False</code> or an empty string.</td>
    </tr>

    <tr>
      <td><code>feature\_flag.result.variationIndex</code></td>
      <td>The index of the variation served, when available.</td>
    </tr>

    <tr>
      <td><code>feature\_flag.result.reason.kind</code></td>
      <td>The kind of evaluation reason, such as <code>FALLTHROUGH</code> or <code>RULE\_MATCH</code>.</td>
    </tr>

    <tr>
      <td><code>feature\_flag.result.reason.inExperiment</code></td>
      <td>Set to <code>true</code> when the evaluation is part of an experiment.</td>
    </tr>

    <tr>
      <td><code>feature\_flag.set.id</code></td>
      <td>The LaunchDarkly environment ID, when the SDK provides it.</td>
    </tr>
  </tbody>
</table>

The hook adds these attributes as New Relic custom attributes. They also appear on the span in New Relic.

LaunchDarkly uses these attributes to connect traces to flag evaluations. After LaunchDarkly receives these traces, you can use them with [OpenTelemetry autogenerated metrics](/docs/home/metrics/autogen/opentelemetry) and [guarded rollouts](/docs/home/releases/guarded-rollouts). To learn more, read [Creating guarded rollouts](/docs/home/releases/creating-guarded-rollouts).

## Verify that data is being received

After you configure the integration and your application handles traffic, traces begin flowing to LaunchDarkly. It can take a few minutes for data to appear.

To verify that traces are being received:

1. Open the **Telemetry** section and navigate to the **Traces** list.
2. Search for traces from the service name you set in `ObservabilityConfig`.
3. Open a trace from a request that evaluated a flag, and confirm that a span includes the `feature_flag.key` attribute.

If no traces appear, check your application logs for New Relic agent warnings. The agent logs a warning if the observability plugin is not registered with the SDK client.

## Limitations

The preview integration has the following limitations:

* The agent only sends traces to LaunchDarkly. It does not send New Relic metrics or logs. To send logs and errors to LaunchDarkly, use the [Python observability plugin](/docs/sdk/observability/python) directly.
* The agent only adds the hook when the New Relic agent starts before your application creates the LaunchDarkly SDK `Config`.
* Flag evaluations outside a New Relic transaction do not add attributes to any span.
