OpenTelemetry Slim Framework: Instrumentation and Monitoring Guide
OpenTelemetry Slim instrumentation provides automatic tracing for HTTP requests, routing, and middleware in Slim PHP applications. Using opentelemetry-auto-slim, you can add observability to your PHP microservices and track request latencies, database queries, and errors across distributed systems.
Quick Reference
| Component | Package | Purpose |
|---|---|---|
| Slim Auto-Instrument | open-telemetry/opentelemetry-auto-slim | Auto-trace HTTP requests |
| PDO Instrumentation | open-telemetry/opentelemetry-auto-pdo | Trace database queries |
| Guzzle Instrumentation | open-telemetry/opentelemetry-auto-guzzle | Trace outgoing HTTP calls |
| OpenTelemetry SDK | open-telemetry/sdk | Core SDK and exporters |
What is OpenTelemetry?
OpenTelemetry is an open-source observability framework that standardizes the collection of telemetry data from applications. It provides three pillars of observability:
- Distributed Traces: Track requests across services and components
- Metrics: Collect quantitative measurements of application performance
- Logs: Capture structured application logs with trace correlation
OpenTelemetry is vendor-neutral, meaning you can export data to any compatible OpenTelemetry backend such as Uptrace, Jaeger, or Grafana. Deploying an OpenTelemetry Collector in your infrastructure provides enhanced telemetry data processing capabilities, including filtering, enrichment, and batching before data reaches your backend.
Prerequisites
- PHP 8.1+
- Slim Framework 4.x
- Composer for dependency management
- OpenTelemetry PHP extension
Quick Start: For fastest setup without code changes, see the PHP zero-code instrumentation guide.
Step 1: Install the OpenTelemetry Extension
The OpenTelemetry PHP extension enables auto-instrumentation by hooking into PHP function calls at the runtime level.
Install Build Dependencies
sudo apt-get install gcc make autoconf php-dev
Install the Extension
pecl install opentelemetry
Enable the Extension
Add to your php.ini file (run php --ini to find the location):
[opentelemetry]
extension=opentelemetry.so
Verify Installation
php -m | grep opentelemetry
Step 2: Install Slim Instrumentation
The Slim auto-instrumentation package registers hooks via Composer that automatically create spans for App::handle() and routing middleware.
composer require open-telemetry/opentelemetry-auto-slim
Install the OpenTelemetry SDK and OTLP exporter:
# Core SDK
composer require open-telemetry/sdk
# OTLP exporter (gRPC or HTTP)
composer require open-telemetry/exporter-otlp
# Required transport
composer require php-http/guzzle7-adapter
Step 3: Configure OpenTelemetry
Using Uptrace SDK
The simplest approach is the Uptrace PHP SDK, which bundles the OpenTelemetry SDK with sensible defaults:
composer require uptrace/uptrace
In your public/index.php, add configuration right after the autoloader:
<?php
require __DIR__ . '/../vendor/autoload.php';
// Configure OpenTelemetry with Uptrace
$uptrace = Uptrace\Distro::builder()
// Set DSN here or use UPTRACE_DSN env var
->setDsn('<FIXME>')
->setServiceName('slim-app')
->setServiceVersion('1.0.0')
->buildAndRegisterGlobal();
// Create Slim app
$app = Slim\Factory\AppFactory::create();
$app->get('/', function ($request, $response) {
$response->getBody()->write('Hello, World!');
return $response;
});
$app->get('/health', function ($request, $response) {
$response->getBody()->write(json_encode(['status' => 'ok']));
return $response->withHeader('Content-Type', 'application/json');
});
$app->run();
Using OpenTelemetry SDK Directly
For a vendor-neutral setup, configure the SDK through environment variables:
export OTEL_SERVICE_NAME="slim-app"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="otlp"
export OTEL_LOGS_EXPORTER="otlp"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.uptrace.dev:4317"
export OTEL_EXPORTER_OTLP_HEADERS="uptrace-dsn=<FIXME>"
export OTEL_EXPORTER_OTLP_COMPRESSION="gzip"
export OTEL_PHP_AUTOLOAD_ENABLED="true"
With OTEL_PHP_AUTOLOAD_ENABLED=true, the SDK initializes automatically via Composer and no code changes are needed. For more details, see the OpenTelemetry PHP guide.
Custom Instrumentation
Add custom spans to trace specific business logic beyond automatic instrumentation:
<?php
use OpenTelemetry\API\Globals;
use OpenTelemetry\API\Trace\StatusCode;
$app->post('/api/orders', function ($request, $response) {
$tracer = Globals::tracerProvider()->getTracer('slim-app');
$span = $tracer->spanBuilder('create-order')->startSpan();
$scope = $span->activate();
try {
$data = json_decode($request->getBody()->getContents(), true);
$span->setAttribute('order.customer_id', $data['customer_id'] ?? '');
$span->setAttribute('order.item_count', count($data['items'] ?? []));
// Validate order
$validateSpan = $tracer->spanBuilder('validate-order')->startSpan();
validateOrder($data);
$validateSpan->end();
// Save to database
$dbSpan = $tracer->spanBuilder('save-order')->startSpan();
$dbSpan->setAttribute('db.operation', 'INSERT');
$dbSpan->setAttribute('db.table', 'orders');
$orderId = saveOrder($data);
$dbSpan->end();
$span->setAttribute('order.id', $orderId);
$response->getBody()->write(json_encode(['order_id' => $orderId]));
return $response->withHeader('Content-Type', 'application/json');
} catch (\Exception $e) {
$span->recordException($e);
$span->setStatus(StatusCode::STATUS_ERROR, $e->getMessage());
$response->getBody()->write(json_encode(['error' => $e->getMessage()]));
return $response->withHeader('Content-Type', 'application/json')->withStatus(500);
} finally {
$scope->detach();
$span->end();
}
});
Tracing Middleware
Create reusable middleware for cross-cutting tracing concerns:
<?php
use OpenTelemetry\API\Globals;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as Handler;
use Slim\Psr7\Response;
$app->add(function (Request $request, Handler $handler) {
$tracer = Globals::tracerProvider()->getTracer('slim-app');
$span = $tracer->spanBuilder('request-middleware')->startSpan();
$scope = $span->activate();
try {
// Add request metadata
$span->setAttribute('http.user_agent', $request->getHeaderLine('User-Agent'));
$span->setAttribute('client.ip', $request->getServerParams()['REMOTE_ADDR'] ?? '');
$response = $handler->handle($request);
$span->setAttribute('http.status_code', $response->getStatusCode());
return $response;
} finally {
$scope->detach();
$span->end();
}
});
Database Instrumentation
PDO Auto-Instrumentation
Automatically trace all PDO database queries:
composer require open-telemetry/opentelemetry-auto-pdo
No code changes are needed. All queries executed through PDO will be automatically traced with query text, execution time, and database metadata.
Eloquent (via Illuminate Database)
If you use Illuminate Database (Eloquent) with Slim:
composer require open-telemetry/opentelemetry-auto-laravel
This traces Eloquent queries, model events, and database transactions via the Laravel auto-instrumentation package, which covers the Illuminate database layer.
Environment Variables Configuration
Configure OpenTelemetry through environment variables for production:
| Variable | Description | Example Value |
|---|---|---|
OTEL_SERVICE_NAME | Service name | slim-app |
OTEL_EXPORTER_OTLP_ENDPOINT | OTLP collector endpoint | https://api.uptrace.dev:4317 |
OTEL_EXPORTER_OTLP_HEADERS | Authentication headers | uptrace-dsn=<FIXME> |
OTEL_TRACES_SAMPLER | Sampling strategy | parentbased_traceidratio |
OTEL_TRACES_SAMPLER_ARG | Sampling ratio (0.0 to 1.0) | 0.1 |
OTEL_PHP_AUTOLOAD_ENABLED | Auto-init via Composer | true |
OTEL_EXPORTER_OTLP_COMPRESSION | Compression algorithm | gzip |
For the full list, see the OpenTelemetry environment variables reference.
Docker Deployment
Deploy a Slim application with OpenTelemetry in Docker:
FROM php:8.3-apache
# Install php-extension-installer, then use it to add the OpenTelemetry extension
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
install-php-extensions opentelemetry
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader
COPY . .
# Point Apache to Slim's public/ directory
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf && \
a2enmod rewrite
# Configure OpenTelemetry via environment variables
ENV OTEL_SERVICE_NAME="slim-app"
ENV OTEL_TRACES_EXPORTER="otlp"
ENV OTEL_METRICS_EXPORTER="otlp"
ENV OTEL_EXPORTER_OTLP_COMPRESSION="gzip"
ENV OTEL_PHP_AUTOLOAD_ENABLED="true"
EXPOSE 80
With Docker Compose:
version: '3.8'
services:
slim-app:
build: .
ports:
- "80:80"
environment:
- OTEL_SERVICE_NAME=slim-app
- OTEL_EXPORTER_OTLP_ENDPOINT=https://api.uptrace.dev:4317
- OTEL_EXPORTER_OTLP_HEADERS=uptrace-dsn=${UPTRACE_DSN}
- OTEL_PHP_AUTOLOAD_ENABLED=true
depends_on:
- mysql
mysql:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: slimapp
For a complete Docker setup with the OpenTelemetry Collector, see the Docker deployment guide.
PHP-FPM Considerations
When running Slim behind PHP-FPM, telemetry is exported at the end of each request. For high-traffic applications, consider:
- Using the OpenTelemetry Collector as a local relay to batch and forward telemetry
- Adjusting batch processor settings via environment variables
- Monitoring PHP-FPM worker pool usage alongside application traces
For PHP-FPM-specific configuration, see the PHP-FPM instrumentation guide.
Troubleshooting
Extension not loading: Verify with php -m | grep opentelemetry. If missing, check that php.ini has the correct extension=opentelemetry.so line and the .so file exists in the extensions directory (php -i | grep extension_dir).
No traces appearing: Confirm OTEL_EXPORTER_OTLP_ENDPOINT is reachable. Check PHP error logs for SDK initialization errors.
Auto-instrumentation not working: Ensure OTEL_PHP_AUTOLOAD_ENABLED=true is set, or verify that Uptrace/SDK initialization happens before $app->run().
High memory usage: Reduce the batch processor queue size:
export OTEL_BSP_MAX_QUEUE_SIZE=512
export OTEL_BSP_MAX_EXPORT_BATCH_SIZE=128
Debug logging: Enable verbose output:
export OTEL_LOG_LEVEL=debug
What is Uptrace?
Uptrace is an OpenTelemetry APM that supports distributed tracing, metrics, and logs. You can use it to monitor applications and troubleshoot issues.

Uptrace comes with an intuitive query builder, rich dashboards, alerting rules with notifications, and integrations for most languages and frameworks.
Uptrace can process billions of spans and metrics on a single server and allows you to monitor your applications at 10x lower cost.
In just a few minutes, you can try Uptrace by visiting the cloud demo (no login required) or running it locally with Docker. The source code is available on GitHub.
What's next?
Your Slim application is now instrumented with OpenTelemetry for comprehensive monitoring. Next steps:
- Laravel instrumentation for full-featured PHP applications
- Symfony instrumentation for enterprise PHP frameworks
- PHP-FPM instrumentation for production PHP deployments
- OpenTelemetry PHP guide for deeper instrumentation options