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

# PHP custom instrumentation

The AppSignal for PHP package provides out-of-the-box instrumentations for your PHP application. However, sometimes you need fine-grained observability, which requires manual instrumentation. For these cases, use the `Appsignal::instrument` method and customize the data sent to AppSignal using the helper methods.

<Warning>
  Data sent to AppSignal must not contain any personal data, such as names or
  email addresses. Sanitize your application's data before sending it to
  AppSignal. If you need to identify a person, use alternatives like a user ID,
  hash, or pseudonym.
</Warning>

## Creating spans

The `Appsignal` class provides a helper for creating spans.

### `instrument`

Creates and activates a new span. Pass a closure to have the span closed automatically, or omit it to manage the span lifecycle manually.

#### With a closure

If you use a closure, AppSignal closes the active span automatically.

```php PHP theme={null}
Appsignal::instrument(
	name: 'process-order',
	attributes: ['order_id' => $orderId],
	closure: function () {
		// do work here
		Appsignal::setAttributes(['order_status' => 'processed']);
	},
);
```

#### Without a closure

Without a closure, the `instrument` method returns an instance of the `ActiveSpan` class, a thin wrapper around the OpenTelemetry span and its scope. Close this span manually by calling `$span->end()`.

```php PHP theme={null}
$activeSpan = Appsignal::instrument(
	name: 'upload-file',
	attributes: ['file_name' => $filename],
);

try {
    uploadFile($file);
} catch (Throwable $e) {
    Appsignal::setError($e);
} finally {
    $activeSpan->end();
}
```

## Helpers

The base `Appsignal` class provides helper methods to add custom data to traces or spans. The following sections describe each helper.

<Note>
  The code examples below assume your code is already being instrumented (for
  example, inside a Laravel or Symfony route handler). If your code is not
  already instrumented, you must create a root span by calling
  `Appsignal::instrument()` and use the helpers inside of it.
</Note>

### `addAttributes`

Add attributes to the current span.

```php PHP theme={null}
Appsignal::addAttributes([
    'user_id'   => $user->id,
    'user_plan' => $user->plan,
]);
```

### `addHeaders`

Adds request headers to the current span. If the header name already exists, the value is overwritten. Request headers are shown for sampled traces in AppSignal. See [the Request header customization guide](/guides/custom-data/request-headers) for more information.

```php PHP theme={null}
Appsignal::addHeaders(['custom-header' => 'some-value']);
```

### `addTags`

Add tags to the current span. Tags appear as filterable metadata in AppSignal and are prefixed with `appsignal.tag.` internally.

```php PHP theme={null}
Appsignal::addTags([
    'locale'  => 'en',
    'version' => '2.1.0',
]);
```

See the [tagging guide](/guides/tagging) for more information on how tags work in AppSignal.

### `setAction`

Sets the action name on the current span. AppSignal displays this as the transaction name and uses it to group samples.

```php PHP theme={null}
Appsignal::setAction('OrdersController::create');
```

### `setNamespace`

Sets the namespace of the root span.

```php PHP theme={null}
Appsignal::setNamespace('admin');
```

### `setParams`

Set the query parameters of the incoming request. The `$params` must be a value that [can be serialized as JSON](https://www.php.net/manual/en/function.json-encode.php).

```php PHP theme={null}
$params = [
    'param1' => 'value1',
    'param2' => 'value2',
    'nested' => [
        'param3' => 'value3',
        'param4' => 'value4',
    ],
];

Appsignal::setParams($params);
```

### `setPayload`

Set the payload of the incoming request. The `$payload` must be a value that [can be serialized as JSON](https://www.php.net/manual/en/function.json-encode.php).

```php PHP theme={null}
$payload = [
    'key1' => 'value1',
    'key2' => 'value2',
    'nested' => [
        'key3' => 'value3',
        'key4' => 'value4',
    ],
];

Appsignal::setPayload($payload);
```

## `ActiveSpan`

`Appsignal::instrument()` returns an `ActiveSpan` instance that proxies all standard OpenTelemetry API `SpanInterface` [methods](https://open-telemetry.github.io/opentelemetry-php/classes/OpenTelemetry-API-Trace-SpanInterface.html). If you need low-level control over the span, use these methods to attach data or events to it directly.

```php PHP theme={null}
$activeSpan = Appsignal::instrument('render-report');
$activeSpan->setAttribute('report.type', 'pdf');
$activeSpan->addEvent('rendering-started');

someExpensiveMethod();

$activeSpan->end();
```
