Skip to content

Commit

Permalink
update quoteservice to opentelemetry-php beta (#644)
Browse files Browse the repository at this point in the history
  • Loading branch information
brettmc committed Dec 21, 2022
1 parent df3d442 commit c839dd7
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 113 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,5 @@ significant modifications will be credited to OpenTelemetry Authors.
([#617](https://github.com/open-telemetry/opentelemetry-demo/pull/617))
* Use `frontend-web` as service name for browser/web requests
([#628](https://github.com/open-telemetry/opentelemetry-demo/pull/628))
* Update `quoteservice` to use opentelemetry-php beta release
([#644](https://github.com/open-telemetry/opentelemetry-demo/pull/644))
8 changes: 2 additions & 6 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -435,14 +435,10 @@ services:
ports:
- "${QUOTE_SERVICE_PORT}"
environment:
# OTEL_EXPORTER_OTLP_TRACES_ENDPOINT # Not working for PHP
- OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://otelcol:4318/v1/traces
- OTEL_PHP_AUTOLOAD_ENABLED=true
- QUOTE_SERVICE_PORT
- OTEL_SERVICE_NAME=quoteservice
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otelcol:4318
- OTEL_TRACES_SAMPLER=parentbased_always_on
- OTEL_TRACES_EXPORTER=otlp
- OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
- OTEL_PHP_TRACES_PROCESSOR=simple
depends_on:
- otelcol
logging: *logging
Expand Down
66 changes: 23 additions & 43 deletions docs/services/quoteservice.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,64 +15,44 @@ The PHP instrumentation may vary when using a different framework.

### Initializing Tracing

The OpenTelemetry SDK is initialized from `index`.
In this demo, the OpenTelemetry SDK has been automatically created as part
of SDK autoloading, which happens as part of composer autoloading.

```php
$tracerProvider = (new TracerProviderFactory('quoteservice'))->create();
ShutdownHandler::register([$tracerProvider, 'shutdown']);
$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php');
This is enabled by setting the environment variable `OTEL_PHP_AUTOLOAD_ENABLED=true`.

$containerBuilder->addDefinitions([
Tracer::class => $tracer
]);
```php
require __DIR__ . '/../vendor/autoload.php';
```

You should call `$tracerProvider->shutdown()` when your service is shutdown to
ensure all spans are exported.
There are multiple ways to create or obtain a `Tracer`, in this example we
obtain one from the global tracer provider which was initialized above, as
part of SDK autoloading:

### Adding HTTP instrumentation
```php
$tracer = Globals::tracerProvider()->getTracer('manual-instrumentation');
```

This service receives HTTP requests, which are instrumented in the middleware.
### Manually creating spans

The middleware starts root span based on route pattern, sets span status
from http code.
Creating a span manually can be done via a `Tracer`. The span will be default
be a child of the active span in the current execution context:

```php
$app->add(function (Request $request, RequestHandler $handler) use ($tracer) {
$parent = TraceContextPropagator::getInstance()->extract($request->getHeaders());
$routeContext = RouteContext::fromRequest($request);
$route = $routeContext->getRoute();
$root = $tracer->spanBuilder($route->getPattern())
->setStartTimestamp((int) ($request->getServerParams()['REQUEST_TIME_FLOAT'] * 1e9))
->setParent($parent)
->setSpanKind(SpanKind::KIND_SERVER)
->startSpan();
$scope = $root->activate();

try {
$response = $handler->handle($request);
$root->setStatus($response->getStatusCode() < 500 ? StatusCode::STATUS_OK : StatusCode::STATUS_ERROR);
} finally {
$root->end();
$scope->detach();
}

return $response;
});
$span = Globals::tracerProvider()
->getTracer('manual-instrumentation')
->spanBuilder('calculate-quote')
->setSpanKind(SpanKind::KIND_INTERNAL)
->startSpan();
/* calculate quote */
$span->end();
```

This is enough to get a new span every time a new request is received by the service.

Note that the `root` span is created with `setParent($parent)` which is coming from
the request headers. This is required to ensure Context Propagation.

### Add span attributes

Within the definition of routes, you can get current span using
`OpenTelemetry\API\Trace\AbstractSpan`.
You can obtain the current span using `OpenTelemetry\API\Trace\Span`.

```php
$span = AbstractSpan::getCurrent();
$span = Span::getCurrent();
```

Adding attributes to a span is accomplished using `setAttribute` on the span
Expand Down
9 changes: 7 additions & 2 deletions src/quoteservice/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ RUN composer install \
--no-dev \
--prefer-dist

FROM php:8.1-apache
FROM php:8.2-apache

RUN docker-php-ext-install opcache
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 \
opcache \
protobuf \
open-telemetry/opentelemetry-php-instrumentation@1.0.0beta1

WORKDIR /var/www
COPY --from=build /tmp/vendor/ ./vendor/
Expand Down
2 changes: 1 addition & 1 deletion src/quoteservice/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
The Quote Service calculates the shipping costs,
based on the number of items to be shipped.

It is a PHP based service.
It is a PHP based service, using a combination of automatic and manual instrumentation.

## Docker Build

Expand Down
19 changes: 11 additions & 8 deletions src/quoteservice/app/routes.php
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
<?php
declare(strict_types=1);

use OpenTelemetry\API\Trace\AbstractSpan;
use OpenTelemetry\API\Common\Instrumentation\Globals;
use OpenTelemetry\API\Trace\Span;
use OpenTelemetry\API\Trace\SpanKind;
use OpenTelemetry\SDK\Trace\Tracer;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;

function calculateQuote($jsonObject, Tracer $tracer): float
function calculateQuote($jsonObject): float
{
$quote = 0.0;
$childSpan = $tracer
$childSpan = Globals::tracerProvider()->getTracer('manual-instrumentation')
->spanBuilder('calculate-quote')
->setSpanKind(SpanKind::KIND_INTERNAL)
->startSpan();
$childSpan->addEvent('Calculating quote');

try {
if (!array_key_exists('numberOfItems', $jsonObject)) {
throw new \InvalidArgumentException('numberOfItems not provided');
}
$numberOfItems = intval($jsonObject['numberOfItems']);
$quote = 8.90 * $numberOfItems;
$quote = round(8.90 * $numberOfItems, 2);

$childSpan->setAttribute('app.quote.items.count', $numberOfItems);
$childSpan->setAttribute('app.quote.cost.total', $quote);
Expand All @@ -34,14 +37,14 @@ function calculateQuote($jsonObject, Tracer $tracer): float
}

return function (App $app) {
$app->post('/getquote', function (Request $request, Response $response, Tracer $tracer) {
$span = AbstractSpan::getCurrent();
$app->post('/getquote', function (Request $request, Response $response) {
$span = Span::getCurrent();
$span->addEvent('Received get quote request, processing it');

$body = $request->getBody()->getContents();
$jsonObject = json_decode($body, true);

$data = calculateQuote($jsonObject, $tracer);
$data = calculateQuote($jsonObject);

$payload = json_encode($data);
$response->getBody()->write($payload);
Expand Down
14 changes: 7 additions & 7 deletions src/quoteservice/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
"name": "openteletry-demo/quoteservice",
"description": "Quote Service part of OpenTelemetry Demo",
"license": "Apache-2.0",
"minimum-stability": "beta",
"require": {
"php": "7.4 || 8.1",
"ext-json": "dev-main",
"php": ">= 8.2",
"ext-json": "*",
"monolog/monolog": "2.8.0",
"open-telemetry/opentelemetry": "0.0.15",
"open-telemetry/sdk": "1.0.0beta1",
"open-telemetry/exporter-otlp": "1.0.0beta1",
"open-telemetry/opentelemetry-auto-slim": "1.0.0beta3",
"open-telemetry/opentelemetry-auto-psr15": "1.0.0beta2",
"guzzlehttp/guzzle": "7.4.5",
"php-di/php-di": "6.4.0",
"php-di/slim-bridge": "3.2.0",
Expand All @@ -19,10 +23,6 @@
"App\\": "src/"
}
},
"scripts": {
"start": "php -S 0.0.0.0:${QUOTE_SERVICE_PORT} -t public",
"test": "phpunit"
},
"config": {
"allow-plugins": {
"phpstan/extension-installer": true
Expand Down
46 changes: 0 additions & 46 deletions src/quoteservice/public/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,7 @@

use DI\Bridge\Slim\Bridge;
use DI\ContainerBuilder;
use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
use OpenTelemetry\API\Trace\SpanKind;
use OpenTelemetry\API\Trace\StatusCode;
use OpenTelemetry\SDK\Trace\Tracer;
use OpenTelemetry\SDK\Trace\TracerProviderFactory;
use OpenTelemetry\SDK\Common\Util\ShutdownHandler;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Factory\AppFactory;
use Slim\Factory\ServerRequestCreatorFactory;
use Slim\Routing\RouteContext;

require __DIR__ . '/../vendor/autoload.php';

Expand All @@ -42,15 +32,6 @@
$dependencies = require __DIR__ . '/../app/dependencies.php';
$dependencies($containerBuilder);

// Add OTel
$tracerProvider = (new TracerProviderFactory('quoteservice'))->create();
ShutdownHandler::register([$tracerProvider, 'shutdown']);
$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php');

$containerBuilder->addDefinitions([
Tracer::class => $tracer
]);

// Build PHP-DI Container instance
$container = $containerBuilder->build();

Expand All @@ -59,38 +40,12 @@
$app = Bridge::create($container);

// Register middleware
//middleware starts root span based on route pattern, sets status from http code
$app->add(function (Request $request, RequestHandler $handler) use ($tracer) {
$parent = TraceContextPropagator::getInstance()->extract($request->getHeaders());
$routeContext = RouteContext::fromRequest($request);
$route = $routeContext->getRoute();
$root = $tracer->spanBuilder($route->getPattern())
->setStartTimestamp((int) ($request->getServerParams()['REQUEST_TIME_FLOAT'] * 1e9))
->setParent($parent)
->setSpanKind(SpanKind::KIND_SERVER)
->startSpan();
$scope = $root->activate();

try {
$response = $handler->handle($request);
$root->setStatus($response->getStatusCode() < 500 ? StatusCode::STATUS_OK : StatusCode::STATUS_ERROR);
} finally {
$root->end();
$scope->detach();
}

return $response;
});
$app->addRoutingMiddleware();

// Register routes
$routes = require __DIR__ . '/../app/routes.php';
$routes($app);

// Create Request object from globals
$serverRequestCreator = ServerRequestCreatorFactory::create();
$request = $serverRequestCreator->createServerRequestFromGlobals();

// Add Body Parsing Middleware
$app->addBodyParsingMiddleware();

Expand All @@ -99,4 +54,3 @@

// Run App
$app->run();
$tracerProvider->shutdown();

0 comments on commit c839dd7

Please sign in to comment.