---
title: Distributed tracing for your PHP services
source: https://docs.newrelic.com/docs/apm/agents/php-agent/configuration/distributed-tracing-php-agent
---

Distributed tracing allows you to see the entire journey of your requests throughout a [distributed system](https://docs.newrelic.com/docs/distributed-tracing/concepts/introduction-distributed-tracing). The PHP agent automatically instruments with distributed tracing a number of native PHP functions, as well as some third party HTTP clients:

-   PHP function [`file_get_contents`](http://php.net/manual/en/function.file-get-contents.php)
-   PHP functions [`curl_exec`](http://php.net/manual/en/function.curl-exec.php) and [`curl_multi_exec`](http://php.net/manual/en/function.curl-multi-exec.php)
-   Guzzle 4, Guzzle 5, Guzzle 6
-   Drupal's `drupal_http_request function`
-   Laravel's queue jobs

For the PHP agent, we offer two types of distributed tracing (for more details, see [How span sampling works](https://docs.newrelic.com/docs/understand-dependencies/distributed-tracing/get-started/how-new-relic-distributed-tracing-works#sampling)):

-   Standard (head-based sampling): Before any traces arrive, we determine a set percentage of traces to accept and analyze. This gives you a solid starting point to see how tracing can help you. It is turned on by default in PHP agents 9.21.0 and higher.

-   Infinite Tracing (tail-based sampling): Our cloud-based service accepts all your traces and then sorts through them to find the most important. Infinite tracing analyzes all of your traces and gives you configuration options to sample the traces that matter most to you.

Whether you just want to try out standard distributed tracing (head-based sampling) or also want to set up Infinite Tracing (tail-based sampling), you need to start by setting up standard tracing.

## Standard distributed tracing [#quick-start-apm]

This is the best approach to set up [standard distributed tracing](https://docs.newrelic.com/docs/distributed-tracing/concepts/how-new-relic-distributed-tracing-works/#head-based) if you haven't installed any APM agents for your services yet.

> #### 💡 TIP
>
> When you install the New Relic PHP agent, standard distributed tracing is turned on by default. If you prefer to turn it off, see our [configuration guide](https://docs.newrelic.com/docs/apm/agents/php-agent/configuration/php-agent-configuration).

### Identify services [#identify]

Figure out which services touch your request so you can instrument each of them to send trace data to New Relic.

### Instrument each service with an APM agent [#update-agents]

For each service involved in your transactions, you'll perform separate installations of the agent. If some of your services use other languages, simply repeat the [installation steps](https://docs.newrelic.com/docs/distributed-tracing/enable-configure/quick-start) for those languages.

To start the installation routine, click the tile below. When you're finished installing each agent, return here to see tips for [viewing your traces](#view-traces).

1.  [Start installation](https://one.newrelic.com/marketplace/install-data-source?account=2498654&duration=1800000&state=4166f468-4b5d-9d7f-4d1f-11a629edef2d)

### View traces [#view-traces]

After you instrument each of your services with APM agents, generate some traffic in your application so we can capture some traces. Here are some ways to view your traces in the UI:

**View traces that include a specific service**

Here's one way you can see traces for a particular service:

1.  Go to **[one.newrelic.com > All capabilities](https://one.newrelic.com/all-capabilities) > APM & services**.
2.  Click your entity (service).
3.  In the left pane's **Monitor** section, click **Distributed tracing**.
4.  For details, click on an individual trace. If **Group similar traces** is on in the top menu, click on a trace group, and then click on an individual trace.
5.  If you don't see the traces you want, you can filter by the `trace.id`.

**View traces across accounts**

To see traces that cross accounts:

1.  Go to **[one.newrelic.com > All capabilities](https://one.newrelic.com/all-capabilities) > Traces**.
2.  Select your entity (service) in the left pane.
3.  For details, click on an individual trace. If **Group similar traces** is on in the top menu, click on a trace group, and then click on an individual trace.
4.  If you don't see the traces you want, you can filter by the `trace.id`.

**Examine logs related to traces**

You can bring your logs and tracing details together to make troubleshooting easier and faster. With [logs in context](https://docs.newrelic.com/docs/logs/logs-context/configure-logs-context-apm-agents/), you can see log messages alongside traces in the New Relic UI.

After you've located an interesting trace using the steps in [View traces that include a specific service](#entity-explorer) or [View traces across accounts](#cross-acct-traces), do the following:

1.  If you've enabled logs in context, click on the **Logs** tab (next to **Trace details**).
2.  To view details related to an individual log, click directly on the message.

For more help finding your traces in the UI:

-   [Understand and use the distributed tracing UI](https://docs.newrelic.com/docs/distributed-tracing/ui-data/understand-use-distributed-tracing-ui)
-   [Query distributed trace data](https://docs.newrelic.com/docs/understand-dependencies/distributed-tracing/ui-data/query-distributed-trace-data)

## Infinite Tracing [#infinite-tracing]

[Standard distributed tracing](#quick-start-apm) for APM agents [captures up to 10 traces per minute](https://docs.newrelic.com/docs/distributed-tracing/concepts/how-new-relic-distributed-tracing-works/#trace-origin-sampling), but if you want us to analyze all your data and find the most relevant traces, you can set up [Infinite Tracing](https://docs.newrelic.com/docs/understand-dependencies/distributed-tracing/infinite-tracing/introduction-infinite-tracing).

Before you start, first ensure you meet [the requirements](https://docs.newrelic.com/docs/understand-dependencies/distributed-tracing/infinite-tracing/introduction-infinite-tracing#requirements).

### Complete the setup for standard distributed tracing [#install-agents-first]

The Infinite Tracing setup builds on standard distributed tracing. So, make sure you've completed the [steps above](#quick-start-apm), and then continue with the trace observer setup.

### Set up the trace observer [#provision-trace-observer]

The trace observer is a New Relic AWS-based service that collects and analyzes all your traces. Follow the instructions in [Set up trace observer](https://docs.newrelic.com/docs/understand-dependencies/distributed-tracing/infinite-tracing/set-trace-observer). When you're done, return here with your trace observer information and continue with the next step to configure the agent.

### Configure the agent for Infinite Tracing [#configure-agent-inf]

Infinite Tracing configuration settings include the standard distributed tracing plus information about the trace observer. Note that server-side configuration is not available for Infinite Tracing.

**PHP Infinite Tracing configurations**

Here's an overview of the settings. For more help with configuration, see [PHP agent configuration](https://docs.newrelic.com/docs/apm/agents/php-agent/configuration/php-agent-configuration).

| Type             | Required configuration                                                                                                                                                                                                                                                                                                                              |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Infinite Tracing | Configuration options: - Configuration file (`newrelic.ini`): ```ini newrelic.distributed_tracing_enabled = true newrelic.span_events_enabled = true newrelic.infinite_tracing.trace_observer.host= "<a href="/docs/understand-dependencies/distributed-tracing/infinite-tracing/set-trace-observer#ui-endpoints">YOUR_TRACE_OBSERVER_HOST</a>" ``` |

> #### 💡 TIP
>
> If you need help with proxy configuration, see [Proxy support](https://docs.newrelic.com/docs/understand-dependencies/distributed-tracing/other-requirements/infinite-tracing-proxy-support).

### (Optional) Customize Infinite Tracing [#customize-agent-inf]

After you add the agent configuration settings, you should start seeing data in the New Relic UI. After you spend some time analyzing your data, you may want to adjust some of the features of Infinite Tracing:

-   [Configure trace observer monitoring](https://docs.newrelic.com/docs/distributed-tracing/infinite-tracing/infinite-tracing-configure-trace-observer-monitoring)
-   [Configure span attribute trace filter](https://docs.newrelic.com/docs/distributed-tracing/infinite-tracing/infinite-tracing-configure-span-attribute-trace-filter)
-   [Configure random trace filter](https://docs.newrelic.com/docs/distributed-tracing/infinite-tracing/infinite-tracing-configure-random-trace-filter)

## Set trace detail level [#performance]

Distributed tracing support depends on the PHP agent's [transaction tracer](https://docs.newrelic.com/docs/agents/php-agent/configuration/php-agent-configuration#inivar-tt-enable). When [distributed tracing is enabled](#enable-distributed), a [span](https://docs.newrelic.com/docs/apm/distributed-tracing/ui-data/distributed-tracing-attributes) is created for each segment seen by the transaction tracer.

As [spans are sampled](https://docs.newrelic.com/docs/apm/distributed-tracing/getting-started/how-new-relic-distributed-tracing-works), the PHP agent will prioritize spans related to external calls above other spans, which are then recorded in descending order of their duration.

If you find that there are too many unimportant spans being reported for PHP function calls, you can reduce the detail of the transaction tracer by setting [`newrelic.transaction_tracer.detail`](https://docs.newrelic.com/docs/agents/php-agent/configuration/php-agent-configuration#inivar-tt-detail) to `0`. You may then use the [`newrelic.transaction_tracer.custom`](https://docs.newrelic.com/docs/agents/php-agent/configuration/php-agent-configuration#inivar-tt-custom) configuration setting or the [`newrelic_add_custom_tracer`](https://docs.newrelic.com/docs/agents/php-agent/php-agent-api/newrelic_add_custom_tracer) API method to add trace segments and spans for the specific PHP function or methods you want to add to your traces.

> #### ⚠️ IMPORTANT
>
> For PHP agent versions 8.4 to 8.7: When distributed tracing is enabled, these versions behave as if [`newrelic.transaction_tracer.detail`](https://docs.newrelic.com/docs/agents/php-agent/configuration/php-agent-configuration#inivar-tt-detail) is set to `0` (as described above), which results in PHP function calls not generating spans. To get spans related to PHP function calls, update to version 9.0 or higher.

## Manually instrument applications and services with PHP agent API [#manual]

> #### ⚠️ IMPORTANT
>
> W3C Trace Context support was added in version 9.8. With this, the API for manually instrumenting applications has changed from the JSON payload related functions:
>
> ```php
> newrelic_create_distributed_trace_payload()
> newrelic_accept_distributed_trace_payload($payload)
> ```
>
> To the header array forms:
>
> ```php
> newrelic_insert_distributed_trace_headers($outbound_headers)
> newrelic_accept_distributed_trace_headers($inbound_headers)
> ```
>
> The JSON functions are now considered deprecated, and will be removed in a future release.

If you're using an unsupported library, or have a non-HTTP based distributed system component (such as messaging queues), you can use the PHP agent API to manually identify transactions to be included in a distributed trace. This is a two step process:

1.  Modify your service or application to **create** or **insert** the distributed tracing data
2.  Modify your service or application to **accept** distributed trace data created by other transactions or requests.

The following example uses a generic message/job queue. While the actual details will vary depending on what sort of system you're trying to add to a distributed trace, the core concepts are the same. Also, while we've used a job queue as an example, you can use these methods with **any** distributed system component.

> #### 💡 TIP
>
> When you **create a payload** or **insert headers**, you're telling New Relic you want this request or transaction or request to participate in a distributed trace. When you **accept** them, you're linking the current request or transaction with its parent request or transaction.

For more information about using manual instrumentation to get more detail or to see connections between services, see the documentation about [distributed tracing APIs](https://docs.newrelic.com/docs/apm/distributed-tracing/enable-configure/enable-distributed-tracing#agent-apis).

### Header API [#header-api]

**Insert distributed trace headers**

Somewhere in your application you'll have code that looks or acts like the following:

````php
// create a job object
$job = new \Generic\Queue\Job;

// set the information needed to run the queue job
$job->setData('info', $info);

// save the job
$job->save();
```

If you want this job to appear in a distributed trace, you need to insert distributed trace headers into an array by using `newrelic_insert_distributed_trace_headers`, and then add those headers to the job's data:

```php
$outbound_headers = array();
if (newrelic_insert_distributed_trace_headers($outbound_headers)) {

    // create a job object
    $job = new \Generic\Queue\Job;

    // set the information needed to run the queue job
    $job->setData('info', $info);

    // add the headers to the job data
    $job->setData('nr_dt_headers', $outbound_headers);

    // save the job
    $job->save();
} else {
    echo "Unable to obtain distributed tracing headers";
}
```

<Callout variant="tip">
  Tip: The headers created via `newrelic_insert_distributed_trace_headers()` are HTTP safe.
</Callout>

This is step one: You've inserted the distributed trace headers.

````

**Accept the distributed tracing headers**

Next, somewhere in your application stack you'll have a queue runner that looks or acts like the following:

````php
// create the job runner
$jobRunner = \Generic\Queue\Runner;

// grab jobs until there aren't any
while($job = $jobRunner->next()) {
    // run the job
    $job->run();
}
```

In order to accept distributed trace headers, use the `newrelic_accept_distributed_trace_headers` function

```php
// create the job runner
$jobRunner = \Generic\Queue\Runner;

while($job = $jobRunner->next()) {
    $inbound_headers = $job->getData('nr_dt_headers');
    if($inbound_headers) {
        newrelic_accept_distributed_trace_headers($inbound_headers);
    }
    $job->run();
}
```

````

### Payload API (deprecated)

**Create a distributed trace payload**

Somewhere in your application you'll have code that looks or acts like the following:

````php
// create a job object
$job = new \Generic\Queue\Job;

// set the information needed to run the queue job
$job->setData('info', $info);

// save the job
$job->save();
```

If you want this job to appear in a distributed trace, you need to create a distributed trace payload using `newrelic_create_distributed_trace_payload`, and then add that payload to the job's data:

```php
$payload = newrelic_create_distributed_trace_payload();

// create a job object
$job = new \Generic\Queue\Job;

// set the information needed to run the queue job
$job->setData('info', $info);

// add the payload data to the job data as a text json string
$job->setData('dt_payload', $payload->Text());

// save the job
$job->save();
```

This is step one: You've created a distributed trace payload.

````

**Accept the distributed tracing payload**

Next, somewhere in your application stack you'll have a queue runner that looks or acts like the following:

````php
// create the job runner
$jobRunner = \Generic\Queue\Runner;

// grab jobs until there aren't any
while($job = $jobRunner->next()) {
    // run the job
    $job->run();
}
```

In order to accept a distributed trace payload, use the `newrelic_accept_distributed_trace_payload` function

```php
// create the job runner
$jobRunner = \Generic\Queue\Runner;

while($job = $jobRunner->next()) {
    $payload = $job->getData('dt_payload');
    if($payload) {
        newrelic_accept_distributed_trace_payload($payload);
    }
    $job->run();
}
```

````

**Optional: Use HTTP safe payload strings**

If you need to transport the payload via a mechanism that requires HTTP safe strings, (HTTP headers, URL query strings, POST fields, etc.), the API includes distributed tracing methods and functions that will create and accept HTTP safe versions of the strings.

````php
// create the HTTP safe payload string 
$payload = newrelic_create_distributed_trace_payload();
$httpSafePayload = $payload->httpSafe();

// ...

// accept the HTTP safe payload string
newrelic_accept_distributed_trace_payload_httpsafe($httpSafePayload);
```

````

## Command line PHP programs [#command-line]

PHP programs run from the PHP command line are always sampled by the agent's distributed tracer. Depending on the programs you run, these processes could see an over-representation in your collection of distributed traces. In these situations, you can opt to disable command line instrumentation by using the [`per-directory newrelic.enabled`](https://docs.newrelic.com/docs/agents/php-agent/configuration/php-agent-configuration) setting in your `newrelic.ini files`.
