diff --git a/src/Instrumentation/Laravel/_register.php b/src/Instrumentation/Laravel/_register.php
index c265131fb..5904a0614 100644
--- a/src/Instrumentation/Laravel/_register.php
+++ b/src/Instrumentation/Laravel/_register.php
@@ -1,18 +1,30 @@
=7.41.3",
"phan/phan": "^5.0",
"php-http/mock-client": "*",
"phpstan/phpstan": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
- "phpunit/phpunit": "^9.5",
+ "phpunit/phpunit": "^10.5 || ^11.3",
"psalm/plugin-phpunit": "^0.19.2",
- "spatie/laravel-ignition": "*",
"vimeo/psalm": "6.4.0"
},
"autoload": {
@@ -48,11 +42,27 @@
"OpenTelemetry\\Tests\\Contrib\\Instrumentation\\Laravel\\": "tests/"
}
},
+ "suggest": {
+ "ext-opentelemetry": "Required to provide auto-instrumentation hooks.",
+ "open-telemetry/opentelemetry-propagation-server-timing": "Automatically propagate the context to the client through server-timing headers.",
+ "open-telemetry/opentelemetry-propagation-traceresponse": "Automatically propagate the context to the client through trace-response headers."
+ },
+ "extra": {
+ "spi-config": {
+ "autoload-files": true
+ },
+ "spi": {
+ "OpenTelemetry\\API\\Configuration\\Config\\ComponentProvider": [
+ "OpenTelemetry\\Contrib\\Instrumentation\\Laravel\\ComponentProvider\\LaravelComponentProvider"
+ ]
+ }
+ },
"config": {
"lock": false,
"sort-packages": true,
"allow-plugins": {
- "php-http/discovery": false
+ "php-http/discovery": false,
+ "tbachert/spi": true
}
}
}
diff --git a/src/Instrumentation/Laravel/phpunit.xml.dist b/src/Instrumentation/Laravel/phpunit.xml.dist
index 0906e0e22..0af9a508c 100644
--- a/src/Instrumentation/Laravel/phpunit.xml.dist
+++ b/src/Instrumentation/Laravel/phpunit.xml.dist
@@ -5,6 +5,7 @@
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
+ bootstrap="tests/bootstrap.php"
cacheResult="false"
colors="false"
convertErrorsToExceptions="true"
@@ -41,7 +42,10 @@
-
+
+
+
+
diff --git a/src/Instrumentation/Laravel/src/ComponentProvider/LaravelComponentProvider.php b/src/Instrumentation/Laravel/src/ComponentProvider/LaravelComponentProvider.php
new file mode 100644
index 000000000..3d59b3368
--- /dev/null
+++ b/src/Instrumentation/Laravel/src/ComponentProvider/LaravelComponentProvider.php
@@ -0,0 +1,33 @@
+arrayNode('laravel')
+ ->canBeDisabled()
+ ->addDefaultsIfNotSet()
+ ;
+ }
+}
diff --git a/src/Instrumentation/Laravel/src/Hooks/Hook.php b/src/Instrumentation/Laravel/src/Hooks/Hook.php
new file mode 100644
index 000000000..cdf41d2a4
--- /dev/null
+++ b/src/Instrumentation/Laravel/src/Hooks/Hook.php
@@ -0,0 +1,18 @@
+hookExecute();
+ public function instrument(
+ LaravelInstrumentation $instrumentation,
+ HookManagerInterface $hookManager,
+ InstrumentationContext $context,
+ ): void {
+ $tracer = $context->tracerProvider->getTracer(
+ $instrumentation->buildProviderName('console', 'command'),
+ schemaUrl: Version::VERSION_1_24_0->url(),
+ );
+
+ $this->hookExecute($hookManager, $tracer);
}
/** @psalm-suppress PossiblyUnusedReturnValue */
- protected function hookExecute(): bool
+ protected function hookExecute(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
- return hook(
+ $hookManager->hook(
IlluminateCommand::class,
'execute',
- pre: function (IlluminateCommand $command, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
+ preHook: function (IlluminateCommand $command, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer) {
/** @psalm-suppress ArgumentTypeCoercion */
- $builder = $this->instrumentation
- ->tracer()
+ $builder = $tracer
->spanBuilder(sprintf('Command %s', $command->getName() ?: 'unknown'))
- ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
- ->setAttribute(TraceAttributes::CODE_FILE_PATH, $filename)
- ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno);
+ ->setAttribute(CodeAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
+ ->setAttribute(CodeAttributes::CODE_FILE_PATH, $filename)
+ ->setAttribute(CodeAttributes::CODE_LINE_NUMBER, $lineno);
$parent = Context::getCurrent();
$span = $builder->startSpan();
@@ -45,7 +55,7 @@ protected function hookExecute(): bool
return $params;
},
- post: function (IlluminateCommand $command, array $params, ?int $exitCode, ?Throwable $exception) {
+ postHook: function (IlluminateCommand $command, array $params, ?int $exitCode, ?Throwable $exception) {
$scope = Context::storage()->scope();
if (!$scope) {
return;
diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Console/Kernel.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Console/Kernel.php
index 2a1c9e29c..18e89d784 100644
--- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Console/Kernel.php
+++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Console/Kernel.php
@@ -6,47 +6,56 @@
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\Kernel as KernelContract;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context as InstrumentationContext;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\HookManagerInterface;
use OpenTelemetry\API\Trace\Span;
use OpenTelemetry\API\Trace\SpanKind;
use OpenTelemetry\API\Trace\StatusCode;
+use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\Context\Context;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Hook;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Illuminate\Queue\AttributesBuilder;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHook;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHookTrait;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\PostHookTrait;
use OpenTelemetry\Contrib\Instrumentation\Laravel\LaravelInstrumentation;
-use function OpenTelemetry\Instrumentation\hook;
-use OpenTelemetry\SemConv\TraceAttributes;
+use OpenTelemetry\SemConv\Attributes\CodeAttributes;
+use OpenTelemetry\SemConv\Version;
use Throwable;
-class Kernel implements LaravelHook
+/** @psalm-suppress UnusedClass */
+class Kernel implements Hook
{
use AttributesBuilder;
- use LaravelHookTrait;
use PostHookTrait;
- public function instrument(): void
- {
- if (LaravelInstrumentation::shouldTraceCli()) {
- $this->hookHandle();
+ public function instrument(
+ LaravelInstrumentation $instrumentation,
+ HookManagerInterface $hookManager,
+ InstrumentationContext $context,
+ ): void {
+ $tracer = $context->tracerProvider->getTracer(
+ $instrumentation->buildProviderName('console', 'kernel'),
+ schemaUrl: Version::VERSION_1_24_0->url(),
+ );
+
+ if ($instrumentation->shouldTraceCli()) {
+ $this->hookHandle($hookManager, $tracer);
}
}
/** @psalm-suppress UnusedReturnValue */
- private function hookHandle(): bool
+ private function hookHandle(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
- return hook(
+ $hookManager->hook(
KernelContract::class,
'handle',
- pre: function (KernelContract $kernel, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
+ preHook: function (KernelContract $kernel, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer) {
/** @psalm-suppress ArgumentTypeCoercion */
- $builder = $this->instrumentation
- ->tracer()
+ $builder = $tracer
->spanBuilder('Artisan handler')
->setSpanKind(SpanKind::KIND_PRODUCER)
- ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
- ->setAttribute(TraceAttributes::CODE_FILE_PATH, $filename)
- ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno);
+ ->setAttribute(CodeAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
+ ->setAttribute(CodeAttributes::CODE_FILE_PATH, $filename)
+ ->setAttribute(CodeAttributes::CODE_LINE_NUMBER, $lineno);
$parent = Context::getCurrent();
$span = $builder->startSpan();
@@ -54,7 +63,7 @@ private function hookHandle(): bool
return $params;
},
- post: function (KernelContract $kernel, array $params, ?int $exitCode, ?Throwable $exception) {
+ postHook: function (KernelContract $kernel, array $params, ?int $exitCode, ?Throwable $exception) {
$scope = Context::storage()->scope();
if (!$scope) {
return;
diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Http/Kernel.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Http/Kernel.php
index b748cb715..005572c05 100644
--- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Http/Kernel.php
+++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Http/Kernel.php
@@ -8,65 +8,86 @@
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use OpenTelemetry\API\Globals;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context as InstrumentationContext;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\HookManagerInterface;
use OpenTelemetry\API\Trace\Span;
use OpenTelemetry\API\Trace\SpanInterface;
use OpenTelemetry\API\Trace\SpanKind;
use OpenTelemetry\API\Trace\StatusCode;
+use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\Context\Context;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHook;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHookTrait;
+use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Hook;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\PostHookTrait;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\LaravelInstrumentation;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Propagators\HeadersPropagator;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Propagators\ResponsePropagationSetter;
-use function OpenTelemetry\Instrumentation\hook;
-use OpenTelemetry\SemConv\TraceAttributes;
+use OpenTelemetry\SemConv\Attributes\ClientAttributes;
+use OpenTelemetry\SemConv\Attributes\CodeAttributes;
+use OpenTelemetry\SemConv\Attributes\HttpAttributes;
+use OpenTelemetry\SemConv\Attributes\NetworkAttributes;
+use OpenTelemetry\SemConv\Attributes\ServerAttributes;
+use OpenTelemetry\SemConv\Attributes\UrlAttributes;
+use OpenTelemetry\SemConv\Attributes\UserAgentAttributes;
+use OpenTelemetry\SemConv\Incubating\Attributes\HttpIncubatingAttributes;
+use OpenTelemetry\SemConv\Version;
use Symfony\Component\HttpFoundation\Response;
use Throwable;
-class Kernel implements LaravelHook
+/** @psalm-suppress UnusedClass */
+class Kernel implements Hook
{
- use LaravelHookTrait;
use PostHookTrait;
- public function instrument(): void
- {
- $this->hookHandle();
+ public function instrument(
+ LaravelInstrumentation $instrumentation,
+ HookManagerInterface $hookManager,
+ InstrumentationContext $context,
+ ): void {
+ $tracer = $context->tracerProvider->getTracer(
+ $instrumentation->buildProviderName('http', 'kernel'),
+ schemaUrl: Version::VERSION_1_24_0->url(),
+ );
+
+ $this->hookHandle($hookManager, $tracer, $context->propagator);
}
/** @psalm-suppress PossiblyUnusedReturnValue */
- protected function hookHandle(): bool
- {
- return hook(
+ protected function hookHandle(
+ HookManagerInterface $hookManager,
+ TracerInterface $tracer,
+ TextMapPropagatorInterface $propagator,
+ ): void {
+ $hookManager->hook(
KernelContract::class,
'handle',
- pre: function (KernelContract $kernel, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
+ preHook: function (KernelContract $kernel, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer, $propagator) {
$request = ($params[0] instanceof Request) ? $params[0] : null;
/** @psalm-suppress ArgumentTypeCoercion */
- $builder = $this->instrumentation
- ->tracer()
+ $builder = $tracer
->spanBuilder(sprintf('%s', $request?->method() ?? 'unknown'))
->setSpanKind(SpanKind::KIND_SERVER)
- ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
- ->setAttribute(TraceAttributes::CODE_FILE_PATH, $filename)
- ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno);
+ ->setAttribute(CodeAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
+ ->setAttribute(CodeAttributes::CODE_FILE_PATH, $filename)
+ ->setAttribute(CodeAttributes::CODE_LINE_NUMBER, $lineno);
$parent = Context::getCurrent();
if ($request) {
/** @phan-suppress-next-line PhanAccessMethodInternal */
- $parent = Globals::propagator()->extract($request, HeadersPropagator::instance());
+ $parent = $propagator->extract($request, HeadersPropagator::instance());
$span = $builder
->setParent($parent)
- ->setAttribute(TraceAttributes::URL_FULL, $request->fullUrl())
- ->setAttribute(TraceAttributes::HTTP_REQUEST_METHOD, $request->method())
- ->setAttribute(TraceAttributes::HTTP_REQUEST_BODY_SIZE, $request->header('Content-Length'))
- ->setAttribute(TraceAttributes::URL_SCHEME, $request->getScheme())
- ->setAttribute(TraceAttributes::NETWORK_PROTOCOL_VERSION, $request->getProtocolVersion())
- ->setAttribute(TraceAttributes::NETWORK_PEER_ADDRESS, $request->server('REMOTE_ADDR'))
- ->setAttribute(TraceAttributes::URL_PATH, $this->httpTarget($request))
- ->setAttribute(TraceAttributes::SERVER_ADDRESS, $this->httpHostName($request))
- ->setAttribute(TraceAttributes::SERVER_PORT, $request->getPort())
- ->setAttribute(TraceAttributes::CLIENT_PORT, $request->server('REMOTE_PORT'))
- ->setAttribute(TraceAttributes::CLIENT_ADDRESS, $request->ip())
- ->setAttribute(TraceAttributes::USER_AGENT_ORIGINAL, $request->userAgent())
+ ->setAttribute(UrlAttributes::URL_FULL, $request->fullUrl())
+ ->setAttribute(HttpAttributes::HTTP_REQUEST_METHOD, $request->method())
+ ->setAttribute(HttpIncubatingAttributes::HTTP_REQUEST_BODY_SIZE, $request->header('Content-Length'))
+ ->setAttribute(UrlAttributes::URL_SCHEME, $request->getScheme())
+ ->setAttribute(NetworkAttributes::NETWORK_PROTOCOL_VERSION, $request->getProtocolVersion())
+ ->setAttribute(NetworkAttributes::NETWORK_PEER_ADDRESS, $request->server('REMOTE_ADDR'))
+ ->setAttribute(UrlAttributes::URL_PATH, $this->httpTarget($request))
+ ->setAttribute(ServerAttributes::SERVER_ADDRESS, $this->httpHostName($request))
+ ->setAttribute(ServerAttributes::SERVER_PORT, $request->getPort())
+ ->setAttribute(ClientAttributes::CLIENT_PORT, $request->server('REMOTE_PORT'))
+ ->setAttribute(ClientAttributes::CLIENT_ADDRESS, $request->ip())
+ ->setAttribute(UserAgentAttributes::USER_AGENT_ORIGINAL, $request->userAgent())
->startSpan();
$request->attributes->set(SpanInterface::class, $span);
} else {
@@ -76,7 +97,7 @@ protected function hookHandle(): bool
return [$request];
},
- post: function (KernelContract $kernel, array $params, ?Response $response, ?Throwable $exception) {
+ postHook: function (KernelContract $kernel, array $params, ?Response $response, ?Throwable $exception) {
$scope = Context::storage()->scope();
if (!$scope) {
return;
@@ -88,16 +109,16 @@ protected function hookHandle(): bool
if ($request && $route instanceof Route) {
$span->updateName("{$request->method()} /" . ltrim($route->uri, '/'));
- $span->setAttribute(TraceAttributes::HTTP_ROUTE, $route->uri);
+ $span->setAttribute(HttpAttributes::HTTP_ROUTE, $route->uri);
}
if ($response) {
if ($response->getStatusCode() >= 500) {
$span->setStatus(StatusCode::STATUS_ERROR);
}
- $span->setAttribute(TraceAttributes::HTTP_RESPONSE_STATUS_CODE, $response->getStatusCode());
- $span->setAttribute(TraceAttributes::NETWORK_PROTOCOL_VERSION, $response->getProtocolVersion());
- $span->setAttribute(TraceAttributes::HTTP_RESPONSE_BODY_SIZE, $response->headers->get('Content-Length'));
+ $span->setAttribute(HttpAttributes::HTTP_RESPONSE_STATUS_CODE, $response->getStatusCode());
+ $span->setAttribute(NetworkAttributes::NETWORK_PROTOCOL_VERSION, $response->getProtocolVersion());
+ $span->setAttribute(HttpIncubatingAttributes::HTTP_RESPONSE_BODY_SIZE, $response->headers->get('Content-Length'));
$prop = Globals::responsePropagator();
/** @phan-suppress-next-line PhanAccessMethodInternal */
diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php
index 403cab68b..3c5e43cf1 100644
--- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php
+++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Contracts/Queue/Queue.php
@@ -7,49 +7,59 @@
use DateInterval;
use DateTimeInterface;
use Illuminate\Contracts\Queue\Queue as QueueContract;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context as InstrumentationContext;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\HookManagerInterface;
use OpenTelemetry\API\Trace\SpanKind;
+use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\Context\Context;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Hook;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Illuminate\Queue\AttributesBuilder;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHook;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHookTrait;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\PostHookTrait;
-use function OpenTelemetry\Instrumentation\hook;
-use OpenTelemetry\SemConv\TraceAttributes;
-use OpenTelemetry\SemConv\TraceAttributeValues;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\LaravelInstrumentation;
+use OpenTelemetry\SemConv\Attributes\CodeAttributes;
+use OpenTelemetry\SemConv\Incubating\Attributes\MessagingIncubatingAttributes;
+use OpenTelemetry\SemConv\Version;
use Throwable;
-class Queue implements LaravelHook
+/** @psalm-suppress UnusedClass */
+class Queue implements Hook
{
use AttributesBuilder;
- use LaravelHookTrait;
use PostHookTrait;
- public function instrument(): void
- {
- $this->hookBulk();
- $this->hookLater();
- $this->hookPushRaw();
+ public function instrument(
+ LaravelInstrumentation $instrumentation,
+ HookManagerInterface $hookManager,
+ InstrumentationContext $context,
+ ): void {
+ $tracer = $context->tracerProvider->getTracer(
+ $instrumentation->buildProviderName('queue'),
+ schemaUrl: Version::VERSION_1_24_0->url(),
+ );
+
+ $this->hookBulk($hookManager, $tracer);
+ $this->hookLater($hookManager, $tracer);
+ $this->hookPushRaw($hookManager, $tracer);
}
/** @psalm-suppress PossiblyUnusedReturnValue */
- protected function hookBulk(): bool
+ protected function hookBulk(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
- return hook(
+ $hookManager->hook(
QueueContract::class,
'bulk',
- pre: function (QueueContract $queue, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
+ preHook: function (QueueContract $queue, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer) {
$attributes = array_merge([
- TraceAttributes::CODE_FUNCTION_NAME => sprintf('%s::%s', $class, $function),
- TraceAttributes::CODE_FILE_PATH => $filename,
- TraceAttributes::CODE_LINE_NUMBER => $lineno,
- TraceAttributes::MESSAGING_BATCH_MESSAGE_COUNT => count($params[0] ?? []),
+ CodeAttributes::CODE_FUNCTION_NAME => sprintf('%s::%s', $class, $function),
+ CodeAttributes::CODE_FILE_PATH => $filename,
+ CodeAttributes::CODE_LINE_NUMBER => $lineno,
+ MessagingIncubatingAttributes::MESSAGING_BATCH_MESSAGE_COUNT => count($params[0] ?? []),
], $this->contextualMessageSystemAttributes($queue, []));
/** @psalm-suppress ArgumentTypeCoercion */
- $span = $this->instrumentation
- ->tracer()
+ $span = $tracer
->spanBuilder(vsprintf('%s %s', [
- TraceAttributeValues::MESSAGING_OPERATION_TYPE_SEND,
+ MessagingIncubatingAttributes::MESSAGING_OPERATION_TYPE_VALUE_SEND,
/** @phan-suppress-next-line PhanUndeclaredMethod */
method_exists($queue, 'getQueue') ? $queue->getQueue($params[2] ?? null) : $queue->getConnectionName(),
]))
@@ -61,19 +71,19 @@ protected function hookBulk(): bool
return $params;
},
- post: function (QueueContract $queue, array $params, $returnValue, ?Throwable $exception) {
+ postHook: function (QueueContract $queue, array $params, $returnValue, ?Throwable $exception) {
$this->endSpan($exception);
},
);
}
/** @psalm-suppress PossiblyUnusedReturnValue */
- protected function hookLater(): bool
+ protected function hookLater(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
- return hook(
+ $hookManager->hook(
QueueContract::class,
'later',
- pre: function (QueueContract $queue, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
+ preHook: function (QueueContract $queue, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer) {
$estimateDeliveryTimestamp = match (true) {
is_int($params[0]) => (new \DateTimeImmutable())->add(new DateInterval("PT{$params[0]}S"))->getTimestamp(),
$params[0] instanceof DateInterval => (new \DateTimeImmutable())->add($params[0])->getTimestamp(),
@@ -82,17 +92,16 @@ protected function hookLater(): bool
};
$attributes = [
- TraceAttributes::CODE_FUNCTION_NAME => sprintf('%s::%s', $class, $function),
- TraceAttributes::CODE_FILE_PATH => $filename,
- TraceAttributes::CODE_LINE_NUMBER => $lineno,
+ CodeAttributes::CODE_FUNCTION_NAME => sprintf('%s::%s', $class, $function),
+ CodeAttributes::CODE_FILE_PATH => $filename,
+ CodeAttributes::CODE_LINE_NUMBER => $lineno,
'messaging.message.delivery_timestamp' => $estimateDeliveryTimestamp,
];
/** @psalm-suppress ArgumentTypeCoercion */
- $span = $this->instrumentation
- ->tracer()
+ $span = $tracer
->spanBuilder(vsprintf('%s %s', [
- TraceAttributeValues::MESSAGING_OPERATION_TYPE_CREATE,
+ MessagingIncubatingAttributes::MESSAGING_OPERATION_TYPE_VALUE_CREATE,
/** @phan-suppress-next-line PhanUndeclaredMethod */
method_exists($queue, 'getQueue') ? $queue->getQueue($params[2] ?? null) : $queue->getConnectionName(),
]))
@@ -104,29 +113,28 @@ protected function hookLater(): bool
return $params;
},
- post: function (QueueContract $queue, array $params, $returnValue, ?Throwable $exception) {
+ postHook: function (QueueContract $queue, array $params, $returnValue, ?Throwable $exception) {
$this->endSpan($exception);
},
);
}
/** @psalm-suppress PossiblyUnusedReturnValue */
- protected function hookPushRaw(): bool
+ protected function hookPushRaw(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
- return hook(
+ $hookManager->hook(
QueueContract::class,
'pushRaw',
- pre: function (QueueContract $queue, array $params, string $_class, string $_function, ?string $_filename, ?int $_lineno) {
+ preHook: function (QueueContract $queue, array $params, string $_class, string $_function, ?string $_filename, ?int $_lineno) use ($tracer) {
/** @phan-suppress-next-line PhanParamTooFewUnpack */
$attributes = $this->buildMessageAttributes($queue, ...$params);
$parent = Context::getCurrent();
/** @psalm-suppress ArgumentTypeCoercion */
- $span = $this->instrumentation
- ->tracer()
+ $span = $tracer
->spanBuilder(vsprintf('%s %s', [
- TraceAttributeValues::MESSAGING_OPERATION_TYPE_CREATE,
- $attributes[TraceAttributes::MESSAGING_DESTINATION_NAME],
+ MessagingIncubatingAttributes::MESSAGING_OPERATION_TYPE_VALUE_CREATE,
+ $attributes[MessagingIncubatingAttributes::MESSAGING_DESTINATION_NAME],
]))
->setSpanKind(SpanKind::KIND_PRODUCER)
->setAttributes($attributes)
@@ -136,7 +144,7 @@ protected function hookPushRaw(): bool
return $params;
},
- post: function (QueueContract $queue, array $params, $returnValue, ?Throwable $exception) {
+ postHook: function (QueueContract $queue, array $params, $returnValue, ?Throwable $exception) {
$this->endSpan($exception);
},
);
diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Database/Eloquent/Model.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Database/Eloquent/Model.php
index 64151b426..8375d8e28 100644
--- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Database/Eloquent/Model.php
+++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Database/Eloquent/Model.php
@@ -5,46 +5,56 @@
namespace OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Illuminate\Database\Eloquent;
use Illuminate\Database\Eloquent\Model as EloquentModel;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context as InstrumentationContext;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\HookManagerInterface;
use OpenTelemetry\API\Trace\SpanKind;
+use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\Context\Context;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHook;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHookTrait;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Hook;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\PostHookTrait;
-use function OpenTelemetry\Instrumentation\hook;
-use OpenTelemetry\SemConv\TraceAttributes;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\LaravelInstrumentation;
+use OpenTelemetry\SemConv\Attributes\CodeAttributes;
+use OpenTelemetry\SemConv\Version;
use Throwable;
-class Model implements LaravelHook
+/** @psalm-suppress UnusedClass */
+class Model implements Hook
{
- use LaravelHookTrait;
use PostHookTrait;
- public function instrument(): void
- {
- $this->hookFind();
- $this->hookPerformInsert();
- $this->hookPerformUpdate();
- $this->hookDelete();
- $this->hookGetModels();
- $this->hookDestroy();
- $this->hookRefresh();
+ public function instrument(
+ LaravelInstrumentation $instrumentation,
+ HookManagerInterface $hookManager,
+ InstrumentationContext $context,
+ ): void {
+ $tracer = $context->tracerProvider->getTracer(
+ $instrumentation->buildProviderName('database', 'eloquent', 'model'),
+ schemaUrl: Version::VERSION_1_24_0->url(),
+ );
+
+ $this->hookFind($hookManager, $tracer);
+ $this->hookPerformInsert($hookManager, $tracer);
+ $this->hookPerformUpdate($hookManager, $tracer);
+ $this->hookDelete($hookManager, $tracer);
+ $this->hookGetModels($hookManager, $tracer);
+ $this->hookDestroy($hookManager, $tracer);
+ $this->hookRefresh($hookManager, $tracer);
}
- private function hookFind(): void
+ private function hookFind(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
/** @psalm-suppress UnusedFunctionCall */
- hook(
+ $hookManager->hook(
\Illuminate\Database\Eloquent\Builder::class,
'find',
- pre: function ($builder, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
+ preHook: function ($builder, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer) {
$model = $builder->getModel();
- $builder = $this->instrumentation
- ->tracer()
+ $builder = $tracer
->spanBuilder($model::class . '::find')
->setSpanKind(SpanKind::KIND_INTERNAL)
- ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
- ->setAttribute(TraceAttributes::CODE_FILE_PATH, $filename)
- ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno)
+ ->setAttribute(CodeAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
+ ->setAttribute(CodeAttributes::CODE_FILE_PATH, $filename)
+ ->setAttribute(CodeAttributes::CODE_LINE_NUMBER, $lineno)
->setAttribute('laravel.eloquent.model', $model::class)
->setAttribute('laravel.eloquent.table', $model->getTable())
->setAttribute('laravel.eloquent.operation', 'find');
@@ -55,26 +65,25 @@ private function hookFind(): void
return $params;
},
- post: function ($builder, array $params, $result, ?Throwable $exception) {
+ postHook: function ($builder, array $params, $result, ?Throwable $exception) {
$this->endSpan($exception);
}
);
}
- private function hookPerformUpdate(): void
+ private function hookPerformUpdate(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
/** @psalm-suppress UnusedFunctionCall */
- hook(
+ $hookManager->hook(
EloquentModel::class,
'performUpdate',
- pre: function (EloquentModel $model, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
- $builder = $this->instrumentation
- ->tracer()
+ preHook: function (EloquentModel $model, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer) {
+ $builder = $tracer
->spanBuilder($model::class . '::update')
->setSpanKind(SpanKind::KIND_INTERNAL)
- ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
- ->setAttribute(TraceAttributes::CODE_FILE_PATH, $filename)
- ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno)
+ ->setAttribute(CodeAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
+ ->setAttribute(CodeAttributes::CODE_FILE_PATH, $filename)
+ ->setAttribute(CodeAttributes::CODE_LINE_NUMBER, $lineno)
->setAttribute('laravel.eloquent.model', $model::class)
->setAttribute('laravel.eloquent.table', $model->getTable())
->setAttribute('laravel.eloquent.operation', 'update');
@@ -85,26 +94,25 @@ private function hookPerformUpdate(): void
return $params;
},
- post: function (EloquentModel $model, array $params, $result, ?Throwable $exception) {
+ postHook: function (EloquentModel $model, array $params, $result, ?Throwable $exception) {
$this->endSpan($exception);
}
);
}
- private function hookPerformInsert(): void
+ private function hookPerformInsert(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
/** @psalm-suppress UnusedFunctionCall */
- hook(
+ $hookManager->hook(
EloquentModel::class,
'performInsert',
- pre: function (EloquentModel $model, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
- $builder = $this->instrumentation
- ->tracer()
+ preHook: function (EloquentModel $model, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer) {
+ $builder = $tracer
->spanBuilder($model::class . '::create')
->setSpanKind(SpanKind::KIND_INTERNAL)
- ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
- ->setAttribute(TraceAttributes::CODE_FILE_PATH, $filename)
- ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno)
+ ->setAttribute(CodeAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
+ ->setAttribute(CodeAttributes::CODE_FILE_PATH, $filename)
+ ->setAttribute(CodeAttributes::CODE_LINE_NUMBER, $lineno)
->setAttribute('laravel.eloquent.model', $model::class)
->setAttribute('laravel.eloquent.table', $model->getTable())
->setAttribute('laravel.eloquent.operation', 'create');
@@ -115,26 +123,25 @@ private function hookPerformInsert(): void
return $params;
},
- post: function (EloquentModel $model, array $params, $result, ?Throwable $exception) {
+ postHook: function (EloquentModel $model, array $params, $result, ?Throwable $exception) {
$this->endSpan($exception);
}
);
}
- private function hookDelete(): void
+ private function hookDelete(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
/** @psalm-suppress UnusedFunctionCall */
- hook(
+ $hookManager->hook(
EloquentModel::class,
'delete',
- pre: function (EloquentModel $model, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
- $builder = $this->instrumentation
- ->tracer()
+ preHook: function (EloquentModel $model, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer) {
+ $builder = $tracer
->spanBuilder($model::class . '::delete')
->setSpanKind(SpanKind::KIND_INTERNAL)
- ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
- ->setAttribute(TraceAttributes::CODE_FILE_PATH, $filename)
- ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno)
+ ->setAttribute(CodeAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
+ ->setAttribute(CodeAttributes::CODE_FILE_PATH, $filename)
+ ->setAttribute(CodeAttributes::CODE_LINE_NUMBER, $lineno)
->setAttribute('laravel.eloquent.model', $model::class)
->setAttribute('laravel.eloquent.table', $model->getTable())
->setAttribute('laravel.eloquent.operation', 'delete');
@@ -145,27 +152,26 @@ private function hookDelete(): void
return $params;
},
- post: function (EloquentModel $model, array $params, $result, ?Throwable $exception) {
+ postHook: function (EloquentModel $model, array $params, $result, ?Throwable $exception) {
$this->endSpan($exception);
}
);
}
- private function hookGetModels(): void
+ private function hookGetModels(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
/** @psalm-suppress UnusedFunctionCall */
- hook(
+ $hookManager->hook(
\Illuminate\Database\Eloquent\Builder::class,
'getModels',
- pre: function ($builder, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
+ preHook: function ($builder, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer) {
$model = $builder->getModel();
- $builder = $this->instrumentation
- ->tracer()
+ $builder = $tracer
->spanBuilder($model::class . '::get')
->setSpanKind(SpanKind::KIND_INTERNAL)
- ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
- ->setAttribute(TraceAttributes::CODE_FILE_PATH, $filename)
- ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno)
+ ->setAttribute(CodeAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
+ ->setAttribute(CodeAttributes::CODE_FILE_PATH, $filename)
+ ->setAttribute(CodeAttributes::CODE_LINE_NUMBER, $lineno)
->setAttribute('laravel.eloquent.model', $model::class)
->setAttribute('laravel.eloquent.table', $model->getTable())
->setAttribute('laravel.eloquent.operation', 'get')
@@ -177,30 +183,29 @@ private function hookGetModels(): void
return $params;
},
- post: function ($builder, array $params, $result, ?Throwable $exception) {
+ postHook: function ($builder, array $params, $result, ?Throwable $exception) {
$this->endSpan($exception);
}
);
}
- private function hookDestroy(): void
+ private function hookDestroy(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
/** @psalm-suppress UnusedFunctionCall */
- hook(
+ $hookManager->hook(
EloquentModel::class,
'destroy',
- pre: function (string $modelClassName, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
+ preHook: function (string $modelClassName, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer) {
// The class-string is passed to the $model argument, because \Illuminate\Database\Eloquent\Model::destroy is static method.
// Therefore, create a class instance from a class-string, and then get the table name from the getTable function.
$model = new $modelClassName();
- $builder = $this->instrumentation
- ->tracer()
+ $builder = $tracer
->spanBuilder($model::class . '::destroy')
->setSpanKind(SpanKind::KIND_INTERNAL)
- ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
- ->setAttribute(TraceAttributes::CODE_FILE_PATH, $filename)
- ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno)
+ ->setAttribute(CodeAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
+ ->setAttribute(CodeAttributes::CODE_FILE_PATH, $filename)
+ ->setAttribute(CodeAttributes::CODE_LINE_NUMBER, $lineno)
->setAttribute('laravel.eloquent.model', $model::class)
->setAttribute('laravel.eloquent.table', $model->getTable())
->setAttribute('laravel.eloquent.operation', 'destroy');
@@ -211,26 +216,25 @@ private function hookDestroy(): void
return $params;
},
- post: function ($model, array $params, $result, ?Throwable $exception) {
+ postHook: function ($model, array $params, $result, ?Throwable $exception) {
$this->endSpan($exception);
}
);
}
- private function hookRefresh(): void
+ private function hookRefresh(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
/** @psalm-suppress UnusedFunctionCall */
- hook(
+ $hookManager->hook(
EloquentModel::class,
'refresh',
- pre: function (EloquentModel $model, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
- $builder = $this->instrumentation
- ->tracer()
+ preHook: function (EloquentModel $model, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer) {
+ $builder = $tracer
->spanBuilder($model::class . '::refresh')
->setSpanKind(SpanKind::KIND_INTERNAL)
- ->setAttribute(TraceAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
- ->setAttribute(TraceAttributes::CODE_FILE_PATH, $filename)
- ->setAttribute(TraceAttributes::CODE_LINE_NUMBER, $lineno)
+ ->setAttribute(CodeAttributes::CODE_FUNCTION_NAME, sprintf('%s::%s', $class, $function))
+ ->setAttribute(CodeAttributes::CODE_FILE_PATH, $filename)
+ ->setAttribute(CodeAttributes::CODE_LINE_NUMBER, $lineno)
->setAttribute('laravel.eloquent.model', $model::class)
->setAttribute('laravel.eloquent.table', $model->getTable())
->setAttribute('laravel.eloquent.operation', 'refresh');
@@ -241,7 +245,7 @@ private function hookRefresh(): void
return $params;
},
- post: function (EloquentModel $model, array $params, $result, ?Throwable $exception) {
+ postHook: function (EloquentModel $model, array $params, $result, ?Throwable $exception) {
$this->endSpan($exception);
}
);
diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Application.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Application.php
index 794ce0f21..8e5848233 100644
--- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Application.php
+++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Application.php
@@ -6,8 +6,10 @@
use Illuminate\Contracts\Foundation\Application as ApplicationContract;
use Illuminate\Foundation\Application as FoundationalApplication;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHook;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHookTrait;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context as InstrumentationContext;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\HookManagerInterface;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Hook;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\LaravelInstrumentation;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Watchers\CacheWatcher;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Watchers\ClientRequestWatcher;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Watchers\ExceptionWatcher;
@@ -15,26 +17,37 @@
use OpenTelemetry\Contrib\Instrumentation\Laravel\Watchers\QueryWatcher;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Watchers\RedisCommand\RedisCommandWatcher;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Watchers\Watcher;
-use function OpenTelemetry\Instrumentation\hook;
+use OpenTelemetry\SemConv\Version;
use Throwable;
-class Application implements LaravelHook
+/** @psalm-suppress UnusedClass */
+class Application implements Hook
{
- use LaravelHookTrait;
+ public function instrument(
+ LaravelInstrumentation $instrumentation,
+ HookManagerInterface $hookManager,
+ InstrumentationContext $context,
+ ): void {
+ $logger = $context->loggerProvider->getLogger(
+ $instrumentation->buildProviderName('foundation', 'application'),
+ schemaUrl: Version::VERSION_1_24_0->url(),
+ );
- public function instrument(): void
- {
- /** @psalm-suppress UnusedFunctionCall */
- hook(
+ $tracer = $context->tracerProvider->getTracer(
+ $instrumentation->buildProviderName('foundation', 'application'),
+ schemaUrl: Version::VERSION_1_24_0->url(),
+ );
+
+ $hookManager->hook(
FoundationalApplication::class,
'__construct',
- post: function (FoundationalApplication $application, array $_params, mixed $_returnValue, ?Throwable $_exception) {
+ postHook: function (FoundationalApplication $application, array $_params, mixed $_returnValue, ?Throwable $_exception) use ($logger, $tracer) {
$this->registerWatchers($application, new CacheWatcher());
- $this->registerWatchers($application, new ClientRequestWatcher($this->instrumentation));
+ $this->registerWatchers($application, new ClientRequestWatcher($tracer));
$this->registerWatchers($application, new ExceptionWatcher());
- $this->registerWatchers($application, new LogWatcher($this->instrumentation));
- $this->registerWatchers($application, new QueryWatcher($this->instrumentation));
- $this->registerWatchers($application, new RedisCommandWatcher($this->instrumentation));
+ $this->registerWatchers($application, new LogWatcher($logger));
+ $this->registerWatchers($application, new QueryWatcher($tracer));
+ $this->registerWatchers($application, new RedisCommandWatcher($tracer));
},
);
}
diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Console/ServeCommand.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Console/ServeCommand.php
index 873f63b8b..af0eb97f6 100644
--- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Console/ServeCommand.php
+++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Foundation/Console/ServeCommand.php
@@ -5,28 +5,27 @@
namespace OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Illuminate\Foundation\Console;
use Illuminate\Foundation\Console\ServeCommand as FoundationServeCommand;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHook;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHookTrait;
-use function OpenTelemetry\Instrumentation\hook;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context as InstrumentationContext;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\HookManagerInterface;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Hook;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\LaravelInstrumentation;
/**
* Instrument Laravel's local PHP development server.
+ *
+ * @psalm-suppress UnusedClass
*/
-class ServeCommand implements LaravelHook
+class ServeCommand implements Hook
{
- use LaravelHookTrait;
-
- public function instrument(): void
- {
- /** @psalm-suppress UnusedFunctionCall */
- hook(
+ public function instrument(
+ LaravelInstrumentation $instrumentation,
+ HookManagerInterface $hookManager,
+ InstrumentationContext $context,
+ ): void {
+ $hookManager->hook(
FoundationServeCommand::class,
'handle',
- pre: static function (FoundationServeCommand $_serveCommand, array $_params, string $_class, string $_function, ?string $_filename, ?int $_lineno) {
- if (!property_exists(FoundationServeCommand::class, 'passthroughVariables')) {
- return;
- }
-
+ preHook: static function (FoundationServeCommand $_serveCommand, array $_params, string $_class, string $_function, ?string $_filename, ?int $_lineno) {
foreach ($_ENV as $key => $_value) {
if (str_starts_with($key, 'OTEL_') && !in_array($key, FoundationServeCommand::$passthroughVariables)) {
FoundationServeCommand::$passthroughVariables[] = $key;
diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/AttributesBuilder.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/AttributesBuilder.php
index 766179f39..6314f068f 100644
--- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/AttributesBuilder.php
+++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/AttributesBuilder.php
@@ -8,8 +8,7 @@
use Illuminate\Queue\BeanstalkdQueue;
use Illuminate\Queue\RedisQueue;
use Illuminate\Queue\SqsQueue;
-use OpenTelemetry\SemConv\TraceAttributes;
-use OpenTelemetry\SemConv\TraceAttributeValues;
+use OpenTelemetry\SemConv\Incubating\Attributes\MessagingIncubatingAttributes;
trait AttributesBuilder
{
@@ -23,9 +22,9 @@ private function buildMessageAttributes(
$payload = json_decode($rawPayload, true) ?? [];
return array_merge([
- TraceAttributes::MESSAGING_DESTINATION_NAME => '(anonymous)',
- TraceAttributes::MESSAGING_MESSAGE_ID => $payload['uuid'] ?? $payload['id'] ?? null,
- TraceAttributes::MESSAGING_MESSAGE_ENVELOPE_SIZE => strlen($rawPayload),
+ MessagingIncubatingAttributes::MESSAGING_DESTINATION_NAME => '(anonymous)',
+ MessagingIncubatingAttributes::MESSAGING_MESSAGE_ID => $payload['uuid'] ?? $payload['id'] ?? null,
+ MessagingIncubatingAttributes::MESSAGING_MESSAGE_ENVELOPE_SIZE => strlen($rawPayload),
'messaging.message.job_name' => $payload['displayName'] ?? $payload['job'] ?? null,
'messaging.message.attempts' => $payload['attempts'] ?? 0,
'messaging.message.max_exceptions' => $payload['maxExceptions'] ?? null,
@@ -53,24 +52,24 @@ private function contextualMessageSystemAttributes(
private function beanstalkContextualAttributes(BeanstalkdQueue $queue, array $_payload, ?string $queueName = null, array $_options = [], mixed ...$_params): array
{
return [
- TraceAttributes::MESSAGING_SYSTEM => 'beanstalk',
- TraceAttributes::MESSAGING_DESTINATION_NAME => $queue->getQueue($queueName),
+ MessagingIncubatingAttributes::MESSAGING_SYSTEM => 'beanstalk',
+ MessagingIncubatingAttributes::MESSAGING_DESTINATION_NAME => $queue->getQueue($queueName),
];
}
private function redisContextualAttributes(RedisQueue $queue, array $_payload, ?string $queueName = null, array $_options = [], mixed ...$_params): array
{
return [
- TraceAttributes::MESSAGING_SYSTEM => 'redis',
- TraceAttributes::MESSAGING_DESTINATION_NAME => $queue->getQueue($queueName),
+ MessagingIncubatingAttributes::MESSAGING_SYSTEM => 'redis',
+ MessagingIncubatingAttributes::MESSAGING_DESTINATION_NAME => $queue->getQueue($queueName),
];
}
private function awsSqsContextualAttributes(SqsQueue $queue, array $_payload, ?string $queueName = null, array $_options = [], mixed ...$_params): array
{
return [
- TraceAttributes::MESSAGING_SYSTEM => TraceAttributeValues::MESSAGING_SYSTEM_AWS_SQS,
- TraceAttributes::MESSAGING_DESTINATION_NAME => $queue->getQueue($queueName),
+ MessagingIncubatingAttributes::MESSAGING_SYSTEM => MessagingIncubatingAttributes::MESSAGING_SYSTEM_VALUE_AWS_SQS,
+ MessagingIncubatingAttributes::MESSAGING_DESTINATION_NAME => $queue->getQueue($queueName),
];
}
}
diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Queue.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Queue.php
index c4a21f590..9ec1eba3d 100644
--- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Queue.php
+++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Queue.php
@@ -5,29 +5,28 @@
namespace OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Illuminate\Queue;
use Illuminate\Queue\Queue as AbstractQueue;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context as InstrumentationContext;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\HookManagerInterface;
use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHook;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHookTrait;
-use function OpenTelemetry\Instrumentation\hook;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Hook;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\LaravelInstrumentation;
use Throwable;
-class Queue implements LaravelHook
+/** @psalm-suppress UnusedClass */
+class Queue implements Hook
{
use AttributesBuilder;
- use LaravelHookTrait;
-
- public function instrument(): void
- {
- $this->hookAbstractQueueCreatePayloadArray();
- }
/** @psalm-suppress PossiblyUnusedReturnValue */
- protected function hookAbstractQueueCreatePayloadArray(): bool
- {
- return hook(
+ public function instrument(
+ LaravelInstrumentation $instrumentation,
+ HookManagerInterface $hookManager,
+ InstrumentationContext $context,
+ ): void {
+ $hookManager->hook(
AbstractQueue::class,
'createPayloadArray',
- post: function (AbstractQueue $_queue, array $_params, array $payload, ?Throwable $_exception): array {
+ postHook: function (AbstractQueue $_queue, array $_params, array $payload, ?Throwable $_exception): array {
TraceContextPropagator::getInstance()->inject($payload);
return $payload;
diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php
index 2934b2750..f4a5400fe 100644
--- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php
+++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/SyncQueue.php
@@ -5,51 +5,61 @@
namespace OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Illuminate\Queue;
use Illuminate\Queue\SyncQueue as LaravelSyncQueue;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context as InstrumentationContext;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\HookManagerInterface;
use OpenTelemetry\API\Trace\SpanKind;
+use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\Context\Context;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHook;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHookTrait;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Hook;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\PostHookTrait;
-use function OpenTelemetry\Instrumentation\hook;
-use OpenTelemetry\SemConv\TraceAttributes;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\LaravelInstrumentation;
+use OpenTelemetry\SemConv\Attributes\CodeAttributes;
+use OpenTelemetry\SemConv\Version;
use Throwable;
-class SyncQueue implements LaravelHook
+/** @psalm-suppress UnusedClass */
+class SyncQueue implements Hook
{
use AttributesBuilder;
- use LaravelHookTrait;
use PostHookTrait;
- public function instrument(): void
- {
- $this->hookPush();
+ public function instrument(
+ LaravelInstrumentation $instrumentation,
+ HookManagerInterface $hookManager,
+ InstrumentationContext $context,
+ ): void {
+ $tracer = $context->tracerProvider->getTracer(
+ $instrumentation->buildProviderName('queue', 'sync'),
+ schemaUrl: Version::VERSION_1_24_0->url(),
+ );
+
+ $this->hookPush($hookManager, $tracer);
}
/** @psalm-suppress PossiblyUnusedReturnValue */
- protected function hookPush(): bool
+ protected function hookPush(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
- return hook(
+ $hookManager->hook(
LaravelSyncQueue::class,
'push',
- pre: function (LaravelSyncQueue $queue, array $params, string $class, string $function, ?string $filename, ?int $lineno) {
+ preHook: function (LaravelSyncQueue $queue, array $params, string $class, string $function, ?string $filename, ?int $lineno) use ($tracer) {
/** @psalm-suppress ArgumentTypeCoercion */
- $span = $this->instrumentation
- ->tracer()
+ $span = $tracer
->spanBuilder(vsprintf('%s %s', [
$queue->getConnectionName(),
'process',
]))
->setSpanKind(SpanKind::KIND_INTERNAL)
->setAttributes([
- TraceAttributes::CODE_FUNCTION_NAME => sprintf('%s::%s', $class, $function),
- TraceAttributes::CODE_FILE_PATH => $filename,
- TraceAttributes::CODE_LINE_NUMBER => $lineno,
+ CodeAttributes::CODE_FUNCTION_NAME => sprintf('%s::%s', $class, $function),
+ CodeAttributes::CODE_FILE_PATH => $filename,
+ CodeAttributes::CODE_LINE_NUMBER => $lineno,
])
->startSpan();
Context::storage()->attach($span->storeInContext(Context::getCurrent()));
},
- post: function (LaravelSyncQueue $queue, array $params, mixed $returnValue, ?Throwable $exception) {
+ postHook: function (LaravelSyncQueue $queue, array $params, mixed $returnValue, ?Throwable $exception) {
$this->endSpan($exception);
},
);
diff --git a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php
index 783b67ac0..b3c89db22 100644
--- a/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php
+++ b/src/Instrumentation/Laravel/src/Hooks/Illuminate/Queue/Worker.php
@@ -6,37 +6,47 @@
use Illuminate\Contracts\Queue\Job;
use Illuminate\Queue\Worker as QueueWorker;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context as InstrumentationContext;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\HookManagerInterface;
use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
use OpenTelemetry\API\Trace\Span;
use OpenTelemetry\API\Trace\SpanKind;
+use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\Context\Context;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHook;
-use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHookTrait;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Hook;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\PostHookTrait;
-use function OpenTelemetry\Instrumentation\hook;
-use OpenTelemetry\SemConv\TraceAttributes;
-use OpenTelemetry\SemConv\TraceAttributeValues;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\LaravelInstrumentation;
+use OpenTelemetry\SemConv\Incubating\Attributes\MessagingIncubatingAttributes;
+use OpenTelemetry\SemConv\Version;
use Throwable;
-class Worker implements LaravelHook
+/** @psalm-suppress UnusedClass */
+class Worker implements Hook
{
use AttributesBuilder;
- use LaravelHookTrait;
use PostHookTrait;
- public function instrument(): void
- {
- $this->hookWorkerProcess();
- $this->hookWorkerGetNextJob();
+ public function instrument(
+ LaravelInstrumentation $instrumentation,
+ HookManagerInterface $hookManager,
+ InstrumentationContext $context,
+ ): void {
+ $tracer = $context->tracerProvider->getTracer(
+ $instrumentation->buildProviderName('queue', 'worker'),
+ schemaUrl: Version::VERSION_1_24_0->url(),
+ );
+
+ $this->hookWorkerProcess($hookManager, $tracer);
+ $this->hookWorkerGetNextJob($hookManager, $tracer);
}
/** @psalm-suppress UnusedReturnValue */
- private function hookWorkerProcess(): bool
+ private function hookWorkerProcess(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
- return hook(
+ $hookManager->hook(
QueueWorker::class,
'process',
- pre: function (QueueWorker $worker, array $params, string $_class, string $_function, ?string $_filename, ?int $_lineno) {
+ preHook: function (QueueWorker $worker, array $params, string $_class, string $_function, ?string $_filename, ?int $_lineno) use ($tracer) {
$connectionName = $params[0];
/** @var Job $job */
$job = $params[1];
@@ -49,11 +59,10 @@ private function hookWorkerProcess(): bool
$attributes = $this->buildMessageAttributes($queue, $job->getRawBody(), $job->getQueue());
/** @psalm-suppress ArgumentTypeCoercion */
- $span = $this->instrumentation
- ->tracer()
+ $span = $tracer
->spanBuilder(vsprintf('%s %s', [
- TraceAttributeValues::MESSAGING_OPERATION_TYPE_PROCESS,
- $attributes[TraceAttributes::MESSAGING_DESTINATION_NAME],
+ MessagingIncubatingAttributes::MESSAGING_OPERATION_TYPE_VALUE_PROCESS,
+ $attributes[MessagingIncubatingAttributes::MESSAGING_DESTINATION_NAME],
]))
->setSpanKind(SpanKind::KIND_CONSUMER)
->setParent($parent)
@@ -64,7 +73,7 @@ private function hookWorkerProcess(): bool
return $params;
},
- post: function (QueueWorker $worker, array $params, $returnValue, ?Throwable $exception) {
+ postHook: function (QueueWorker $worker, array $params, $returnValue, ?Throwable $exception) {
$scope = Context::storage()->scope();
if (!$scope) {
return;
@@ -84,12 +93,12 @@ private function hookWorkerProcess(): bool
}
/** @psalm-suppress UnusedReturnValue */
- private function hookWorkerGetNextJob(): bool
+ private function hookWorkerGetNextJob(HookManagerInterface $hookManager, TracerInterface $tracer): void
{
- return hook(
+ $hookManager->hook(
QueueWorker::class,
'getNextJob',
- pre: function (QueueWorker $_worker, array $params, string $_class, string $_function, ?string $_filename, ?int $_lineno) {
+ preHook: function (QueueWorker $_worker, array $params, string $_class, string $_function, ?string $_filename, ?int $_lineno) use ($tracer) {
/** @var \Illuminate\Contracts\Queue\Queue $connection */
$connection = $params[0];
$queue = $params[1];
@@ -97,11 +106,10 @@ private function hookWorkerGetNextJob(): bool
$attributes = $this->buildMessageAttributes($connection, '', $queue);
/** @psalm-suppress ArgumentTypeCoercion */
- $span = $this->instrumentation
- ->tracer()
+ $span = $tracer
->spanBuilder(vsprintf('%s %s', [
- TraceAttributeValues::MESSAGING_OPERATION_TYPE_RECEIVE,
- $attributes[TraceAttributes::MESSAGING_DESTINATION_NAME],
+ MessagingIncubatingAttributes::MESSAGING_OPERATION_TYPE_VALUE_RECEIVE,
+ $attributes[MessagingIncubatingAttributes::MESSAGING_DESTINATION_NAME],
]))
->setSpanKind(SpanKind::KIND_CONSUMER)
->setAttributes($attributes)
@@ -111,7 +119,7 @@ private function hookWorkerGetNextJob(): bool
return $params;
},
- post: function (QueueWorker $_worker, array $params, ?Job $job, ?Throwable $exception) {
+ postHook: function (QueueWorker $_worker, array $params, ?Job $job, ?Throwable $exception) {
$scope = Context::storage()->scope();
if (!$scope) {
return;
diff --git a/src/Instrumentation/Laravel/src/Hooks/LaravelHook.php b/src/Instrumentation/Laravel/src/Hooks/LaravelHook.php
deleted file mode 100644
index e36284ad8..000000000
--- a/src/Instrumentation/Laravel/src/Hooks/LaravelHook.php
+++ /dev/null
@@ -1,15 +0,0 @@
-instrument();
- }
-
- return self::$instance;
- }
-}
diff --git a/src/Instrumentation/Laravel/src/LaravelConfiguration.php b/src/Instrumentation/Laravel/src/LaravelConfiguration.php
new file mode 100644
index 000000000..48e5acf43
--- /dev/null
+++ b/src/Instrumentation/Laravel/src/LaravelConfiguration.php
@@ -0,0 +1,31 @@
+ !class_exists(Sdk::class) || !Sdk::isInstrumentationDisabled('laravel'),
+ ]);
+ }
+}
diff --git a/src/Instrumentation/Laravel/src/LaravelInstrumentation.php b/src/Instrumentation/Laravel/src/LaravelInstrumentation.php
index e3c210ba8..ad840b1f8 100644
--- a/src/Instrumentation/Laravel/src/LaravelInstrumentation.php
+++ b/src/Instrumentation/Laravel/src/LaravelInstrumentation.php
@@ -4,39 +4,43 @@
namespace OpenTelemetry\Contrib\Instrumentation\Laravel;
-use OpenTelemetry\API\Instrumentation\CachedInstrumentation;
-use OpenTelemetry\SDK\Common\Configuration\Configuration;
+use Nevay\SPI\ServiceLoader;
+use OpenTelemetry\API\Configuration\ConfigProperties;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\HookManagerInterface;
+use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Instrumentation;
+use OpenTelemetry\API\Instrumentation\ConfigurationResolver;
+use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\Hook;
-class LaravelInstrumentation
+class LaravelInstrumentation implements Instrumentation
{
- public const NAME = 'laravel';
+ public const INSTRUMENTATION_NAME = 'io.opentelemetry.contrib.php.laravel';
/** @psalm-suppress PossiblyUnusedMethod */
- public static function register(): void
+ public function register(HookManagerInterface $hookManager, ConfigProperties $configuration, Context $context): void
{
- $instrumentation = new CachedInstrumentation(
- 'io.opentelemetry.contrib.php.laravel',
- null,
- 'https://opentelemetry.io/schemas/1.32.0',
- );
-
- Hooks\Illuminate\Console\Command::hook($instrumentation);
- Hooks\Illuminate\Contracts\Console\Kernel::hook($instrumentation);
- Hooks\Illuminate\Contracts\Http\Kernel::hook($instrumentation);
- Hooks\Illuminate\Contracts\Queue\Queue::hook($instrumentation);
- Hooks\Illuminate\Foundation\Application::hook($instrumentation);
- Hooks\Illuminate\Foundation\Console\ServeCommand::hook($instrumentation);
- Hooks\Illuminate\Queue\SyncQueue::hook($instrumentation);
- Hooks\Illuminate\Queue\Queue::hook($instrumentation);
- Hooks\Illuminate\Queue\Worker::hook($instrumentation);
- Hooks\Illuminate\Database\Eloquent\Model::hook($instrumentation);
+ $config = $configuration->get(LaravelConfiguration::class) ?? LaravelConfiguration::default();
+
+ if (! $config->enabled) {
+ return;
+ }
+
+ foreach (ServiceLoader::load(Hook::class) as $hook) {
+ /** @var Hook $hook */
+ $hook->instrument($this, $hookManager, $context);
+ }
+ }
+
+ public function buildProviderName(string ...$component): string
+ {
+ return implode('.', [
+ self::INSTRUMENTATION_NAME,
+ ...$component,
+ ]);
}
- public static function shouldTraceCli(): bool
+ public function shouldTraceCli(): bool
{
- return PHP_SAPI !== 'cli' || (
- class_exists(Configuration::class)
- && Configuration::getBoolean('OTEL_PHP_TRACE_CLI_ENABLED', false)
- );
+ return PHP_SAPI !== 'cli' || (new ConfigurationResolver())->getBoolean('OTEL_PHP_TRACE_CLI_ENABLED');
}
}
diff --git a/src/Instrumentation/Laravel/src/Watchers/ClientRequestWatcher.php b/src/Instrumentation/Laravel/src/Watchers/ClientRequestWatcher.php
index 3cf025dd4..7c0992076 100644
--- a/src/Instrumentation/Laravel/src/Watchers/ClientRequestWatcher.php
+++ b/src/Instrumentation/Laravel/src/Watchers/ClientRequestWatcher.php
@@ -10,10 +10,10 @@
use Illuminate\Http\Client\Events\ResponseReceived;
use Illuminate\Http\Client\Request;
use Illuminate\Http\Client\Response;
-use OpenTelemetry\API\Instrumentation\CachedInstrumentation;
use OpenTelemetry\API\Trace\SpanInterface;
use OpenTelemetry\API\Trace\SpanKind;
use OpenTelemetry\API\Trace\StatusCode;
+use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\SemConv\TraceAttributes;
use Symfony\Component\HttpFoundation\Response as HttpResponse;
@@ -25,7 +25,7 @@ class ClientRequestWatcher extends Watcher
protected array $spans = [];
public function __construct(
- private CachedInstrumentation $instrumentation,
+ private readonly TracerInterface $tracer,
) {
}
@@ -53,15 +53,16 @@ public function recordRequest(RequestSending $request): void
if ($parsedUrl->has('query')) {
$processedUrl .= '?' . $parsedUrl->get('query');
}
- $span = $this->instrumentation->tracer()->spanBuilder($request->request->method())
+ $span = $this->tracer
+ ->spanBuilder($request->request->method())
->setSpanKind(SpanKind::KIND_CLIENT)
->setAttributes([
TraceAttributes::HTTP_REQUEST_METHOD => $request->request->method(),
TraceAttributes::URL_FULL => $processedUrl,
- TraceAttributes::URL_PATH => $parsedUrl['path'] ?? '',
- TraceAttributes::URL_SCHEME => $parsedUrl['scheme'] ?? '',
- TraceAttributes::SERVER_ADDRESS => $parsedUrl['host'] ?? '',
- TraceAttributes::SERVER_PORT => $parsedUrl['port'] ?? '',
+ TraceAttributes::URL_PATH => $parsedUrl['path'] ?? null,
+ TraceAttributes::URL_SCHEME => $parsedUrl['scheme'] ?? null,
+ TraceAttributes::SERVER_ADDRESS => $parsedUrl['host'] ?? null,
+ TraceAttributes::SERVER_PORT => $parsedUrl['port'] ?? null,
])
->startSpan();
$this->spans[$this->createRequestComparisonHash($request->request)] = $span;
diff --git a/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php b/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php
index 169921235..292b74281 100644
--- a/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php
+++ b/src/Instrumentation/Laravel/src/Watchers/LogWatcher.php
@@ -7,7 +7,7 @@
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Log\Events\MessageLogged;
use Illuminate\Log\LogManager;
-use OpenTelemetry\API\Instrumentation\CachedInstrumentation;
+use OpenTelemetry\API\Logs\LoggerInterface;
use OpenTelemetry\API\Logs\LogRecord;
use OpenTelemetry\API\Logs\Severity;
use OpenTelemetry\SDK\Common\Exception\StackTraceFormatter;
@@ -16,9 +16,10 @@
class LogWatcher extends Watcher
{
- private LogManager $logger;
+ private LogManager $logManager;
+
public function __construct(
- private CachedInstrumentation $instrumentation,
+ private readonly LoggerInterface $logger,
) {
}
@@ -29,7 +30,7 @@ public function register(Application $app): void
$app['events']->listen(MessageLogged::class, [$this, 'recordLog']);
/** @phan-suppress-next-line PhanTypeArraySuspicious */
- $this->logger = $app['log'];
+ $this->logManager = $app['log'];
}
/**
@@ -39,7 +40,7 @@ public function register(Application $app): void
*/
public function recordLog(MessageLogged $log): void
{
- $underlyingLogger = $this->logger->getLogger();
+ $underlyingLogger = $this->logManager->getLogger();
/**
* This assumes that the underlying logger (expected to be monolog) would accept `$log->level` as a string.
@@ -71,14 +72,12 @@ public function recordLog(MessageLogged $log): void
] : [],
];
- $logger = $this->instrumentation->logger();
-
$record = (new LogRecord($log->message))
->setSeverityText($log->level)
->setSeverityNumber(Severity::fromPsr3($log->level))
->setAttributes($attributes);
- $logger->emit($record);
+ $this->logger->emit($record);
}
private function getExceptionFromContext(array $context): ?Throwable
diff --git a/src/Instrumentation/Laravel/src/Watchers/QueryWatcher.php b/src/Instrumentation/Laravel/src/Watchers/QueryWatcher.php
index 9cb5ac7b6..8d4903dcf 100644
--- a/src/Instrumentation/Laravel/src/Watchers/QueryWatcher.php
+++ b/src/Instrumentation/Laravel/src/Watchers/QueryWatcher.php
@@ -7,14 +7,14 @@
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Support\Str;
-use OpenTelemetry\API\Instrumentation\CachedInstrumentation;
use OpenTelemetry\API\Trace\SpanKind;
+use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\SemConv\TraceAttributes;
class QueryWatcher extends Watcher
{
public function __construct(
- private CachedInstrumentation $instrumentation,
+ private readonly TracerInterface $tracer,
) {
}
@@ -38,7 +38,8 @@ public function recordQuery(QueryExecuted $query): void
$operationName = null;
}
/** @psalm-suppress ArgumentTypeCoercion */
- $span = $this->instrumentation->tracer()->spanBuilder('sql ' . $operationName)
+ $span = $this->tracer
+ ->spanBuilder('sql ' . $operationName)
->setSpanKind(SpanKind::KIND_CLIENT)
->setStartTimestamp($this->calculateQueryStartTime($nowInNs, $query->time))
->startSpan();
diff --git a/src/Instrumentation/Laravel/src/Watchers/RedisCommand/RedisCommandWatcher.php b/src/Instrumentation/Laravel/src/Watchers/RedisCommand/RedisCommandWatcher.php
index db8e84992..52b3dc377 100644
--- a/src/Instrumentation/Laravel/src/Watchers/RedisCommand/RedisCommandWatcher.php
+++ b/src/Instrumentation/Laravel/src/Watchers/RedisCommand/RedisCommandWatcher.php
@@ -9,8 +9,8 @@
use Illuminate\Redis\Connections\PhpRedisConnection;
use Illuminate\Redis\Connections\PredisConnection;
use Illuminate\Redis\Events\CommandExecuted;
-use OpenTelemetry\API\Instrumentation\CachedInstrumentation;
use OpenTelemetry\API\Trace\SpanKind;
+use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\Contrib\Instrumentation\Laravel\Watchers\Watcher;
use OpenTelemetry\SemConv\TraceAttributes;
use OpenTelemetry\SemConv\TraceAttributeValues;
@@ -24,7 +24,7 @@
class RedisCommandWatcher extends Watcher
{
public function __construct(
- private CachedInstrumentation $instrumentation,
+ private readonly TracerInterface $tracer,
) {
}
@@ -46,7 +46,7 @@ public function recordRedisCommand(CommandExecuted $event): void
$operationName = strtoupper($event->command);
/** @psalm-suppress ArgumentTypeCoercion */
- $span = $this->instrumentation->tracer()
+ $span = $this->tracer
->spanBuilder($operationName)
->setSpanKind(SpanKind::KIND_CLIENT)
->setStartTimestamp($this->calculateQueryStartTime($nowInNs, $event->time))
@@ -82,7 +82,7 @@ private function fetchDbIndex(Connection $connection): ?int
}
return null;
- } catch (Throwable $e) {
+ } catch (Throwable) {
return null;
}
}
@@ -98,7 +98,7 @@ private function fetchDbHost(Connection $connection): ?string
}
return null;
- } catch (Throwable $e) {
+ } catch (Throwable) {
return null;
}
}
diff --git a/src/Instrumentation/Laravel/tests/Fixtures/ComponentProvider/LogRecordExporterInMemory.php b/src/Instrumentation/Laravel/tests/Fixtures/ComponentProvider/LogRecordExporterInMemory.php
new file mode 100644
index 000000000..e9aff332b
--- /dev/null
+++ b/src/Instrumentation/Laravel/tests/Fixtures/ComponentProvider/LogRecordExporterInMemory.php
@@ -0,0 +1,27 @@
+arrayNode('test/in_memory_exporter');
+ }
+}
diff --git a/src/Instrumentation/Laravel/tests/Fixtures/ComponentProvider/SpanExporterInMemory.php b/src/Instrumentation/Laravel/tests/Fixtures/ComponentProvider/SpanExporterInMemory.php
new file mode 100644
index 000000000..818a8173a
--- /dev/null
+++ b/src/Instrumentation/Laravel/tests/Fixtures/ComponentProvider/SpanExporterInMemory.php
@@ -0,0 +1,27 @@
+arrayNode('test/in_memory_exporter');
+ }
+}
diff --git a/src/Instrumentation/Laravel/tests/Fixtures/TestStorage.php b/src/Instrumentation/Laravel/tests/Fixtures/TestStorage.php
new file mode 100644
index 000000000..59941c7ba
--- /dev/null
+++ b/src/Instrumentation/Laravel/tests/Fixtures/TestStorage.php
@@ -0,0 +1,22 @@
+exchangeArray([]);
+ }
+}
diff --git a/src/Instrumentation/Laravel/tests/Fixtures/otel-instrumentation.yaml b/src/Instrumentation/Laravel/tests/Fixtures/otel-instrumentation.yaml
new file mode 100644
index 000000000..6d9e1e3b3
--- /dev/null
+++ b/src/Instrumentation/Laravel/tests/Fixtures/otel-instrumentation.yaml
@@ -0,0 +1,18 @@
+file_format: '0.4'
+
+logger_provider:
+ processors:
+ - simple:
+ exporter:
+ test/in_memory_exporter: {}
+
+tracer_provider:
+ processors:
+ - simple:
+ exporter:
+ test/in_memory_exporter: {}
+
+instrumentation/development:
+ php:
+ laravel:
+ enabled: true
diff --git a/src/Instrumentation/Laravel/tests/Integration/TestCase.php b/src/Instrumentation/Laravel/tests/Integration/TestCase.php
index 2ed778d86..b2f8109a1 100644
--- a/src/Instrumentation/Laravel/tests/Integration/TestCase.php
+++ b/src/Instrumentation/Laravel/tests/Integration/TestCase.php
@@ -5,57 +5,25 @@
namespace OpenTelemetry\Tests\Contrib\Instrumentation\Laravel\Integration;
use ArrayObject;
-use OpenTelemetry\API\Instrumentation\Configurator;
-use OpenTelemetry\Context\ScopeInterface;
-use OpenTelemetry\SDK\Common\Attribute\Attributes;
-use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory;
-use OpenTelemetry\SDK\Logs\Exporter\InMemoryExporter as LogInMemoryExporter;
-use OpenTelemetry\SDK\Logs\LoggerProvider;
-use OpenTelemetry\SDK\Logs\Processor\SimpleLogRecordProcessor;
-use OpenTelemetry\SDK\Trace\ImmutableSpan;
-use OpenTelemetry\SDK\Trace\SpanExporter\InMemoryExporter as SpanInMemoryExporter;
-use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
-use OpenTelemetry\SDK\Trace\TracerProvider;
+use OpenTelemetry\Tests\Contrib\Instrumentation\Laravel\Fixtures\TestStorage;
use Orchestra\Testbench\TestCase as BaseTestCase;
+use PHPUnit\Framework\Attributes\After;
+use PHPUnit\Framework\Attributes\Before;
/** @psalm-suppress UnusedClass */
abstract class TestCase extends BaseTestCase
{
- protected ScopeInterface $scope;
- /** @var ArrayObject|ImmutableSpan[] $storage */
protected ArrayObject $storage;
- protected ArrayObject $loggerStorage;
- protected TracerProvider $tracerProvider;
- protected LoggerProvider $loggerProvider;
- public function setUp(): void
+ #[Before]
+ public function setUpTestStorage(): void
{
- parent::setUp();
-
- $this->storage = new ArrayObject();
- $this->tracerProvider = new TracerProvider(
- new SimpleSpanProcessor(
- new SpanInMemoryExporter($this->storage),
- ),
- );
-
- $this->loggerProvider = new LoggerProvider(
- new SimpleLogRecordProcessor(
- new LogInMemoryExporter($this->storage),
- ),
- new InstrumentationScopeFactory(Attributes::factory())
- );
-
- $this->scope = Configurator::create()
- ->withTracerProvider($this->tracerProvider)
- ->withLoggerProvider($this->loggerProvider)
- ->activate();
+ $this->storage = TestStorage::getInstance();
}
- public function tearDown(): void
+ #[After]
+ public function tearDownTestStorage(): void
{
- parent::tearDown();
-
- $this->scope->detach();
+ TestStorage::reset();
}
}
diff --git a/src/Instrumentation/Laravel/tests/bootstrap.php b/src/Instrumentation/Laravel/tests/bootstrap.php
new file mode 100644
index 000000000..581ccce71
--- /dev/null
+++ b/src/Instrumentation/Laravel/tests/bootstrap.php
@@ -0,0 +1,21 @@
+