Integrate OpenTelemetry into a PHP Application bu using Manual Instrumentation
Integrate OpenTelemetry for PHP Application with manual instrumentation to enable detailed observability by collecting, processing, and exporting telemetry data like traces and logs, allowing direct control over which parts of the application are monitored.
Prerequisites
AWS Account with Ubuntu 24.04 LTS EC2 Instance.
PHP, PECL, composer installed.
update the packages.
sudo apt update
Installs the command-line interface for PHP 8.3.
sudo apt install php8.3-cli
Verify the installation.
php -v
Install PECL to get the necessary tools for developing PHP extensions.
sudo apt install php-pear php8.3-dev
Download and install Composer, a tool that helps manage PHP libraries more easily.
curl -sS https://getcomposer.org/installer | php
Move the Composer binary to a directory in /usr/local/bin/ to make it accessible globally.
sudo mv composer.phar /usr/local/bin/composer
Run composer -V
to check the Composer version and verify the installation.
composer -v
Install Build Tools needed for creating PECL extensions.
sudo apt-get install gcc make autoconf
Create your PHP project with the Slim Framework.
Create a new project directory.
mkdir opentelemetry-php-example
Move to the directory.
cd opentelemetry-php-example
Initialize a new Composer project and add Slim as a dependency.
composer init --no-interaction --require slim/slim:"^4" --require slim/psr7:"^1"
Install the dependencies defined in composer.json using the following command.
composer update
Create an index.php file that contains a simple Slim application.
nano index.php
add the following code into it.
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/vendor/autoload.php';
$app = AppFactory::create();
$app->get('/rolldice', function (Request $request, Response $response) {
$result = random_int(1,6);
$response->getBody()->write(strval($result));
return $response;
});
$app->run();
Explanation of the code
This code begins by importing necessary classes and loading dependencies installed with Composer. It then initializes a new Slim application instance, with the $app
variable serving as the application object to manage routes and handle HTTP requests. A route (/rolldice
) is defined, which generates a random integer between 1 and 6, writes it to the response, and sends it back to the client. Finally, the application is started to listen for incoming requests.
Now, start the built-in PHP server to test your application with the following command.
php -S 0.0.0.0:8080
Open http://<Public-IP-Address>:8080/rolldice in your browser. You should see a random number between 1 and 6.
Integrate OpenTelemetry for PHP Application with Manual Instrumentation to get Trace data
First install the OpenTelemetry SDK.
composer require open-telemetry/sdk
Modify index.php to add OpenTelemetry manual tracing.
nano index.php
add the following code into it.
<?php
use OpenTelemetry\API\Globals;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/vendor/autoload.php';
$tracer = Globals::tracerProvider()->getTracer('demo');
$app = AppFactory::create();
$app->get('/rolldice', function (Request $request, Response $response) use ($tracer) {
$span = $tracer
->spanBuilder('manual-span')
->startSpan();
$result = random_int(1,6);
$response->getBody()->write(strval($result));
$span
->addEvent('rolled dice', ['result' => $result])
->end();
return $response;
});
$app->run();
Explanation of the code:
The code starts with Imports and Autoloading, importing necessary classes from OpenTelemetry, Slim, and PSR-7, using the Globals
class for OpenTelemetry's global tracer, ResponseInterface
and ServerRequestInterface
for HTTP request and response structures, and AppFactory
to create a Slim application instance, while the Autoloading part uses the require
statement to include Composer’s autoload file for loading dependencies from composer.json.
Create Application: This initializes a new Slim application instance using AppFactory
. The $app
variable now holds the application object that will manage routes and handle HTTP requests.
Define the /rolldice Route: Defines a route (/rolldice
) that listens for GET requests. Manual Tracing with OpenTelemetry: spanBuilder
creates a new span (manual-span
) to capture trace data for this request. startSpan()
begins the span, recording this operation in the trace.
Rolls a Dice: random_int(1,6)
generates a random number from 1 to 6, simulating a dice roll. Returns the Result: The result is written to the response body using write()
, and addEvent()
logs the event within the trace, capturing the result as additional data. end()
closes the span, marking the end of this traced operation. The final response is sent to the client with the dice roll result.
Run the Application: Starts the PHP application and begins listening for incoming requests. Slim routes them to their corresponding handlers, which process the request and return a response.
Run the PHP application with OpenTelemetry environment variables to display tracing output in the console.
env OTEL_PHP_AUTOLOAD_ENABLED=true \
OTEL_TRACES_EXPORTER=console \
OTEL_METRICS_EXPORTER=none \
OTEL_LOGS_EXPORTER=none \
php -S 0.0.0.0:8080
http://<Public-IP-Address>:8080/rolldice to view trace information in the console, where the OpenTelemetry SDK captures trace details for the /rolldice
route, displaying span and event data.
Integrate OpenTelemetry logging with Monolog
Install Monolog and OpenTelemetry logger dependencies.
composer require monolog \ monolog open-telemetry \ opentelemetry-logger-monolog
Modify index.php to add logging functionality using Monolog with OpenTelemetry
nano index.php
Add the following code into it.
<?php
use Monolog\Logger;
use OpenTelemetry\API\Globals;
use OpenTelemetry\Contrib\Logs\Monolog\Handler;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Log\LogLevel;
use Slim\Factory\AppFactory;
require __DIR__ . '/vendor/autoload.php';
$loggerProvider = Globals::loggerProvider();
$handler = new Handler(
$loggerProvider,
LogLevel::INFO
);
$monolog = new Logger('otel-php-monolog', [$handler]);
$app = AppFactory::create();
$app->get('/rolldice', function (Request $request, Response $response) use ($monolog) {
$result = random_int(1,6);
$response->getBody()->write(strval($result));
$monolog->info('dice rolled', ['result' => $result]);
return $response;
});
$app->run();
Explanation of the code
Imports and Autoloading:
Imports necessary classes for logging, OpenTelemetry, HTTP messaging, and Slim:
Logger
: Monolog’s main class for logging events.Globals
andHandler
: Access to OpenTelemetry’s global logger provider and a handler to integrate OpenTelemetry with Monolog.ResponseInterface
andServerRequestInterface
: Define HTTP request and response structures for handling them in Slim.LogLevel
: Provides log severity levels, such asINFO
.AppFactory
: Used to create the Slim application instance.
Autoloading: Loads dependencies specified in
composer.json
through Composer’s autoloader.
Set Up Logging:
Initialize OpenTelemetry Logger Provider: Retrieves the global logger provider from OpenTelemetry.
Create a Handler for Monolog:
Handler
: Sets up a bridge between OpenTelemetry and Monolog.LogLevel::INFO
: Defines the minimum log level to capture (INFO and above).
Set Up Monolog Logger:
Logger
: A Monolog instance is created, with OpenTelemetry’s handler attached.The logger name
otel-php-monolog
will label all logs generated by this instance.
Define the /rolldice Route:
Defines a route (
/rolldice
) that listens for GET requests.Simulates a Dice Roll:
random_int(1,6)
: Generates a random number from 1 to 6, simulating a dice roll.Logs the Dice Roll:
info()
logs the result at INFO level, with a messagedice rolled
and attaches the dice roll result as a context property.Returns the Response: The dice roll result is written to the response body, which is then returned to the client.
Run the Application:
- Starts the php application and begins listening for incoming requests. Slim handles routing to the appropriate handler, which processes the request and returns a response with the dice roll result.
Run the PHP application again with environment variables set up for logging.
env OTEL_PHP_AUTOLOAD_ENABLED=true \
OTEL_TRACES_EXPORTER=console \
OTEL_METRICS_EXPORTER=none \
OTEL_LOGS_EXPORTER=console \
php -S 0.0.0.0:8080
Access http://<Public-IP-Address>:8080/rolldice to see log messages with dice roll results and trace data from OpenTelemetry on the console.
Subscribe to my newsletter
Read articles from Ankita Lunawat directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Ankita Lunawat
Ankita Lunawat
I am a dedicated and experienced Cloud Engineer with two years in the industry, specializing in designing, implementing, and managing scalable and secure cloud infrastructures. With a strong foundation in AWS, Azure, and GCP, I excel at leveraging cloud services to optimize performance, enhance security, and reduce operational costs. My expertise includes automated deployment pipelines, infrastructure as code (IaC) with tools like Terraform and container orchestration using Kubernetes and Docker. Throughout my career, I've collaborated with cross-functional teams to deliver robust cloud solutions, ensuring high availability and fault tolerance. I'm passionate about staying at the forefront of cloud technology trends and continuously enhancing my skill set to provide innovative solutions that drive business success. Whether it's migrating legacy systems to the cloud or architecting new cloud-native applications, I bring a strategic approach to every project, focusing on efficiency, scalability, and reliability. In addition to my technical skills, I am an advocate for DevOps practices, promoting a culture of collaboration and continuous improvement within development and operations teams. My commitment to learning and adapting to new technologies ensures that I can meet the evolving needs of any organization and deliver top-tier cloud solutions.