Documentation Index
Fetch the complete documentation index at: https://docs.bronto.io/llms.txt
Use this file to discover all available pages before exploring further.
This page covers instrumenting a PHP application with the OpenTelemetry SDK to send logs and traces to Bronto over OTLP/HTTP via a local OTel Collector. Logs are bridged via a Monolog handler — no log statement changes needed. Traces are added by configuring a tracer provider alongside the log provider.
If you don’t have a Collector and want to export directly from your application to Bronto, see Direct export to Bronto at the bottom of this page.
Prerequisites
Install dependencies
composer require \
open-telemetry/api \
open-telemetry/sdk \
open-telemetry/exporter-otlp \
open-telemetry/opentelemetry-logger-monolog \
monolog/monolog \
php-http/guzzle7-adapter \
guzzlehttp/psr7
| Package | Purpose |
|---|
open-telemetry/api | Core OTel API |
open-telemetry/sdk | SDK — LoggerProvider, processors, resource |
open-telemetry/exporter-otlp | OTLP/HTTP exporter |
open-telemetry/opentelemetry-logger-monolog | Bridges Monolog into OTel |
php-http/guzzle7-adapter | HTTP client for the exporter |
Set up a LoggerProvider with an OTLP exporter and attach the OtelHandler to your Monolog logger.
<?php
use Monolog\Logger;
use OpenTelemetry\Contrib\Logs\Monolog\Handler as OtelHandler;
use OpenTelemetry\Contrib\Otlp\LogsExporter;
use OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory;
use OpenTelemetry\SDK\Common\Attribute\Attributes;
use OpenTelemetry\SDK\Logs\LoggerProvider;
use OpenTelemetry\SDK\Logs\Processor\BatchLogRecordProcessor;
use OpenTelemetry\SDK\Resource\ResourceInfo;
use OpenTelemetry\SemConv\ResourceAttributes;
function configureOtelLogging(): Logger
{
$resource = ResourceInfo::create(Attributes::create([
ResourceAttributes::SERVICE_NAME => 'my-service',
ResourceAttributes::SERVICE_NAMESPACE => 'my-team',
'deployment.environment' => 'production',
]));
$transport = (new OtlpHttpTransportFactory())->create(
'http://localhost:4318/v1/logs',
'application/x-protobuf'
);
$exporter = new LogsExporter($transport);
$loggerProvider = LoggerProvider::builder()
->setResource($resource)
->addLogRecordProcessor(new BatchLogRecordProcessor($exporter))
->build();
$handler = new OtelHandler($loggerProvider, Logger::DEBUG);
$logger = new Logger('my-service');
$logger->pushHandler($handler);
$logger->pushHandler(new \Monolog\Handler\StreamHandler('php://stdout', Logger::DEBUG));
return $logger;
}
The OtlpHttpTransportFactory in the snippet above connects to the OTel Collector on localhost:4318. If your Collector runs on a different host or port, update the URL accordingly.
Set resource attributes
Resource attributes are attached to every log record exported from this process. Two attributes drive how Bronto organises incoming logs:
| OTel attribute | Bronto concept | Description |
|---|
service.name | Dataset | Groups logs from one service |
service.namespace | Collection | Groups related services or a team’s services |
These are set via ResourceInfo::create in the setup above.
Complete example
<?php
require __DIR__ . '/vendor/autoload.php';
require __DIR__ . '/configure_logging.php';
$logger = configureOtelLogging();
$logger->info('Application started');
$logger->warning('Low disk space', ['disk_free_gb' => 2.1]);
$logger->error('Database connection failed', ['exception' => 'timeout']);
Existing Monolog log statements require no changes. The OtelHandler is added alongside any existing handlers (console, file, etc.) so both continue to work.
Verify log collection
After running your application, open the Search page in Bronto. Filter by the dataset name you set in service.name — your log records should appear within a few seconds.
If no logs appear, check:
- The OTel Collector is running and reachable at the configured endpoint.
- The Collector’s pipeline includes a
logs pipeline with an otlp receiver and the Bronto exporter — see Connect Open Telemetry to Bronto.
configureOtelLogging() is called before the first log statement.
Traces
Auto-instrumentation packages are available for Laravel, Symfony, Guzzle, PSR-18 HTTP clients, and more. Install the relevant open-telemetry/opentelemetry-auto-* package via Composer and register the instrumentation — no manual span code needed. See PHP instrumentation libraries for the full list.
No additional packages are needed — open-telemetry/sdk and open-telemetry/exporter-otlp already include tracing support.
<?php
use OpenTelemetry\Contrib\Otlp\SpanExporter;
use OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessor;
use OpenTelemetry\SDK\Trace\TracerProvider;
function configureOtelTracing(ResourceInfo $resource): TracerProvider
{
$transport = (new OtlpHttpTransportFactory())->create(
'http://localhost:4318/v1/traces',
'application/x-protobuf'
);
$spanExporter = new SpanExporter($transport);
$tracerProvider = TracerProvider::builder()
->setResource($resource)
->addSpanProcessor(new BatchSpanProcessor($spanExporter))
->build();
\OpenTelemetry\API\Globals::registerInitializer(function (Configurator $configurator) use ($tracerProvider) {
$configurator->withTracerProvider($tracerProvider);
});
return $tracerProvider;
}
Pass the same $resource used for logging so both signals share service.name and service.namespace.
Creating spans
$tracer = $tracerProvider->getTracer('my-service');
$span = $tracer->spanBuilder('process-payment')->startSpan();
$scope = $span->activate();
try {
$span->setAttribute('payment.amount', 99.99);
$logger->info('Processing payment'); // trace_id and span_id injected automatically
} finally {
$scope->detach();
$span->end();
}
Direct export to Bronto
If you are not using an OTel Collector, export directly to Bronto by replacing the transport configurations with the Bronto OTLP endpoints and your API key:
// Logs
$logTransport = (new OtlpHttpTransportFactory())->create(
'https://ingestion.eu.bronto.io/v1/logs', // or ingestion.us.bronto.io
'application/x-protobuf',
['x-bronto-api-key' => '<YOUR_API_KEY>']
);
// Traces
$traceTransport = (new OtlpHttpTransportFactory())->create(
'https://ingestion.eu.bronto.io/v1/traces', // or ingestion.us.bronto.io
'application/x-protobuf',
['x-bronto-api-key' => '<YOUR_API_KEY>']
);
| Region | Logs endpoint | Traces endpoint |
|---|
| EU | https://ingestion.eu.bronto.io/v1/logs | https://ingestion.eu.bronto.io/v1/traces |
| US | https://ingestion.us.bronto.io/v1/logs | https://ingestion.us.bronto.io/v1/traces |
See API Keys for how to create a key with ingestion permissions. No other changes to the rest of the setup are required.