JFIFxxC      C  " }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3RbrFILE ON : __71c931/index.php gilour
<?php namespace Sentry\Laravel\Features; use Closure; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Queue\Events\JobExceptionOccurred; use Illuminate\Queue\Events\JobProcessed; use Illuminate\Queue\Events\JobProcessing; use Illuminate\Queue\Events\JobQueued; use Illuminate\Queue\Events\JobQueueing; use Illuminate\Queue\Events\WorkerStopping; use Illuminate\Queue\Queue; use Sentry\Breadcrumb; use Sentry\Laravel\Features\Concerns\TracksPushedScopesAndSpans; use Sentry\Laravel\Integration; use Sentry\SentrySdk; use Sentry\State\Scope; use Sentry\Tracing\PropagationContext; use Sentry\Tracing\SpanContext; use Sentry\Tracing\SpanStatus; use Sentry\Tracing\TransactionContext; use Sentry\Tracing\TransactionSource; use function Sentry\continueTrace; use function Sentry\getBaggage; use function Sentry\getTraceparent; class QueueIntegration extends Feature { use TracksPushedScopesAndSpans { pushScope as private pushScopeTrait; } private const QUEUE_SPAN_OP_QUEUE_PUBLISH = 'queue.publish'; private const QUEUE_PAYLOAD_BAGGAGE_DATA = 'sentry_baggage_data'; private const QUEUE_PAYLOAD_TRACE_PARENT_DATA = 'sentry_trace_parent_data'; public function isApplicable(): bool { if (!$this->container()->bound('queue')) { return false; } return $this->isBreadcrumbFeatureEnabled('queue_info') || $this->isTracingFeatureEnabled('queue_jobs') || $this->isTracingFeatureEnabled('queue_job_transactions'); } public function onBoot(Dispatcher $events): void { $events->listen(JobQueueing::class, [$this, 'handleJobQueueingEvent']); $events->listen(JobQueued::class, [$this, 'handleJobQueuedEvent']); $events->listen(JobProcessed::class, [$this, 'handleJobProcessedQueueEvent']); $events->listen(JobProcessing::class, [$this, 'handleJobProcessingQueueEvent']); $events->listen(WorkerStopping::class, [$this, 'handleWorkerStoppingQueueEvent']); $events->listen(JobExceptionOccurred::class, [$this, 'handleJobExceptionOccurredQueueEvent']); if ($this->isTracingFeatureEnabled('queue_jobs') || $this->isTracingFeatureEnabled('queue_job_transactions')) { Queue::createPayloadUsing(function (?string $connection, ?string $queue, ?array $payload): ?array { $parentSpan = SentrySdk::getCurrentHub()->getSpan(); if ($parentSpan !== null) { $context = (new SpanContext) ->setOp(self::QUEUE_SPAN_OP_QUEUE_PUBLISH) ->setData([ 'messaging.system' => 'laravel', 'messaging.destination.name' => $queue, 'messaging.destination.connection' => $connection, ]) ->setDescription($queue); $this->pushSpan($parentSpan->startChild($context)); } if ($payload !== null) { $payload[self::QUEUE_PAYLOAD_BAGGAGE_DATA] = getBaggage(); $payload[self::QUEUE_PAYLOAD_TRACE_PARENT_DATA] = getTraceparent(); } return $payload; }); } } public function handleJobQueueingEvent(JobQueueing $event): void { $currentSpan = SentrySdk::getCurrentHub()->getSpan(); // If there is no tracing span active there is no need to handle the event if ($currentSpan === null || $currentSpan->getOp() !== self::QUEUE_SPAN_OP_QUEUE_PUBLISH) { return; } $jobName = $event->job; if ($jobName instanceof Closure) { $jobName = 'Closure'; } elseif (is_object($jobName)) { $jobName = get_class($jobName); } $currentSpan ->setData([ 'messaging.laravel.job' => $jobName, ]) ->setDescription($jobName); } public function handleJobQueuedEvent(JobQueued $event): void { $span = $this->maybePopSpan(); if ($span !== null) { $span->finish(); } } public function handleJobProcessedQueueEvent(JobProcessed $event): void { $this->finishJobWithStatus(SpanStatus::ok()); $this->maybePopScope(); } public function handleJobProcessingQueueEvent(JobProcessing $event): void { $this->maybePopScope(); $this->pushScope(); if ($this->isBreadcrumbFeatureEnabled('queue_info')) { $job = [ 'job' => $event->job->getName(), 'queue' => $event->job->getQueue(), 'attempts' => $event->job->attempts(), 'connection' => $event->connectionName, ]; // Resolve name exists only from Laravel 5.3+ if (method_exists($event->job, 'resolveName')) { $job['resolved'] = $event->job->resolveName(); } Integration::addBreadcrumb(new Breadcrumb( Breadcrumb::LEVEL_INFO, Breadcrumb::TYPE_DEFAULT, 'queue.job', 'Processing queue job', $job )); } $parentSpan = SentrySdk::getCurrentHub()->getSpan(); // If there is no tracing span active and we don't trace jobs as transactions there is no need to handle the event if ($parentSpan === null && !$this->isTracingFeatureEnabled('queue_job_transactions')) { return; } // If there is a parent span we can record that job as a child unless configured to not do so if ($parentSpan !== null && !$this->isTracingFeatureEnabled('queue_jobs')) { return; } if ($parentSpan === null) { $baggage = $event->job->payload()[self::QUEUE_PAYLOAD_BAGGAGE_DATA] ?? null; $traceParent = $event->job->payload()[self::QUEUE_PAYLOAD_TRACE_PARENT_DATA] ?? null; $context = continueTrace($traceParent ?? '', $baggage ?? ''); // If the parent transaction was not sampled we also stop the queue job from being recorded if ($context->getParentSampled() === false) { return; } } else { $context = new SpanContext; } $resolvedJobName = $event->job->resolveName(); $job = [ 'job' => $event->job->getName(), 'queue' => $event->job->getQueue(), 'resolved' => $resolvedJobName, 'attempts' => $event->job->attempts(), 'connection' => $event->connectionName, ]; if ($context instanceof TransactionContext) { $context->setName($resolvedJobName); $context->setSource(TransactionSource::task()); } $context->setOp('queue.process'); $context->setData($job); $context->setStartTimestamp(microtime(true)); // When the parent span is null we start a new transaction otherwise we start a child of the current span if ($parentSpan === null) { $span = SentrySdk::getCurrentHub()->startTransaction($context); } else { $span = $parentSpan->startChild($context); } $this->pushSpan($span); } public function handleWorkerStoppingQueueEvent(WorkerStopping $event): void { Integration::flushEvents(); } public function handleJobExceptionOccurredQueueEvent(JobExceptionOccurred $event): void { $this->finishJobWithStatus(SpanStatus::internalError()); Integration::flushEvents(); } private function finishJobWithStatus(SpanStatus $status): void { $span = $this->maybePopSpan(); if ($span !== null) { $span->setStatus($status); $span->finish(); } } protected function pushScope(): void { $this->pushScopeTrait(); // When a job starts, we want to make sure the scope is cleared of breadcrumbs // as well as setting a new propagation context. SentrySdk::getCurrentHub()->configureScope(static function (Scope $scope) { $scope->clearBreadcrumbs(); $scope->setPropagationContext(PropagationContext::fromDefaults()); }); } }