Skip to content

Commit

Permalink
Merge pull request #3 from plunkettscott/feat/watchers
Browse files Browse the repository at this point in the history
New features
  • Loading branch information
plunkettscott authored Apr 2, 2023
2 parents 64c5b62 + d51b028 commit 3898abd
Show file tree
Hide file tree
Showing 37 changed files with 1,477 additions and 348 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ jobs:
composer update --prefer-dist --no-interaction --no-progress
- name: Execute tests
run: vendor/bin/phpunit
run: vendor/bin/pest
1 change: 1 addition & 0 deletions .valetrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
php=8.2
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ This package is currently in development and contains the following Watchers:
- [x] HTTP Client Requests
- [x] Database Queries
- [x] Redis Commands
- [ ] Queue Jobs
- [x] Queued Jobs
- [x] Events
- [x] Event Listeners
- [x] Cache Commands
- [ ] View Rendering
- [ ] View Rendering (Exploring Capabilities)
- [x] Exceptions
- [x] Log Messages
- [x] Scheduled Tasks

## Requirements

Expand Down
16 changes: 8 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,24 @@
"php": "^8.2",
"guzzlehttp/promises": "^1.5",
"laravel/framework": "^10.0",
"open-telemetry/opentelemetry": "^1",
"open-telemetry/api": "^1.0@beta",
"open-telemetry/sdk": "^1.0@beta",
"php-http/message-factory": "^1.0",
"symfony/http-client": "^6.2"
},
"require-dev": {
"guzzlehttp/guzzle": "^7.5",
"laravel/pint": "^1.6",
"orchestra/testbench": "^8.0",
"pestphp/pest": "^1.22",
"pestphp/pest": "^2.0",
"pestphp/pest-plugin-mock": "^2.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.0",
"laravel/pint": "^1.6"
"phpunit/phpunit": "^10.0"
},
"autoload": {
"psr-4": {
"PlunkettScott\\LaravelOpenTelemetry\\": "src"
},
"files": [
"src/helpers.php"
]
}
},
"autoload-dev": {
"psr-4": {
Expand Down
44 changes: 40 additions & 4 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use PlunkettScott\LaravelOpenTelemetry\Enums;
use PlunkettScott\LaravelOpenTelemetry\Watchers;
use PlunkettScott\LaravelOpenTelemetry\Resolvers;

return [

Expand Down Expand Up @@ -72,10 +73,8 @@
'enabled' => env('OTEL_WATCHER_REQUEST_ENABLED', true),
'options' => (new Watchers\RequestWatcherOptions(
continue_trace: env('OTEL_WATCHER_REQUEST_CONTINUE_TRACE', true),
middleware_groups: [
'web',
'api',
],
record_route: true,
record_user: true,
))->toArray(),
],

Expand All @@ -97,6 +96,28 @@
ignored: [],
))->toArray(),
],

Watchers\EventWatcher::class => [
'enabled' => env('OTEL_WATCHER_EVENT_ENABLED', true),
'options' => (new Watchers\EventWatcherOptions(
ignored: [],
))->toArray(),
],

Watchers\QueueWatcher::class => [
'enabled' => env('OTEL_WATCHER_QUEUE_ENABLED', true),
'options' => (new Watchers\QueueWatcherOptions(
trace_by_default: true,
ignored: [],
))->toArray(),
],

Watchers\ScheduleWatcher::class => [
'enabled' => env('OTEL_WATCHER_SCHEDULE_ENABLED', true),
'options' => (new Watchers\ScheduleWatcherOptions(
record_output: false,
))->toArray(),
],
],

/*
Expand All @@ -116,4 +137,19 @@
Enums\LogContextFields::TRACE_ID => 'trace_id',
],
],

/*
|--------------------------------------------------------------------------
| OpenTelemetry Attribute Resolvers
|--------------------------------------------------------------------------
|
| The following array lists the resolver implementations used to resolve
| various attributes for spans. You are free to customize the default
| list of resolvers to suit your instrumentation needs.
|
*/

'resolvers' => [
'user' => Resolvers\DefaultUserResolver::class,
],
];
12 changes: 7 additions & 5 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
parameters:
paths:
- config
- src

level: 0
level: 0
paths:
- config
- src
- tests
ignoreErrors:
- '#^Undefined variable: \$this$#'
35 changes: 11 additions & 24 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,26 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
beStrictAboutTestsThatDoNotTestAnything="true"
bootstrap="vendor/autoload.php"
colors="true"
convertDeprecationsToExceptions="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
verbose="true"
>
<testsuites>
<testsuite name="OpenTelemetry for Laravel Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<php>
<env name="APP_ENV" value="self-testing"/>
<env name="APP_KEY" value="base64:yk+bUVuZa1p86Dqjk9OjVK2R1pm6XHxC6xEKFq8utH0="/>
<env name="CACHE_DRIVER" value="file"/>
</php>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" beStrictAboutTestsThatDoNotTestAnything="true" bootstrap="vendor/autoload.php" colors="true" processIsolation="false" stopOnError="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
<testsuites>
<testsuite name="Tests">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<php>
<env name="APP_ENV" value="testing"/>
<env name="APP_KEY" value="base64:yk+bUVuZa1p86Dqjk9OjVK2R1pm6XHxC6xEKFq8utH0="/>
<env name="CACHE_DRIVER" value="file"/>
</php>
</phpunit>
81 changes: 67 additions & 14 deletions src/Concerns/TracesHttpRequests.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PlunkettScott\LaravelOpenTelemetry\Concerns;

