Revision 148 | Blame | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed
<?phpnamespace Spatie\FlareClient;use Closure;use Error;use ErrorException;use Exception;use Illuminate\Contracts\Container\Container;use Illuminate\Pipeline\Pipeline;use Spatie\FlareClient\Concerns\HasContext;use Spatie\FlareClient\Context\BaseContextProviderDetector;use Spatie\FlareClient\Context\ContextProviderDetector;use Spatie\FlareClient\Enums\MessageLevels;use Spatie\FlareClient\FlareMiddleware\AddEnvironmentInformation;use Spatie\FlareClient\FlareMiddleware\AddGlows;use Spatie\FlareClient\FlareMiddleware\CensorRequestBodyFields;use Spatie\FlareClient\FlareMiddleware\FlareMiddleware;use Spatie\FlareClient\FlareMiddleware\RemoveRequestIp;use Spatie\FlareClient\Glows\Glow;use Spatie\FlareClient\Glows\GlowRecorder;use Spatie\FlareClient\Http\Client;use Throwable;class Flare{use HasContext;protected Client $client;protected Api $api;/** @var array<int, FlareMiddleware|class-string<FlareMiddleware>> */protected array $middleware = [];protected GlowRecorder $recorder;protected ?string $applicationPath = null;protected ContextProviderDetector $contextDetector;protected ?Closure $previousExceptionHandler = null;/** @var null|callable */protected $previousErrorHandler = null;/** @var null|callable */protected $determineVersionCallable = null;protected ?int $reportErrorLevels = null;/** @var null|callable */protected $filterExceptionsCallable = null;/** @var null|callable */protected $filterReportsCallable = null;protected ?string $stage = null;protected ?string $requestId = null;protected ?Container $container = null;public static function make(string $apiKey = null,ContextProviderDetector $contextDetector = null): self {$client = new Client($apiKey);return new self($client, $contextDetector);}public function setApiToken(string $apiToken): self{$this->client->setApiToken($apiToken);return $this;}public function apiTokenSet(): bool{return $this->client->apiTokenSet();}public function setBaseUrl(string $baseUrl): self{$this->client->setBaseUrl($baseUrl);return $this;}public function setStage(?string $stage): self{$this->stage = $stage;return $this;}public function sendReportsImmediately(): self{$this->api->sendReportsImmediately();return $this;}public function determineVersionUsing(callable $determineVersionCallable): self{$this->determineVersionCallable = $determineVersionCallable;return $this;}public function reportErrorLevels(int $reportErrorLevels): self{$this->reportErrorLevels = $reportErrorLevels;return $this;}public function filterExceptionsUsing(callable $filterExceptionsCallable): self{$this->filterExceptionsCallable = $filterExceptionsCallable;return $this;}public function filterReportsUsing(callable $filterReportsCallable): self{$this->filterReportsCallable = $filterReportsCallable;return $this;}public function version(): ?string{if (! $this->determineVersionCallable) {return null;}return ($this->determineVersionCallable)();}/*** @param \Spatie\FlareClient\Http\Client $client* @param \Spatie\FlareClient\Context\ContextProviderDetector|null $contextDetector* @param array<int, FlareMiddleware> $middleware*/public function __construct(Client $client,ContextProviderDetector $contextDetector = null,array $middleware = []) {$this->client = $client;$this->recorder = new GlowRecorder();$this->contextDetector = $contextDetector ?? new BaseContextProviderDetector();$this->middleware = $middleware;$this->api = new Api($this->client);$this->registerDefaultMiddleware();}/** @return array<int, FlareMiddleware|class-string<FlareMiddleware>> */public function getMiddleware(): array{return $this->middleware;}public function setContextProviderDetector(ContextProviderDetector $contextDetector): self{$this->contextDetector = $contextDetector;return $this;}public function setContainer(Container $container): self{$this->container = $container;return $this;}public function registerFlareHandlers(): self{$this->registerExceptionHandler();$this->registerErrorHandler();return $this;}public function registerExceptionHandler(): self{/** @phpstan-ignore-next-line */$this->previousExceptionHandler = set_exception_handler([$this, 'handleException']);return $this;}public function registerErrorHandler(): self{$this->previousErrorHandler = set_error_handler([$this, 'handleError']);return $this;}protected function registerDefaultMiddleware(): self{return $this->registerMiddleware([new AddGlows($this->recorder),new AddEnvironmentInformation(),]);}/*** @param FlareMiddleware|array<FlareMiddleware>|class-string<FlareMiddleware>|callable $middleware** @return $this*/public function registerMiddleware($middleware): self{if (! is_array($middleware)) {$middleware = [$middleware];}$this->middleware = array_merge($this->middleware, $middleware);return $this;}/*** @return array<int,FlareMiddleware|class-string<FlareMiddleware>>*/public function getMiddlewares(): array{return $this->middleware;}/*** @param string $name* @param string $messageLevel* @param array<int, mixed> $metaData** @return $this*/public function glow(string $name,string $messageLevel = MessageLevels::INFO,array $metaData = []): self {$this->recorder->record(new Glow($name, $messageLevel, $metaData));return $this;}public function handleException(Throwable $throwable): void{$this->report($throwable);if ($this->previousExceptionHandler) {call_user_func($this->previousExceptionHandler, $throwable);}}/*** @return mixed*/public function handleError(mixed $code, string $message, string $file = '', int $line = 0){$exception = new ErrorException($message, 0, $code, $file, $line);$this->report($exception);if ($this->previousErrorHandler) {return call_user_func($this->previousErrorHandler,$message,$code,$file,$line);}}public function applicationPath(string $applicationPath): self{$this->applicationPath = $applicationPath;return $this;}public function report(Throwable $throwable, callable $callback = null, Report $report = null): ?Report{if (! $this->shouldSendReport($throwable)) {return null;}$report ??= $this->createReport($throwable);if (! is_null($callback)) {call_user_func($callback, $report);}$this->recorder->reset();$this->sendReportToApi($report);return $report;}protected function shouldSendReport(Throwable $throwable): bool{if (isset($this->reportErrorLevels) && $throwable instanceof Error) {return (bool)($this->reportErrorLevels & $throwable->getCode());}if (isset($this->reportErrorLevels) && $throwable instanceof ErrorException) {return (bool)($this->reportErrorLevels & $throwable->getSeverity());}if ($this->filterExceptionsCallable && $throwable instanceof Exception) {return (bool)(call_user_func($this->filterExceptionsCallable, $throwable));}return true;}public function reportMessage(string $message, string $logLevel, callable $callback = null): void{$report = $this->createReportFromMessage($message, $logLevel);if (! is_null($callback)) {call_user_func($callback, $report);}$this->sendReportToApi($report);}public function sendTestReport(Throwable $throwable): void{$this->api->sendTestReport($this->createReport($throwable));}protected function sendReportToApi(Report $report): void{if ($this->filterReportsCallable) {if (! call_user_func($this->filterReportsCallable, $report)) {return;}}try {$this->api->report($report);} catch (Exception $exception) {}}public function reset(): void{$this->api->sendQueuedReports();$this->userProvidedContext = [];$this->recorder->reset();}protected function applyAdditionalParameters(Report $report): void{$report->stage($this->stage)->messageLevel($this->messageLevel)->setApplicationPath($this->applicationPath)->userProvidedContext($this->userProvidedContext);}public function anonymizeIp(): self{$this->registerMiddleware(new RemoveRequestIp());return $this;}/*** @param array<int, string> $fieldNames** @return $this*/public function censorRequestBodyFields(array $fieldNames): self{$this->registerMiddleware(new CensorRequestBodyFields($fieldNames));return $this;}public function createReport(Throwable $throwable): Report{$report = Report::createForThrowable($throwable,$this->contextDetector->detectCurrentContext(),$this->applicationPath,$this->version());return $this->applyMiddlewareToReport($report);}public function createReportFromMessage(string $message, string $logLevel): Report{$report = Report::createForMessage($message,$logLevel,$this->contextDetector->detectCurrentContext(),$this->applicationPath);return $this->applyMiddlewareToReport($report);}protected function applyMiddlewareToReport(Report $report): Report{$this->applyAdditionalParameters($report);$middleware = array_map(function ($singleMiddleware) {return is_string($singleMiddleware)? new $singleMiddleware: $singleMiddleware;}, $this->middleware);$report = (new Pipeline())->send($report)->through($middleware)->then(fn ($report) => $report);return $report;}}