use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
Expand All @@ -10,6 +11,7 @@
use OpenTelemetry\Context\ContextInterface;
use OpenTelemetry\Context\ScopeInterface;
use OpenTelemetry\SemConv\TraceAttributes;
use PlunkettScott\LaravelOpenTelemetry\Resolvers\Contracts\UserResolver;

trait TracesHttpRequests
{
Expand All @@ -25,19 +27,9 @@ public function extractParentFromRequest(Request $request): ContextInterface

public function createAndActivateRootSpan(bool $continueTrace, Request $request): void
{
$route = $request->route();

$routeParameters = [];
foreach ($route->parameterNames() as $parameterName) {
$routeParameters[$parameterName] = $route->parameter($parameterName);
}

$attributes = [
TraceAttributes::HTTP_METHOD => $request->method(),
TraceAttributes::HTTP_URL => $request->fullUrl(),
TraceAttributes::HTTP_ROUTE => $route->uri,
'http.route_name' => $request->route()?->getName() ?? null,
'http.route_parameters' => json_encode($routeParameters),
TraceAttributes::HTTP_TARGET => $request->path(),
TraceAttributes::HTTP_HOST => $request->getHost(),
TraceAttributes::HTTP_SCHEME => $request->getScheme(),
Expand Down Expand Up @@ -75,6 +67,10 @@ public function terminateRootSpan(Request $request, mixed $response): void
return;
}

$this->recordRouteInformation($request);

$this->recordAuthenticatedUser($request);

if (method_exists($response, 'getStatusCode')) {
$this->span->setAttribute(TraceAttributes::HTTP_STATUS_CODE, $response->getStatusCode());
}
Expand All @@ -85,17 +81,72 @@ public function terminateRootSpan(Request $request, mixed $response): void
$this->span->setAttribute('http.response_content_encoding', $response->headers->get('Content-Encoding'));
}

$this->span->updateName($this->calculateSpanName($request));

$this->span->end();
$this->scope->detach();
}

private function recordRouteInformation(Request $request): void
{
if (! $this->options->record_route) {
return;
}

$route = $request->route();

if (isset($this->scope)) {
$this->scope->detach();
if (is_null($route)) {
return;
}

$routeParameters = [];

foreach ($route->parameterNames() as $parameterName) {
$routeParameters[$parameterName] = $route->parameter($parameterName);
}

$this->span->setAttributes([
TraceAttributes::HTTP_ROUTE => Str::startsWith($route->uri, '/')
? $route->uri
: '/' . $route->uri,
'http.route_name' => $route->getName(),
'http.route_parameters' => json_encode($routeParameters),
]);
}

private function recordAuthenticatedUser(Request $request): void
{
if (! $this->options->record_user) {
return;
}

/** @var UserResolver|null $userResolver */
$userResolver = app(UserResolver::class);
if (is_null($userResolver)) {
return;
}

try {
if ($user = $userResolver->resolve($request)) {
$user->addToSpan($this->span);
}
} catch (Exception $e) {
$this->span->addEvent('Failed to resolve EndUser using ['.get_class($userResolver).'::resolve()] method.');
$this->span->recordException($e);
}
}

private function calculateSpanName(Request $request): string
{
$route = $request->route();
$routeName = $route?->getName();
if (is_null($route)) {
// Early on in the request lifecycle, the route may not be available yet.
return $request->method().' '.$request->path();
}

// If the route is available, let's do a more generic span name that also
// includes the name of the route, if it has one.
$routeName = $route->getName();

if (Str::startsWith($routeName, 'generated::')) {
// This is a route name generated by for a closure when caching
Expand All @@ -104,7 +155,9 @@ private function calculateSpanName(Request $request): string
$routeName = null;
}

$routePath = $route?->uri ?? $request->path();
$routePath = Str::startsWith($route->uri, '/')
? $route->uri
: '/' . $route->uri;

return "{$request->method()} $routePath".($routeName ? " ($routeName)" : '');
}
Expand Down
8 changes: 8 additions & 0 deletions src/Contracts/NotTraceAware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace PlunkettScott\LaravelOpenTelemetry\Contracts;

interface NotTraceAware
{

}
8 changes: 8 additions & 0 deletions src/Contracts/TraceAware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace PlunkettScott\LaravelOpenTelemetry\Contracts;

interface TraceAware
{

}
Loading

0 comments on commit 3898abd

Please sign in to comment.