40
vendor/sentry/sentry/.php_cs.dist
vendored
Normal file
40
vendor/sentry/sentry/.php_cs.dist
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
return PhpCsFixer\Config::create()
|
||||
->setRules([
|
||||
'@PSR2' => true,
|
||||
'@Symfony' => true,
|
||||
'@Symfony:risky' => true,
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
'concat_space' => ['spacing' => 'one'],
|
||||
'ordered_imports' => [
|
||||
'imports_order' => ['class', 'function', 'const'],
|
||||
],
|
||||
'declare_strict_types' => true,
|
||||
'psr0' => true,
|
||||
'psr4' => true,
|
||||
'random_api_migration' => true,
|
||||
'yoda_style' => true,
|
||||
'self_accessor' => false,
|
||||
'phpdoc_no_useless_inheritdoc' => false,
|
||||
'phpdoc_to_comment' => false,
|
||||
'phpdoc_align' => [
|
||||
'tags' => ['param', 'return', 'throws', 'type', 'var'],
|
||||
],
|
||||
'phpdoc_line_span' => [
|
||||
'const' => 'multi',
|
||||
'method' => 'multi',
|
||||
'property' => 'multi',
|
||||
],
|
||||
])
|
||||
->setRiskyAllowed(true)
|
||||
->setFinder(
|
||||
PhpCsFixer\Finder::create()
|
||||
->in(__DIR__)
|
||||
->exclude([
|
||||
'tests/resources',
|
||||
'tests/phpt',
|
||||
'tests/Fixtures',
|
||||
])
|
||||
)
|
||||
;
|
||||
4
vendor/sentry/sentry/AUTHORS
vendored
Normal file
4
vendor/sentry/sentry/AUTHORS
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
The Sentry PHP SDK was originally written by Michael van Tellingen
|
||||
and is maintained by the Sentry Team.
|
||||
|
||||
http://github.com/getsentry/sentry-php/contributors
|
||||
402
vendor/sentry/sentry/CHANGELOG.md
vendored
Normal file
402
vendor/sentry/sentry/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,402 @@
|
||||
# CHANGELOG
|
||||
|
||||
## Unreleased
|
||||
|
||||
### 2.4.2 (2020-07-24)
|
||||
|
||||
- Fix typehint errors while instantiating the Httplug cURL client by forcing the usage of PSR-17 complaint factories (#1052)
|
||||
|
||||
### 2.4.1 (2020-07-03)
|
||||
|
||||
- Fix HTTP client connection timeouts not being applied if an HTTP proxy is specified (#1033)
|
||||
- [BC CHANGE] Revert "Add support for iterables in the serializer (#991)" (#1030)
|
||||
|
||||
### 2.4.0 (2020-05-21)
|
||||
|
||||
- Enforce a timeout for connecting to the server and for the requests instead of waiting indefinitely (#979)
|
||||
- Add `RequestFetcherInterface` to allow customizing the request data attached to the logged event (#984)
|
||||
- Log internal debug and error messages to a PSR-3 compatible logger (#989)
|
||||
- Make `AbstractSerializer` to accept `Traversable` values using `is_iterable` instead of `is_array` (#991)
|
||||
- Refactor the `ModulesIntegration` integration to improve its code and its tests (#990)
|
||||
- Extract the parsing and validation logic of the DSN into its own value object (#995)
|
||||
- Support passing either a Httplug or PSR-17 stream factory to the `GzipEncoderPlugin` class (#1012)
|
||||
- Add the `FrameContextifierIntegration` integration (#1011)
|
||||
- Add missing validation for the `context_lines` option and fix its behavior when passing `null` to make it working as described in the documentation (#1003)
|
||||
- Trim the file path from the anonymous class name in the stacktrace according to the `prefixes` option (#1016)
|
||||
|
||||
## 2.3.2 (2020-03-06)
|
||||
|
||||
- Hard-limit concurrent requests in `HttpTransport` and removed pre-init of promises (fixes "too many open files" errors) (#981)
|
||||
- Fix `http_proxy` option not being applied (#978)
|
||||
- Fix the error handler rethrowing the captured exception when previous handler didn't (#974)
|
||||
|
||||
## 2.3.1 (2020-01-23)
|
||||
|
||||
- Allow unsetting the stack trace on an `Event` by calling `Event::setStacktrace(null)` (#961)
|
||||
- Fix sending of both `event.stacktrace` and `event.exceptions` when `attach_stacktrace = true` (#960)
|
||||
- Fix regression that set all frames of a stacktrace as not in app by default (#958)
|
||||
- Fix issues with memory addresses in anonymous class stack traces (#956)
|
||||
- Fix exception thrown regardless of whether the HTTP client was instantiated when using the `http_proxy option` (#951)
|
||||
|
||||
## 2.3.0 (2020-01-08)
|
||||
|
||||
- Add `in_app_include` option to whitelist paths that should be marked as part of the app (#909)
|
||||
- Fix `Client::captureEvent` not considering the `attach_stacktrace` option (#940)
|
||||
- Replace `ramsey/uuid` dependency with `uuid_create` from the PECL [`uuid`](https://pecl.php.net/package/uuid) extension or [`symfony/polyfill-uuid`](https://github.com/symfony/polyfill-uuid) (#937)
|
||||
- Deprecate `Scope::setUser` behaviour of replacing user data. (#929)
|
||||
- Add the `$merge` parameter on `Scope::setUser` to allow merging user context. (#929)
|
||||
- Make the `integrations` option accept a `callable` that will receive the list of default integrations and returns a customized list (#919)
|
||||
- Add the `IgnoreErrorsIntegration` integration to deprecate and replace the `exclude_exceptions` option (#928)
|
||||
- Allow setting custom contexts on the scope and on the event (#839)
|
||||
- Replace dependency to `zendframework/zend-diactoros` with `guzzlehttp/psr7` (#945)
|
||||
|
||||
## 2.2.6 (2019-12-18)
|
||||
|
||||
- Fix remaining PHP 7.4 deprecations (#930)
|
||||
- Fix error thrown during JSON encoding if a string contains invalid UTF-8 characters (#934)
|
||||
|
||||
## 2.2.5 (2019-11-27)
|
||||
|
||||
- Add compatibility with Symfony 5 (#925)
|
||||
- Ensure compatibility with PHP 7.4 (#894, #926)
|
||||
|
||||
## 2.2.4 (2019-11-04)
|
||||
|
||||
- Suggest installing Monolog to send log messages directly to Sentry (#908)
|
||||
- Make the `$errcontext` argument of the `ErrorHandler::handleError()` method `nullable` (#917)
|
||||
|
||||
## 2.2.3 (2019-10-31)
|
||||
|
||||
- Fix deprecation raised when serializing callable in certain circumstances (#821)
|
||||
- Fix incorrect `critical` breadcrumb level by replacing it with the `fatal` level (#901)
|
||||
- Fix regression on default sending behavior of the `HttpTransport` transport (#905)
|
||||
- Fix stacktrace frame inApp detection: all paths outside the project_root are now considered as not in app (#911)
|
||||
|
||||
## 2.2.2 (2019-10-10)
|
||||
|
||||
- Fix handling of fifth argument in the error handler (#892)
|
||||
- Catch exception from vendors in `Sentry\Transport\HttpTransport` (#899)
|
||||
|
||||
## 2.2.1 (2019-09-23)
|
||||
|
||||
- Disable default deprecation warning `Sentry\Transport\HttpTransport` (#884)
|
||||
|
||||
## 2.2.0 (2019-09-23)
|
||||
|
||||
- Change type hint for both parameter and return value of `HubInterface::getCurrentHub` and `HubInterface::setCurrentHub()` methods (#849)
|
||||
- Add the `setTags`, `setExtras` and `clearBreadcrumbs` methods to the `Scope` class (#852)
|
||||
- Silently cast numeric values to strings when trying to set the tags instead of throwing (#858)
|
||||
- Support force sending events on-demand and fix sending of events in long-running processes (#813)
|
||||
- Update PHPStan and introduce Psalm (#846)
|
||||
- Add an integration to set the transaction attribute of the event (#865)
|
||||
- Deprecate `Hub::getCurrent` and `Hub::setCurrent` methods to set the current hub instance (#847)
|
||||
|
||||
## 2.1.3 (2019-09-06)
|
||||
|
||||
- Fix GZIP-compressed requests failing when `exit($code)` was used to terminate the application (#877)
|
||||
|
||||
## 2.1.2 (2019-08-22)
|
||||
|
||||
- Fix `TypeError` in `Sentry\Monolog\Handler` when the extra data array has numeric keys (#833).
|
||||
- Fix sending of GZIP-compressed requests when the `enable_compression` option is `true` (#857)
|
||||
- Fix error thrown when trying to set the `transaction` attribute of the event in a CLI environment (#862)
|
||||
- Fix integrations that were not skipped if the client bound to the current hub was not using them (#861)
|
||||
- Fix undefined index generated by missing function in class (#823)
|
||||
|
||||
## 2.1.1 (2019-06-13)
|
||||
|
||||
- Fix the behavior of the `excluded_exceptions` option: now it's used to skip capture of exceptions, not to purge the
|
||||
`exception` data of the event, which resulted in broken or empty chains of exceptions in reported events (#822)
|
||||
- Fix handling of uploaded files in the `RequestIntegration`, to respect the PSR-7 spec fully (#827)
|
||||
- Fix use of `REMOTE_ADDR` server variable rather than HTTP header
|
||||
- Fix exception, open_basedir restriction in effect (#824)
|
||||
|
||||
## 2.1.0 (2019-05-22)
|
||||
|
||||
- Mark Sentry internal frames when using `attach_stacktrace` as `in_app` `false` (#786)
|
||||
- Increase default severity of `E_RECOVERABLE_ERROR` to `Severity::ERROR`, instead of warning (#792)
|
||||
- Make it possible to register fatal error listeners separately from the error listeners
|
||||
and change the type of the reported exception to `\Sentry\Exception\FatalErrorException` (#788)
|
||||
- Add a static factory method to create a breadcrumb from an array of data (#798)
|
||||
- Add support for `SENTRY_ENVRIONMENT` and `SENTRY_RELEASE` environment variables (#810)
|
||||
- Add the `class_serializers` option to make it possible to customize how objects are serialized in the event payload (#809)
|
||||
- Fix the default value of the `$exceptions` property of the Event class (#806)
|
||||
- Add a Monolog handler (#808)
|
||||
- Allow capturing the body of an HTTP request (#807)
|
||||
- Capture exceptions during serialization, to avoid hard failures (#818)
|
||||
|
||||
## 2.0.1 (2019-03-01)
|
||||
|
||||
- Do no longer report silenced errors by default (#785)
|
||||
- New option `capture_silenced_error` to enable reporting of silenced errors, disabled by default (#785)
|
||||
|
||||
## 2.0.0 (2019-02-25)
|
||||
|
||||
**Version 2.0.0 is a complete rewrite of the existing SDK. Code Changes are needed. Please see [UPGRADE 2.0](https://github.com/getsentry/sentry-php/blob/master/UPGRADE-2.0.md) for more details.**
|
||||
|
||||
- Updated .gitattributes to reduce package footprint (#770)
|
||||
- Use multibyte functions to handle unicode paths (#774)
|
||||
- Remove `Hub::getScope()` to deny direct access to `Scope` instances (#776)
|
||||
- Reintroduce `http_proxy` option (#775)
|
||||
- Added support for HTTPlug 2 / PSR-18 (#777)
|
||||
|
||||
## 2.0.0-beta2 (2019-02-11)
|
||||
- Rename `SentryAuth` class to `SentryAuthentication` (#742)
|
||||
- `Client` class is now final
|
||||
- Fix issue with `ClientBuilder`: factories are not instantiated if transport is set manually (#747)
|
||||
- Rename `excluded_paths` to `in_app_exclude` option to follow Unified API spec (#755)
|
||||
- Add `max_value_length` option to trim long values during serialization (#754)
|
||||
- Lower the default `send_attempts` to 3 (#760)
|
||||
- Fix method argument name handling when Xdebug is enabled (#763)
|
||||
- Add CI build under Windows with AppVeyor (#758) and fix some bugs
|
||||
- Change the `ErrorHandler` and default integrations behavior: the handler is now a singleton,
|
||||
and it's possible to attach a number of callables as listeners for errors and exceptions (#762)
|
||||
- The `context_lines` options changed the default to `5` and is properly applied (#743)
|
||||
- Add support for "formatted messages" in `captureEvent` as payload (#752)
|
||||
- Fix issue when capturing exceptions to remove warning when converting array args (#761)
|
||||
|
||||
## 2.0.0-beta1 (2018-12-19)
|
||||
|
||||
- Require PHP >= 7.1
|
||||
- Refactor the whole codebase to support the Unified API SDK specs
|
||||
- See the UPGRADE.md document for more information.
|
||||
|
||||
## 1.10.0 (2018-11-09)
|
||||
|
||||
- Added passing data from context in monolog breadcrumb handler (#683)
|
||||
- Do not return error id if we know we did not send the error (#667)
|
||||
- Do not force IPv4 protocol by default (#654)
|
||||
|
||||
## 1.9.2 (2018-08-18)
|
||||
|
||||
- Remove secret_key from required keys for CLI test command. (#645)
|
||||
- Proper case in Raven_Util class name usage. (#642)
|
||||
- Support longer credit card numbers. (#635)
|
||||
- Use configured message limit when creating serializers. (#634)
|
||||
- Do not truncate strings if message limit is set to zero. (#630)
|
||||
- Add option to ignore SERVER_PORT getting added to url. (#629)
|
||||
- Cleanup the PHP version reported. (#604)
|
||||
|
||||
## 1.9.1 (2018-06-19)
|
||||
|
||||
- Allow the use of a public DSN (private part of the DSN was deprecated in Sentry 9) (#615)
|
||||
- Send transaction as transaction not as culprit (#601)
|
||||
|
||||
## 1.9.0 (2018-05-03)
|
||||
|
||||
- Fixed undefined variable (#588)
|
||||
- Fix for exceptions throwing exceptions when setting event id (#587)
|
||||
- Fix monolog handler not accepting Throwable (#586)
|
||||
- Add `excluded_exceptions` option to exclude exceptions and their extending exceptions (#583)
|
||||
- Fix `HTTP_X_FORWARDED_PROTO` header detection (#578)
|
||||
- Fix sending events async in PHP 5 (#576)
|
||||
- Avoid double reporting due to `ErrorException`s (#574)
|
||||
- Make it possible to overwrite serializer message limit of 1024 (#559)
|
||||
- Allow request data to be nested up to 5 levels deep (#554)
|
||||
- Update serializer to handle UTF-8 characters correctly (#553)
|
||||
|
||||
## 1.8.4 (2018-03-20)
|
||||
|
||||
- Revert ignoring fatal errors on PHP 7+ (#571)
|
||||
- Add PHP runtime information (#564)
|
||||
- Cleanup the `site` value if it's empty (#555)
|
||||
- Add `application/json` input handling (#546)
|
||||
|
||||
## 1.8.3 (2018-02-07)
|
||||
|
||||
- Serialize breadcrumbs to prevent issues with binary data (#538)
|
||||
- Fix notice array_key_exists() expects parameter 2 to be array, null given (#527)
|
||||
|
||||
## 1.8.2 (2017-12-21)
|
||||
|
||||
- Improve handling DSN with "null" like values (#522)
|
||||
- Prevent warning in Raven_Stacktrace (#493)
|
||||
|
||||
## 1.8.1 (2017-11-09)
|
||||
|
||||
- Add setters for the serializers on the `Raven_Client` (#515)
|
||||
- Avoid to capture `E_ERROR` in PHP 7+, because it's also a `Throwable` that gets captured and duplicates the error (#514)
|
||||
|
||||
## 1.8.0 (2017-10-29)
|
||||
|
||||
- Use namespaced classes in test for PHPUnit (#506)
|
||||
- Prevent segmentation fault on PHP `<5.6` (#504)
|
||||
- Remove `ini_set` call for unneeded functionality (#501)
|
||||
- Exclude single `.php` files from the app path (#500)
|
||||
- Start testing PHP 7.2 (#489)
|
||||
- Exclude anonymous frames from app path (#482)
|
||||
|
||||
## 1.7.1 (2017-08-02)
|
||||
|
||||
- Fix of filtering sensitive data when there is an exception with multiple 'values' (#483)
|
||||
|
||||
## 1.7.0 (2017-06-07)
|
||||
|
||||
- Corrected some issues with argument serialization in stacktraces (#399).
|
||||
- The default exception handler will now re-raise exceptions when `call_existing` is true and no exception handler is registered (#421).
|
||||
- Collect `User.ip_address` automatically (#419).
|
||||
- Added a processor to remove web cookies. It will be enabled by default in `2.0` (#405).
|
||||
- Added a processor to remove HTTP body data for POST, PUT, PATCH and DELETE requests. It will be enabled by default in `2.0` (#405).
|
||||
- Added a processor to sanitize HTTP headers (e.g. the Authorization header) (#428).
|
||||
- Added a processor to remove `pre_context`, `context_line` and `post_context` informations from reported exceptions (#429).
|
||||
|
||||
## 1.6.2 (2017-02-03)
|
||||
|
||||
- Fixed behavior where fatal errors weren't correctly being reported in most situations.
|
||||
|
||||
## 1.6.1 (2016-12-14)
|
||||
|
||||
- Correct handling of null in `user_context`.
|
||||
|
||||
## 1.6.0 (2016-12-09)
|
||||
|
||||
- Improved serialization of certain types to be more restrictive.
|
||||
- `error_types` can now be configured via `RavenClient`.
|
||||
- Class serialization has been expanded to include attributes.
|
||||
- The session extension is no longer required.
|
||||
- Monolog is no longer a required dependency.
|
||||
- `user_context` now merges by default.
|
||||
|
||||
## 1.5.0 (2016-09-29)
|
||||
|
||||
- Added named transaction support.
|
||||
|
||||
## 1.4.0 (2016-09-20)
|
||||
|
||||
This version primarily overhauls the exception/stacktrace generation to fix
|
||||
a few bugs and improve the quality of data (#359).
|
||||
|
||||
- Added `excluded_app_paths` config.
|
||||
- Removed `shift_vars` config.
|
||||
- Correct fatal error handling to only operate on expected types. This also fixes some behavior with the error suppression operator.
|
||||
- Expose anonymous and similar frames in the stacktrace.
|
||||
- Default `prefixes` to PHP's include paths.
|
||||
- Remove `module` usage.
|
||||
- Better handle empty argument context.
|
||||
- Correct alignment of filename (current frame) and function (caller frame)
|
||||
|
||||
## 1.3.0 (2016-12-19)
|
||||
|
||||
- Fixed an issue causing the error suppression operator to not be respected (#335)
|
||||
- Fixed some serialization behavior (#352)
|
||||
- Fixed an issue with app paths and trailing slashes (#350)
|
||||
- Handle non-latin encoding with source code context line (#345)
|
||||
|
||||
## 1.2.0 (2016-12-08)
|
||||
|
||||
- Handle non-latin encoding in source code and exception values (#342)
|
||||
- Ensure pending events are sent on shutdown by default (#338)
|
||||
- Add `captureLastError` helper (#334)
|
||||
- Dont report duplicate errors with fatal error handler (#334)
|
||||
- Enforce maximum length for string serialization (#329)
|
||||
|
||||
## 1.1.0 (2016-07-30)
|
||||
|
||||
- Uncoercable values should no longer prevent exceptions from sending
|
||||
to the Sentry server.
|
||||
- `install()` can no longer be called multiple times.
|
||||
|
||||
## 1.0.0 (2016-07-28)
|
||||
|
||||
- Removed deprecated error codes configuration from ErrorHandler.
|
||||
- Removed env data from HTTP interface.
|
||||
- Removed `message` attribute from exceptions.
|
||||
- appPath and prefixes are now resolved fully.
|
||||
- Fixed various getter methods requiring invalid args.
|
||||
- Fixed data mutation with `send_callback`.
|
||||
|
||||
## 0.22.0 (2016-06-23)
|
||||
|
||||
- Improve handling of encodings.
|
||||
- Improve resiliency of variable serialization.
|
||||
- Add 'formatted' attribute to Message interface.
|
||||
|
||||
## 0.21.0 (2016-06-10)
|
||||
|
||||
- Added `transport` option.
|
||||
- Added `install()` shortcut.
|
||||
|
||||
## 0.20.0 (2016-06-02)
|
||||
|
||||
- Handle missing function names on frames.
|
||||
- Remove suppression operator usage in breadcrumbs buffer.
|
||||
- Force serialization of context values.
|
||||
|
||||
## 0.19.0 (2016-05-27)
|
||||
|
||||
- Add `error_reporting` breadcrumb handler.
|
||||
|
||||
## 0.18.0 (2016-05-17)
|
||||
|
||||
- Remove session from serialized data.
|
||||
- `send_callback` return value must now be false to prevent capture.
|
||||
- Add various getter/setter methods for configuration.
|
||||
|
||||
## 0.17.0 (2016-05-11)
|
||||
|
||||
- Don't attempt to serialize fixed SDK inputs.
|
||||
- Improvements to breadcrumbs support in Monolog.
|
||||
|
||||
## 0.16.0 (2016-05-03)
|
||||
|
||||
- Initial breadcrumbs support with Monolog handler.
|
||||
|
||||
## 0.15.0 (2016-04-29)
|
||||
|
||||
- Fixed some cases where serialization wouldn't happen.
|
||||
- Added sdk attribute.
|
||||
|
||||
## 0.14.0 (2016-04-27)
|
||||
|
||||
- Added `prefixes` option for stripping absolute paths.
|
||||
- Removed `abs_path` from stacktraces.
|
||||
- Added `app_path` to specify application root for resolving `in_app` on frames.
|
||||
- Moved Laravel support to `sentry-laravel` project.
|
||||
- Fixed duplicate stack computation.
|
||||
- Added `dsn` option to ease configuration.
|
||||
- Fixed an issue with the curl async transport.
|
||||
- Improved serialization of values.
|
||||
|
||||
## 0.13.0 (2015-09-09)
|
||||
|
||||
- Updated API to use new style interfaces.
|
||||
- Remove session cookie in default processor.
|
||||
- Expand docs for Laravel, Symfony2, and Monolog.
|
||||
- Default error types can now be set as part of ErrorHandler configuration.
|
||||
|
||||
## 0.12.1 (2015-07-26)
|
||||
|
||||
- Dont send empty values for various context.
|
||||
|
||||
## 0.12.0 (2015-05-19)
|
||||
|
||||
- Bumped protocol version to 6.
|
||||
- Fixed an issue with the async curl handler (GH-216).
|
||||
- Removed UDP transport.
|
||||
|
||||
## 0.11.0 (2015-03-25)
|
||||
|
||||
- New configuration parameter: `release`
|
||||
- New configuration parameter: `message_limit`
|
||||
- New configuration parameter: `curl_ssl_version`
|
||||
- New configuration parameter: `curl_ipv4`
|
||||
- New configuration parameter: `verify_ssl`
|
||||
- Updated remote endpoint to use modern project-based path.
|
||||
- Expanded default sanitizer support to include `auth_pw` attribute.
|
||||
|
||||
## 0.10.0 (2014-09-03)
|
||||
|
||||
- Added a default certificate bundle which includes common root CA's as well as getsentry.com's CA.
|
||||
|
||||
## 0.9.1 (2014-08-26)
|
||||
|
||||
- Change default curl connection to `sync`
|
||||
- Improve CLI reporting
|
||||
|
||||
## 0.9.0 (2014-06-04)
|
||||
|
||||
- Protocol version 5
|
||||
- Default to asynchronous HTTP handler using curl_multi.
|
||||
|
||||
|
||||
(For previous versions see the commit history)
|
||||
12
vendor/sentry/sentry/LICENSE
vendored
Normal file
12
vendor/sentry/sentry/LICENSE
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
Copyright (c) 2012 Sentry Team and individual contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the Raven, Sentry, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
122
vendor/sentry/sentry/README.md
vendored
Normal file
122
vendor/sentry/sentry/README.md
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
<p align="center">
|
||||
<a href="https://sentry.io" target="_blank" align="center">
|
||||
<img src="https://sentry-brand.storage.googleapis.com/sentry-logo-black.png" width="280">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
# Sentry SDK for PHP
|
||||
|
||||
[](https://packagist.org/packages/sentry/sentry)
|
||||
[](https://packagist.org/packages/sentry/sentry)
|
||||
[](https://packagist.org/packages/sentry/sentry)
|
||||
[](https://packagist.org/packages/sentry/sentry)
|
||||
[](https://discord.gg/cWnMQeA)
|
||||
|
||||
| Version | Build Status | Code Coverage |
|
||||
|:---------:|:-------------:|:-----:|
|
||||
| `master`| [![Build Status][Travis Master Build Status Image]][Travis Build Status] [![Build Status][AppVeyor Master Build Status Image]][AppVeyor Build Status] | [![Coverage Status][Master Code Coverage Image]][Master Code Coverage] |
|
||||
| `develop` | [![Build Status][Travis Develop Build Status Image]][Travis Build Status] [![Build Status][AppVeyor Develop Build Status Image]][AppVeyor Build Status] | [![Coverage Status][Develop Code Coverage Image]][Develop Code Coverage] |
|
||||
|
||||
The Sentry PHP error reporter tracks errors and exceptions that happen during the
|
||||
execution of your application and provides instant notification with detailed
|
||||
information needed to prioritize, identify, reproduce and fix each issue.
|
||||
|
||||
## Install
|
||||
|
||||
To install the SDK you will need to be using [Composer]([https://getcomposer.org/)
|
||||
in your project. To install it please see the [docs](https://getcomposer.org/download/).
|
||||
|
||||
This is our "core" SDK, meaning that all the important code regarding error handling lives here.
|
||||
If you are happy with using the HTTP client we recommend install the SDK like: [`sentry/sdk`](https://github.com/getsentry/sentry-php-sdk)
|
||||
|
||||
```bash
|
||||
php composer.phar require sentry/sdk
|
||||
```
|
||||
|
||||
This package (`sentry/sentry`) is not tied to any specific library that sends HTTP messages. Instead,
|
||||
it uses [Httplug](https://github.com/php-http/httplug) to let users choose whichever
|
||||
PSR-7 implementation and HTTP client they want to use.
|
||||
|
||||
If you just want to get started quickly you should run the following command:
|
||||
|
||||
```bash
|
||||
php composer.phar require sentry/sentry php-http/curl-client
|
||||
```
|
||||
|
||||
This is basically what our metapackage (`sentry/sdk`) provides.
|
||||
|
||||
This will install the library itself along with an HTTP client adapter that uses
|
||||
cURL as transport method (provided by Httplug). You do not have to use those
|
||||
packages if you do not want to. The SDK does not care about which transport method
|
||||
you want to use because it's an implementation detail of your application. You may
|
||||
use any package that provides [`php-http/async-client-implementation`](https://packagist.org/providers/php-http/async-client-implementation)
|
||||
and [`http-message-implementation`](https://packagist.org/providers/psr/http-message-implementation).
|
||||
|
||||
## Usage
|
||||
|
||||
```php
|
||||
\Sentry\init(['dsn' => '___PUBLIC_DSN___' ]);
|
||||
|
||||
try {
|
||||
thisFunctionThrows(); // -> throw new \Exception('foo bar');
|
||||
} catch (\Exception $exception) {
|
||||
\Sentry\captureException($exception);
|
||||
}
|
||||
```
|
||||
|
||||
### Official integrations
|
||||
|
||||
The following integrations are fully supported and maintained by the Sentry team.
|
||||
|
||||
- [Symfony](https://github.com/getsentry/sentry-symfony)
|
||||
- [Laravel](https://github.com/getsentry/sentry-laravel)
|
||||
|
||||
### 3rd party integrations
|
||||
|
||||
The following integrations are available and maintained by members of the Sentry community.
|
||||
|
||||
- [Drupal](https://www.drupal.org/project/raven)
|
||||
- [Flow Framework](https://github.com/networkteam/Networkteam.SentryClient)
|
||||
- [OXID eShop](https://github.com/OXIDprojects/sentry)
|
||||
- [WordPress](https://wordpress.org/plugins/wp-sentry-integration/)
|
||||
- [ZendFramework](https://github.com/facile-it/sentry-module)
|
||||
- [SilverStripe](https://github.com/phptek/silverstripe-sentry)
|
||||
- [TYPO3](https://github.com/networkteam/sentry_client)
|
||||
- ... feel free to be famous, create a port to your favourite platform!
|
||||
|
||||
### 3rd party integrations using old SDK 1.x
|
||||
|
||||
- [Neos CMS](https://github.com/networkteam/Netwokteam.Neos.SentryClient)
|
||||
- [OpenCart](https://github.com/BurdaPraha/oc_sentry)
|
||||
- [TYPO3](https://github.com/networkteam/sentry_client/tree/2.1.1)
|
||||
|
||||
## Community
|
||||
|
||||
- [Documentation](https://docs.sentry.io/error-reporting/quickstart/?platform=php)
|
||||
- [Bug Tracker](http://github.com/getsentry/sentry-php/issues)
|
||||
- [Code](http://github.com/getsentry/sentry-php)
|
||||
|
||||
## Contributing
|
||||
|
||||
Dependencies are managed through `composer`:
|
||||
|
||||
```
|
||||
$ composer install
|
||||
```
|
||||
|
||||
Tests can then be run via phpunit:
|
||||
|
||||
```
|
||||
$ vendor/bin/phpunit
|
||||
```
|
||||
|
||||
[Travis Build Status]: http://travis-ci.org/getsentry/sentry-php
|
||||
[Travis Master Build Status Image]: https://img.shields.io/travis/getsentry/sentry-php/master?logo=travis
|
||||
[Travis Develop Build Status Image]: https://img.shields.io/travis/getsentry/sentry-php/develop?logo=travis
|
||||
[AppVeyor Build Status]: https://ci.appveyor.com/project/sentry/sentry-php
|
||||
[AppVeyor Master Build Status Image]: https://img.shields.io/appveyor/ci/sentry/sentry-php/master?logo=appveyor
|
||||
[AppVeyor Develop Build Status Image]: https://img.shields.io/appveyor/ci/sentry/sentry-php/develop?logo=appveyor
|
||||
[Master Code Coverage]: https://codecov.io/gh/getsentry/sentry-php/branch/master
|
||||
[Master Code Coverage Image]: https://img.shields.io/codecov/c/github/getsentry/sentry-php/master?logo=codecov
|
||||
[Develop Code Coverage]: https://codecov.io/gh/getsentry/sentry-php/branch/develop
|
||||
[Develop Code Coverage Image]: https://img.shields.io/codecov/c/github/getsentry/sentry-php/develop?logo=codecov
|
||||
700
vendor/sentry/sentry/UPGRADE-2.0.md
vendored
Normal file
700
vendor/sentry/sentry/UPGRADE-2.0.md
vendored
Normal file
@@ -0,0 +1,700 @@
|
||||
# Upgrade from 1.10 to 2.0
|
||||
|
||||
Version `2.x` is a complete rewrite of the existing code base. The public API has been trimmed down to a minimum.
|
||||
The preferred way of using the SDK is through our "Static API" / global functions.
|
||||
|
||||
Here is a simple example to get started:
|
||||
|
||||
```php
|
||||
\Sentry\init(['dsn' => '___PUBLIC_DSN___' ]);
|
||||
|
||||
\Sentry\configureScope(function (\Sentry\State\Scope $scope): void {
|
||||
$scope->setTag('page_locale', 'de-at');
|
||||
$scope->setUser(['email' => 'john.doe@example.com']);
|
||||
$scope->setLevel(\Sentry\Severity::warning());
|
||||
$scope->setExtra('character_name', 'Mighty Fighter');
|
||||
});
|
||||
|
||||
// The following capture call will contain the data from the previous configured Scope
|
||||
try {
|
||||
thisFunctionThrows(); // -> throw new \Exception('foo bar');
|
||||
} catch (\Exception $exception) {
|
||||
\Sentry\captureException($exception);
|
||||
}
|
||||
|
||||
\Sentry\addBreadcrumb(new Breadcrumb(Breadcrumb::LEVEL_ERROR, Breadcrumb::TYPE_ERROR, 'error_reporting', 'Message'));
|
||||
```
|
||||
|
||||
The call to `\Sentry\init()` sets up global exception/error handlers and any uncaught error will be sent to Sentry.
|
||||
Version `>= 2.0` conforms to the [Unified SDK API](https://docs.sentry.io/development/sdk-dev/unified-api/).
|
||||
It has a fundamentally different concept, it's no longer recommended to just use a `Client` unless you really know what you are doing.
|
||||
|
||||
Please visit [our docs](https://docs.sentry.io/error-reporting/quickstart/?platform=php) to get a full overview.
|
||||
|
||||
### Client options
|
||||
|
||||
- The `exclude` option has been removed.
|
||||
|
||||
- The `excluded_app_path` option has been renamed to `in_app_exclude`
|
||||
|
||||
- The `send_callback` option has been renamed to `before_send`.
|
||||
|
||||
- The `name` option has been renamed to `server_name`.
|
||||
|
||||
- The `secret_key` option has been removed.
|
||||
|
||||
- The `public_key` option has been removed.
|
||||
|
||||
- The `message_limit` option has been removed.
|
||||
|
||||
- The `project` option has been removed.
|
||||
|
||||
- The `severity_map` option has been removed.
|
||||
|
||||
- The `ignore_server_port` option has been removed.
|
||||
|
||||
- The `trust_x_forwarded_proto` option has been removed.
|
||||
|
||||
- The `mb_detect_order` option has been removed.
|
||||
|
||||
- The `trace` option has been removed.
|
||||
|
||||
- The `tags` option has been removed in favour of setting them in the scope.
|
||||
|
||||
- The `site` option has been removed.
|
||||
|
||||
- The `extra_data` option has been removed in favour of setting additional data
|
||||
in the scope.
|
||||
|
||||
- The `curl_method` option has been removed.
|
||||
|
||||
- The `curl_path` option has been removed.
|
||||
|
||||
- The `curl_ipv4` option has been removed.
|
||||
|
||||
- The `curl_ssl_version` option has been removed.
|
||||
|
||||
- The `verify_ssl` option has been removed.
|
||||
|
||||
- The `ca_cert` option has been removed.
|
||||
|
||||
- The `proxy` option has been removed in favour of leaving to the user the burden
|
||||
of configuring the HTTP client options using a custom client.
|
||||
|
||||
- The `processors` option has been removed.
|
||||
|
||||
- The `processors_options` option has been removed.
|
||||
|
||||
- The `transport` option has been removed in favour of setting it using the
|
||||
client builder.
|
||||
|
||||
- The `install_default_breadcrumb_handlers` option has been removed.
|
||||
|
||||
- The `serialize_all_object` option has been removed.
|
||||
|
||||
- The `context_lines` option has been added to configure the number of lines of
|
||||
code context to capture.
|
||||
|
||||
- The `max_value_length` option has been added to set an upper bound to the length
|
||||
of serialized items.
|
||||
|
||||
- The `server` option has been renamed to `dsn`.
|
||||
|
||||
### Misc
|
||||
|
||||
- All the classes have been renamed and moved around to follow the PSR-4
|
||||
convention and `final` have been added where appropriate.
|
||||
|
||||
- The `Raven_Autoloader` class has been removed. To install and use the
|
||||
library you are required to use [Composer](https://getcomposer.org/).
|
||||
|
||||
- The `Raven_Util` class has been removed.
|
||||
|
||||
- The `Raven_Compat` class has been removed.
|
||||
|
||||
- The `Raven_Util` class has been removed.
|
||||
|
||||
- The `Raven_CurlHandler` class has been removed.
|
||||
|
||||
- The `Raven_TransactionStack` class has been removed.
|
||||
|
||||
- The `Raven_Exception` class has been removed.
|
||||
|
||||
### Client
|
||||
|
||||
- The constructor of the `Client` (before `Raven_Client`) class has changed its signature and
|
||||
now requires to be passed a configuration object, an instance of a transport
|
||||
and an event factory.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
public function __construct($options_or_dsn = null, $options = array())
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
public function __construct(Options $options, TransportInterface $transport, EventFactoryInterface $eventFactory)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
The suggested way to create your own instance of the client is to use the provided builder (`ClientBuilder`) that will take care of instantiating a few dependencies like the PSR-7 factories and the HTTP client.
|
||||
|
||||
- The method `Raven_Client::close_all_children_link` has been removed and there
|
||||
|
||||
- The methods `Raven_Client::getRelease` and `Raven_Client::setRelease` have
|
||||
been removed. You should use `Options::getRelease` and `Options::setRelease`
|
||||
instead.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client->getRelease();
|
||||
$client->setRelease(...);
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\State\Hub;
|
||||
|
||||
$options = Hub::getCurrent()->getClient()->getOptions();
|
||||
|
||||
$options->getRelease();
|
||||
$options->setRelease(...);
|
||||
```
|
||||
|
||||
- The methods `Raven_Client::getEnvironment` and `Raven_Client::setEnvironment`
|
||||
have been removed. You should use `Options::getEnvironment` and `Options::setEnvironment`
|
||||
instead.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client->getEnvironment();
|
||||
$client->setEnvironment(...);
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\State\Hub;
|
||||
|
||||
$options = Hub::getCurrent()->getClient()->getOptions();
|
||||
|
||||
$options->getEnvironment();
|
||||
$options->setEnvironment(...);
|
||||
```
|
||||
|
||||
- The method `Raven_Client::getInputStream` has been removed.
|
||||
|
||||
- The methods `Raven_Client::getDefaultPrefixes` and `Raven_Client::setPrefixes`
|
||||
have been removed. You should use `Options::getPrefixes` and
|
||||
`Options::setPrefixes` instead.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client->getPrefixes();
|
||||
$client->setPrefixes(...);
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\State\Hub;
|
||||
|
||||
$options = Hub::getCurrent()->getClient()->getOptions();
|
||||
|
||||
$options->getPrefixes();
|
||||
$options->setPrefixes(...);
|
||||
```
|
||||
|
||||
- The methods `Raven_Client::getAppPath` and `Raven_Client::setAppPath` have been
|
||||
removed. You should use `Options::getProjectRoot` and `Options::setProjectRoot`
|
||||
instead.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client->getAppPath();
|
||||
$client->setAppPath(...);
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\State\Hub;
|
||||
|
||||
$options = Hub::getCurrent()->getClient()->getOptions();
|
||||
|
||||
$options->getProjectRoot();
|
||||
$options->setProjectRoot(...);
|
||||
```
|
||||
|
||||
- The methods `Raven_Client::getExcludedAppPaths` and `Raven_Client::setExcludedAppPaths`
|
||||
have been removed. You should use `Options::getInAppExcludedPaths`
|
||||
and `Options::setInAppExcludedPaths` instead.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client->getExcludedAppPaths();
|
||||
$client->setExcludedAppPaths(...);
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\State\Hub;
|
||||
|
||||
$options = Hub::getCurrent()->getClient()->getOptions();
|
||||
|
||||
$options->getExcludedAppPaths();
|
||||
$options->setExcludedAppPaths(...);
|
||||
```
|
||||
|
||||
- The methods `Raven_Client::getSendCallback` and `Raven_Client::setSendCallback`
|
||||
have been removed. You should use `Options::getBeforeSendCallback` and
|
||||
`Options::setBeforeSendCallback` instead.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client->getSendCallback();
|
||||
$client->setSendCallback(...);
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\State\Hub;
|
||||
|
||||
$options = Hub::getCurrent()->getClient()->getOptions();
|
||||
|
||||
$options->getBeforeSendCallback();
|
||||
$options->setBeforeSendCallback(...);
|
||||
|
||||
- The method `Raven_Client::getServerEndpoint` has been removed. You should use
|
||||
`Options::getDsn` instead.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client->getServerEndpoint();
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\State\Hub;
|
||||
|
||||
$options = Hub::getCurrent()->getClient()->getOptions();
|
||||
|
||||
$options->getDsn();
|
||||
```
|
||||
|
||||
- The methods `Raven_Client::getTransport` and `Raven_Client::setTransport` have
|
||||
been removed. The transport is now a required dependency of the client and must
|
||||
be passed as required constructor argument.
|
||||
|
||||
- The method `Raven_Client::getUserAgent` has been removed.
|
||||
|
||||
- The method `Raven_Client::getErrorTypes` has been removed. You should use
|
||||
`Configuration::getErrorTypes` instead.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client->getErrorTypes();
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
$client->getConfig()->getErrorTypes();
|
||||
```
|
||||
|
||||
- The `Raven_Client::getDefaultProcessors` method has been removed.
|
||||
|
||||
- The `Raven_Client::setProcessorsFromOptions` method has been removed.
|
||||
|
||||
- The `Raven_Client::getLastEventID` method has been removed. The ID of the
|
||||
last event that was captured is now returned by each of the `Client::capture*`
|
||||
methods. You can also use `Hub::getCurrent()->getLastEventId()`.
|
||||
|
||||
- The `Raven_Client::parseDSN` method has been removed.
|
||||
|
||||
- The `Raven_Client::getLastError` method has been removed.
|
||||
|
||||
- The `Raven_Client::getIdent` method has been removed.
|
||||
|
||||
- The `Raven_Client::registerShutdownFunction` method has been removed.
|
||||
|
||||
- The `Raven_Client::is_http_request` method has been removed.
|
||||
|
||||
- The `Raven_Client::get_http_data` method has been removed.
|
||||
|
||||
- The `Raven_Client::get_user_data` method has been removed.
|
||||
|
||||
- The `Raven_Client::get_extra_data` method has been removed.
|
||||
|
||||
- The `Raven_Client::get_default_data` method has been removed.
|
||||
|
||||
- The `Raven_Client::message` method has been removed.
|
||||
|
||||
- The `Raven_Client::exception` method has been removed.
|
||||
|
||||
- The `Raven_Client::captureQuery` method has been removed.
|
||||
|
||||
- The `Raven_Client::captureMessage` method has changed its signature.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
public function captureMessage($message, $params = array(), $data = array(), $stack = false, $vars = null)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
public function captureMessage(string $message, ?Severity $level = null, ?Scope $scope = null): ?string
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
- The `Raven_Client::captureException` method has changed its signature.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
public function captureException($exception, $data = null, $logger = null, $vars = null)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
public function captureException(\Throwable $exception, ?Scope $scope = null): ?string
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
- The `Raven_Client::captureLastError` method has changed its signature.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
public function captureLastError()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
public function captureLastError(?Scope $scope = null): ?string
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
- The method `Raven_Client::capture` has been removed.
|
||||
|
||||
- The method `Raven_Client::sanitize` has been removed.
|
||||
|
||||
- The method `Raven_Client::process` has been removed.
|
||||
|
||||
- The method `Raven_Client::sendUnsentErrors` has been removed.
|
||||
|
||||
- The method `Raven_Client::encode` has been removed.
|
||||
|
||||
- The method `Raven_Client::send` has been removed.
|
||||
|
||||
- The method `Raven_Client::send_remote` has been removed.
|
||||
|
||||
- The method `Raven_Client::get_default_ca_cert` has been removed.
|
||||
|
||||
- The method `Raven_Client::get_curl_options` has been removed.
|
||||
|
||||
- The method `Raven_Client::send_http` has been removed.
|
||||
|
||||
- The method `Raven_Client::buildCurlCommand` has been removed.
|
||||
|
||||
- The method `Raven_Client::send_http_asynchronous_curl_exec` has been removed.
|
||||
|
||||
- The method `Raven_Client::send_http_synchronous` has been removed.
|
||||
|
||||
- The method `Raven_Client::get_auth_header` has been removed.
|
||||
|
||||
- The method `Raven_Client::getAuthHeader` has been removed.
|
||||
|
||||
- The method `Raven_Client::uuid4` has been removed.
|
||||
|
||||
- The method `Raven_Client::get_current_url` has been removed.
|
||||
|
||||
- The method `Raven_Client::isHttps` has been removed.
|
||||
|
||||
- The method `Raven_Client::translateSeverity` has been removed.
|
||||
|
||||
- The method `Raven_Client::registerSeverityMap` has been removed.
|
||||
|
||||
- The method `Raven_Client::set_user_data` has been removed.
|
||||
|
||||
- The method `Raven_Client::onShutdown` has been removed.
|
||||
|
||||
- The method `Raven_Client::createProcessors` has been removed.
|
||||
|
||||
- The method `Raven_Client::setProcessors` has been removed.
|
||||
|
||||
- The method `Raven_Client::getLastSentryError` has been removed.
|
||||
|
||||
- The method `Raven_Client::getShutdownFunctionHasBeenSet` has been removed.
|
||||
|
||||
- The method `Raven_Client::close_curl_resource` has been removed.
|
||||
|
||||
- The method `Raven_Client::setSerializer` has been removed. You can set it
|
||||
using the client builder.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client = new Raven_Client();
|
||||
$client->setSerializer(...);
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\ClientBuilder;
|
||||
|
||||
$clientBuilder = ClientBuilder::create();
|
||||
$clientBuilder->setSerializer(...);
|
||||
```
|
||||
|
||||
- The method `Raven_Client::setReprSerializer` has been removed. You can set it
|
||||
using the client builder.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client = new Raven_Client();
|
||||
$client->setSerializer(...);
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\ClientBuilder;
|
||||
|
||||
$clientBuilder = ClientBuilder::create();
|
||||
$clientBuilder->setRepresentationSerializer(...);
|
||||
```
|
||||
|
||||
- The method `Raven_Client::cleanup_php_version` has been removed.
|
||||
|
||||
- The method `Raven_Client::registerDefaultBreadcrumbHandlers` has been removed.
|
||||
|
||||
- The `Raven_Client::user_context` method has been removed. You can set this
|
||||
data in the current active scope.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client->user_context(array('foo', 'bar'));
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\State\Hub;
|
||||
use Sentry\State\Scope;
|
||||
|
||||
Hub::getCurrent()->configureScope(function (Scope $scope): void {
|
||||
$scope->setUser(['email' => 'foo@example.com']);
|
||||
});
|
||||
```
|
||||
|
||||
- The `Raven_Client::tags_context` method has been removed. You can set this
|
||||
data in the current active scope.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client->tags_context(array('foo', 'bar'));
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\State\Hub;
|
||||
use Sentry\State\Scope;
|
||||
|
||||
Hub::getCurrent()->configureScope(function (Scope $scope): void {
|
||||
$scope->setTag('tag_name', 'tag_value');
|
||||
});
|
||||
```
|
||||
|
||||
- The `Raven_Client::extra_context` method has been removed. You can set this
|
||||
data in the current active scope.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$client->extra_context(array('foo' => 'bar'));
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\State\Hub;
|
||||
use Sentry\State\Scope;
|
||||
|
||||
Hub::getCurrent()->configureScope(function (Scope $scope): void {
|
||||
$scope->setExtra('extra_key', 'extra_value');
|
||||
});
|
||||
```
|
||||
|
||||
- The method `Raven_Client::install` has been removed. The error handler is
|
||||
registered automatically when using the `ExceptionListenerIntegration`
|
||||
and `ErrorListenerIntegration` integrations (which are enabled by default).
|
||||
|
||||
### Processors
|
||||
|
||||
- The `Raven_Processor_RemoveCookiesProcessor` class has been removed.
|
||||
|
||||
- The `Raven_Processor_SanitizeStacktraceProcessor` class has been removed.
|
||||
|
||||
- The `Raven_Processor_SanitizeHttpHeadersProcessor` class has been removed.
|
||||
|
||||
- The `Raven_Processor_RemoveHttpBodyProcessor` class has been removed.
|
||||
|
||||
- The `Raven_Processor_SanitizeDataProcessor` class has been removed.
|
||||
|
||||
- The `Raven_Processor` class has been removed.
|
||||
|
||||
### Context
|
||||
|
||||
- The `Raven_Context` class has been renamed to `Context`.
|
||||
|
||||
- The `tags`, `extra` and `user` properties of the `Raven_Context` class have
|
||||
been removed. Each instance of the new class represents now a single context
|
||||
type at once.
|
||||
|
||||
## Error handlers
|
||||
|
||||
- The `Raven_Breadcrumbs_ErrorHandler` class has been removed.
|
||||
|
||||
- The `Raven_Breadcrumbs_MonologHandler` class has been removed.
|
||||
|
||||
- The `Raven_ErrorHandler` class has been renamed to `ErrorHandler` and has
|
||||
been made `final`.
|
||||
|
||||
- The method `Raven_ErrorHandler::handleError` has changed its signature by removing
|
||||
the `$context` argument and it has been marked as `internal` to make it clear that
|
||||
it should not be called publicly and its method visibility is subject to changes
|
||||
without any notice.
|
||||
|
||||
- The methods `Raven_ErrorHandler::registerErrorHandler`, `Raven_ErrorHandler::registerExceptionHandler`
|
||||
and `Raven_ErrorHandler::registerShutdownFunction` have been removed. You should
|
||||
use the `ErrorHandler::register` method instead, but note that it registers all
|
||||
error handlers (error, exception and fatal error) at once and there is no way
|
||||
anymore to only use one of them.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$errorHandler = new Raven_ErrorHandler($client);
|
||||
$errorHandler->registerErrorHandler();
|
||||
$errorHandler->registerExceptionHandler();
|
||||
$errorHandler->registerShutdownFunction();
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Sentry\ErrorHandler;
|
||||
|
||||
ErrorHandler::register(function (\Throwable $exception): void {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
- The method `Raven_ErrorHandler::handleError` has changed its signature by
|
||||
removing the `$context` argument and it has been marked as `internal` to
|
||||
make it clear that it should not be called publicly and its method visibility
|
||||
is subject to changes without any notice.
|
||||
|
||||
- The method `Raven_ErrorHandler::handleFatalError` has changed its signature
|
||||
by adding an optional argument named `$error` and it has been marked as `internal`
|
||||
to make it clear that it should not be called publicly and its method visibility
|
||||
is subject to changes without any notice.
|
||||
|
||||
- The method `Raven_ErrorHandler::handleException` has changed its signature by
|
||||
removing the `$isError` and `$vars` arguments and it has been marked as `internal`
|
||||
to make it clear that it should not be called publicly and its method visibility
|
||||
is subject to changes without any notice.
|
||||
|
||||
- The method `Raven_ErrorHandler::bitwiseOr` has been removed and there is no
|
||||
replacement for it.
|
||||
|
||||
- The method `Raven_ErrorHandler::shouldCaptureFatalError` has been removed and
|
||||
there is no replacement for it.
|
||||
|
||||
### Serializers
|
||||
|
||||
- The `Raven_Serializer` class has been renamed to `Serializer` and its constructor
|
||||
changed signature.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
public function __construct($mb_detect_order = null, $message_limit = null)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
public function __construct(int $maxDepth = 3, ?string $mbDetectOrder = null, int $messageLimit = Client::MESSAGE_MAX_LENGTH_LIMIT)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
- The `Raven_ReprSerializer` class has been renamed to `RepresentationSerializer`
|
||||
and its constructor changed signature.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
public function __construct($mb_detect_order = null, $message_limit = null)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
public function __construct(int $maxDepth = 3, ?string $mbDetectOrder = null, int $messageLimit = Client::MESSAGE_MAX_LENGTH_LIMIT)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
5
vendor/sentry/sentry/codecov.yml
vendored
Normal file
5
vendor/sentry/sentry/codecov.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
comment: false
|
||||
ignore:
|
||||
- tests/data
|
||||
- tests/resources
|
||||
- tests/Fixtures
|
||||
94
vendor/sentry/sentry/composer.json
vendored
Normal file
94
vendor/sentry/sentry/composer.json
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"name": "sentry/sentry",
|
||||
"type": "library",
|
||||
"description": "A PHP SDK for Sentry (http://sentry.io)",
|
||||
"keywords": [
|
||||
"sentry",
|
||||
"log",
|
||||
"logging",
|
||||
"error-monitoring",
|
||||
"error-handler",
|
||||
"crash-reporting",
|
||||
"crash-reports"
|
||||
],
|
||||
"homepage": "http://sentry.io",
|
||||
"license": "BSD-3-Clause",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sentry",
|
||||
"email": "accounts@sentry.io"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.1",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"guzzlehttp/promises": "^1.3",
|
||||
"guzzlehttp/psr7": "^1.6",
|
||||
"jean85/pretty-package-versions": "^1.2",
|
||||
"php-http/async-client-implementation": "^1.0",
|
||||
"php-http/client-common": "^1.5|^2.0",
|
||||
"php-http/discovery": "^1.6.1",
|
||||
"php-http/httplug": "^1.1|^2.0",
|
||||
"php-http/message": "^1.5",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/http-message-implementation": "^1.0",
|
||||
"psr/log": "^1.0",
|
||||
"symfony/options-resolver": "^2.7|^3.0|^4.0|^5.0",
|
||||
"symfony/polyfill-uuid": "^1.13.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.16",
|
||||
"monolog/monolog": "^1.3|^2.0",
|
||||
"php-http/mock-client": "^1.3",
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpstan/phpstan-phpunit": "^0.12",
|
||||
"phpunit/phpunit": "^7.5.18",
|
||||
"symfony/phpunit-bridge": "^4.3|^5.0",
|
||||
"vimeo/psalm": "^3.4"
|
||||
},
|
||||
"suggest": {
|
||||
"monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler."
|
||||
},
|
||||
"conflict": {
|
||||
"php-http/client-common": "1.8.0",
|
||||
"raven/raven": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Sentry\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Sentry\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"tests": [
|
||||
"vendor/bin/phpunit --verbose"
|
||||
],
|
||||
"phpcs": [
|
||||
"vendor/bin/php-cs-fixer fix --verbose --diff --dry-run"
|
||||
],
|
||||
"phpstan": [
|
||||
"vendor/bin/phpstan analyse"
|
||||
],
|
||||
"psalm": [
|
||||
"vendor/bin/psalm"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"prefer-stable": true,
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.4-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
68
vendor/sentry/sentry/psalm.xml.dist
vendored
Normal file
68
vendor/sentry/sentry/psalm.xml.dist
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
totallyTyped="false"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
memoizeMethodCallResults="true"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
|
||||
<issueHandlers>
|
||||
<LessSpecificReturnType errorLevel="info" />
|
||||
|
||||
<!-- level 3 issues - slightly lazy code writing, but provably low false-negatives -->
|
||||
|
||||
<DeprecatedMethod errorLevel="info" />
|
||||
<DeprecatedProperty errorLevel="info" />
|
||||
<DeprecatedClass errorLevel="info" />
|
||||
<DeprecatedConstant errorLevel="info" />
|
||||
<DeprecatedFunction errorLevel="info" />
|
||||
<DeprecatedInterface errorLevel="info" />
|
||||
<DeprecatedTrait errorLevel="info" />
|
||||
|
||||
<InternalMethod errorLevel="info" />
|
||||
<InternalProperty errorLevel="info" />
|
||||
<InternalClass errorLevel="info" />
|
||||
|
||||
<MissingClosureReturnType errorLevel="info" />
|
||||
<MissingReturnType errorLevel="info" />
|
||||
<MissingPropertyType errorLevel="info" />
|
||||
<InvalidDocblock errorLevel="info" />
|
||||
<MisplacedRequiredParam errorLevel="info" />
|
||||
|
||||
<PropertyNotSetInConstructor errorLevel="info">
|
||||
<errorLevel type="suppress">
|
||||
<file name="src/Monolog/Handler.php" />
|
||||
<referencedProperty name="Monolog\Handler\AbstractHandler::$formatter" />
|
||||
</errorLevel>
|
||||
</PropertyNotSetInConstructor>
|
||||
|
||||
<MissingConstructor errorLevel="info" />
|
||||
<MissingClosureParamType errorLevel="info" />
|
||||
<MissingParamType errorLevel="info" />
|
||||
|
||||
<RedundantCondition errorLevel="info" />
|
||||
|
||||
<DocblockTypeContradiction errorLevel="info" />
|
||||
<RedundantConditionGivenDocblockType errorLevel="info" />
|
||||
|
||||
<UnresolvableInclude errorLevel="info" />
|
||||
|
||||
<RawObjectIteration errorLevel="info" />
|
||||
|
||||
<InvalidStringClass errorLevel="info" />
|
||||
|
||||
<UndefinedClass errorLevel="error">
|
||||
<errorLevel type="suppress">
|
||||
<file name="src/ClientBuilder.php" />
|
||||
<referencedClass name="Http\Client\Curl\Client" />
|
||||
</errorLevel>
|
||||
</UndefinedClass>
|
||||
</issueHandlers>
|
||||
</psalm>
|
||||
398
vendor/sentry/sentry/src/Breadcrumb.php
vendored
Normal file
398
vendor/sentry/sentry/src/Breadcrumb.php
vendored
Normal file
@@ -0,0 +1,398 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
use Sentry\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* This class stores all the information about a breadcrumb.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class Breadcrumb implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* This constant defines the default breadcrumb type.
|
||||
*/
|
||||
public const TYPE_DEFAULT = 'default';
|
||||
|
||||
/**
|
||||
* This constant defines the http breadcrumb type.
|
||||
*/
|
||||
public const TYPE_HTTP = 'http';
|
||||
|
||||
/**
|
||||
* This constant defines the user breadcrumb type.
|
||||
*/
|
||||
public const TYPE_USER = 'user';
|
||||
|
||||
/**
|
||||
* This constant defines the navigation breadcrumb type.
|
||||
*/
|
||||
public const TYPE_NAVIGATION = 'navigation';
|
||||
|
||||
/**
|
||||
* This constant defines the error breadcrumb type.
|
||||
*/
|
||||
public const TYPE_ERROR = 'error';
|
||||
|
||||
/**
|
||||
* This constant defines the debug level for a breadcrumb.
|
||||
*/
|
||||
public const LEVEL_DEBUG = 'debug';
|
||||
|
||||
/**
|
||||
* This constant defines the info level for a breadcrumb.
|
||||
*/
|
||||
public const LEVEL_INFO = 'info';
|
||||
|
||||
/**
|
||||
* This constant defines the warning level for a breadcrumb.
|
||||
*/
|
||||
public const LEVEL_WARNING = 'warning';
|
||||
|
||||
/**
|
||||
* This constant defines the error level for a breadcrumb.
|
||||
*/
|
||||
public const LEVEL_ERROR = 'error';
|
||||
|
||||
/**
|
||||
* This constant defines the critical level for a breadcrumb.
|
||||
*
|
||||
* @deprecated since version 2.2.2, to be removed in 3.0; use fatal instead.
|
||||
*/
|
||||
public const LEVEL_CRITICAL = 'critical';
|
||||
|
||||
/**
|
||||
* This constant defines the fatal level for a breadcrumb.
|
||||
*/
|
||||
public const LEVEL_FATAL = 'fatal';
|
||||
|
||||
/**
|
||||
* This constant defines the list of values allowed to be set as severity
|
||||
* level of the breadcrumb.
|
||||
*/
|
||||
private const ALLOWED_LEVELS = [
|
||||
self::LEVEL_DEBUG,
|
||||
self::LEVEL_INFO,
|
||||
self::LEVEL_WARNING,
|
||||
self::LEVEL_ERROR,
|
||||
self::LEVEL_CRITICAL,
|
||||
self::LEVEL_FATAL,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string The category of the breadcrumb
|
||||
*/
|
||||
private $category;
|
||||
|
||||
/**
|
||||
* @var string The type of breadcrumb
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @var string|null The message of the breadcrumb
|
||||
*/
|
||||
private $message;
|
||||
|
||||
/**
|
||||
* @var string The level of the breadcrumb
|
||||
*/
|
||||
private $level;
|
||||
|
||||
/**
|
||||
* @var array<string, mixed> The meta data of the breadcrumb
|
||||
*/
|
||||
private $metadata;
|
||||
|
||||
/**
|
||||
* @var float The timestamp of the breadcrumb
|
||||
*/
|
||||
private $timestamp;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $level The error level of the breadcrumb
|
||||
* @param string $type The type of the breadcrumb
|
||||
* @param string $category The category of the breadcrumb
|
||||
* @param string|null $message Optional text message
|
||||
* @param array<string, mixed> $metadata Additional information about the breadcrumb
|
||||
*/
|
||||
public function __construct(string $level, string $type, string $category, ?string $message = null, array $metadata = [])
|
||||
{
|
||||
if (!\in_array($level, self::ALLOWED_LEVELS, true)) {
|
||||
throw new InvalidArgumentException('The value of the $level argument must be one of the Breadcrumb::LEVEL_* constants.');
|
||||
}
|
||||
|
||||
$this->type = $type;
|
||||
$this->level = $level;
|
||||
$this->category = $category;
|
||||
$this->message = $message;
|
||||
$this->metadata = $metadata;
|
||||
$this->timestamp = microtime(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the severity of the error to one of the levels supported by the
|
||||
* breadcrumbs.
|
||||
*
|
||||
* @param \ErrorException $exception The exception
|
||||
*
|
||||
* @deprecated since version 2.3, to be removed in 3.0
|
||||
*/
|
||||
public static function levelFromErrorException(\ErrorException $exception): string
|
||||
{
|
||||
@trigger_error(sprintf('Method %s() is deprecated since version 2.3 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
switch ($exception->getSeverity()) {
|
||||
case E_DEPRECATED:
|
||||
case E_USER_DEPRECATED:
|
||||
case E_WARNING:
|
||||
case E_USER_WARNING:
|
||||
case E_RECOVERABLE_ERROR:
|
||||
return self::LEVEL_WARNING;
|
||||
case E_ERROR:
|
||||
case E_PARSE:
|
||||
case E_CORE_ERROR:
|
||||
case E_CORE_WARNING:
|
||||
case E_COMPILE_ERROR:
|
||||
case E_COMPILE_WARNING:
|
||||
return self::LEVEL_FATAL;
|
||||
case E_USER_ERROR:
|
||||
return self::LEVEL_ERROR;
|
||||
case E_NOTICE:
|
||||
case E_USER_NOTICE:
|
||||
case E_STRICT:
|
||||
return self::LEVEL_INFO;
|
||||
default:
|
||||
return self::LEVEL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the breadcrumb type.
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of the breadcrumb.
|
||||
*
|
||||
* @param string $type The type
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function withType(string $type): self
|
||||
{
|
||||
if ($type === $this->type) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->type = $type;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the breadcrumb level.
|
||||
*/
|
||||
public function getLevel(): string
|
||||
{
|
||||
return $this->level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the error level of the breadcrumb.
|
||||
*
|
||||
* @param string $level The level
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function withLevel(string $level): self
|
||||
{
|
||||
if (!\in_array($level, self::ALLOWED_LEVELS, true)) {
|
||||
throw new InvalidArgumentException('The value of the $level argument must be one of the Breadcrumb::LEVEL_* constants.');
|
||||
}
|
||||
|
||||
if ($level === $this->level) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->level = $level;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the breadcrumb category.
|
||||
*/
|
||||
public function getCategory(): string
|
||||
{
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the breadcrumb category.
|
||||
*
|
||||
* @param string $category The category
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function withCategory(string $category): self
|
||||
{
|
||||
if ($category === $this->category) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->category = $category;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the breadcrumb message.
|
||||
*/
|
||||
public function getMessage(): ?string
|
||||
{
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the breadcrumb message.
|
||||
*
|
||||
* @param string $message The message
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function withMessage(string $message): self
|
||||
{
|
||||
if ($message === $this->message) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->message = $message;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the breadcrumb meta data.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getMetadata(): array
|
||||
{
|
||||
return $this->metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of this class with the provided metadata, replacing
|
||||
* any existing values of any metadata with the same name.
|
||||
*
|
||||
* @param string $name The name of the metadata
|
||||
* @param mixed $value The value
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function withMetadata(string $name, $value): self
|
||||
{
|
||||
if (isset($this->metadata[$name]) && $value === $this->metadata[$name]) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
$new->metadata[$name] = $value;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of this class without the specified metadata
|
||||
* information.
|
||||
*
|
||||
* @param string $name The name of the metadata
|
||||
*
|
||||
* @return static|Breadcrumb
|
||||
*/
|
||||
public function withoutMetadata(string $name): self
|
||||
{
|
||||
if (!isset($this->metadata[$name])) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$new = clone $this;
|
||||
|
||||
unset($new->metadata[$name]);
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the breadcrumb timestamp.
|
||||
*/
|
||||
public function getTimestamp(): float
|
||||
{
|
||||
return $this->timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the breadcrumb as an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'type' => $this->type,
|
||||
'category' => $this->category,
|
||||
'level' => $this->level,
|
||||
'message' => $this->message,
|
||||
'timestamp' => $this->timestamp,
|
||||
'data' => $this->metadata,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create an instance of this class from an array of data.
|
||||
*
|
||||
* @param array $data Data used to populate the breadcrumb
|
||||
*
|
||||
* @psalm-param array{
|
||||
* level: string,
|
||||
* type?: string,
|
||||
* category: string,
|
||||
* message?: string,
|
||||
* data?: array<string, mixed>
|
||||
* } $data
|
||||
*/
|
||||
public static function fromArray(array $data): self
|
||||
{
|
||||
return new self(
|
||||
$data['level'],
|
||||
$data['type'] ?? self::TYPE_DEFAULT,
|
||||
$data['category'],
|
||||
$data['message'] ?? null,
|
||||
$data['data'] ?? []
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
}
|
||||
214
vendor/sentry/sentry/src/Client.php
vendored
Normal file
214
vendor/sentry/sentry/src/Client.php
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
use GuzzleHttp\Promise\FulfilledPromise;
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Sentry\Integration\FrameContextifierIntegration;
|
||||
use Sentry\Integration\Handler;
|
||||
use Sentry\Integration\IgnoreErrorsIntegration;
|
||||
use Sentry\Integration\IntegrationInterface;
|
||||
use Sentry\State\Scope;
|
||||
use Sentry\Transport\ClosableTransportInterface;
|
||||
use Sentry\Transport\TransportInterface;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@see ClientInterface} interface.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class Client implements FlushableClientInterface
|
||||
{
|
||||
/**
|
||||
* The version of the protocol to communicate with the Sentry server.
|
||||
*/
|
||||
public const PROTOCOL_VERSION = '7';
|
||||
|
||||
/**
|
||||
* The identifier of the SDK.
|
||||
*/
|
||||
public const SDK_IDENTIFIER = 'sentry.php';
|
||||
|
||||
/**
|
||||
* @var Options The client options
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @var TransportInterface The transport
|
||||
*/
|
||||
private $transport;
|
||||
|
||||
/**
|
||||
* @var EventFactoryInterface The factory to create {@see Event} from raw data
|
||||
*/
|
||||
private $eventFactory;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface The PSR-3 logger
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var array<string, IntegrationInterface> The stack of integrations
|
||||
*
|
||||
* @psalm-var array<class-string<IntegrationInterface>, IntegrationInterface>
|
||||
*/
|
||||
private $integrations;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Options $options The client configuration
|
||||
* @param TransportInterface $transport The transport
|
||||
* @param EventFactoryInterface $eventFactory The factory for events
|
||||
* @param LoggerInterface|null $logger The PSR-3 logger
|
||||
*/
|
||||
public function __construct(Options $options, TransportInterface $transport, EventFactoryInterface $eventFactory, ?LoggerInterface $logger = null)
|
||||
{
|
||||
$this->options = $options;
|
||||
$this->transport = $transport;
|
||||
$this->eventFactory = $eventFactory;
|
||||
$this->integrations = Handler::setupIntegrations($options->getIntegrations());
|
||||
$this->logger = $logger ?? new NullLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOptions(): Options
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function captureMessage(string $message, ?Severity $level = null, ?Scope $scope = null): ?string
|
||||
{
|
||||
$payload = [
|
||||
'message' => $message,
|
||||
'level' => $level,
|
||||
];
|
||||
|
||||
return $this->captureEvent($payload, $scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function captureException(\Throwable $exception, ?Scope $scope = null): ?string
|
||||
{
|
||||
if (!isset($this->integrations[IgnoreErrorsIntegration::class]) && $this->options->isExcludedException($exception, false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->captureEvent(['exception' => $exception], $scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function captureEvent(array $payload, ?Scope $scope = null): ?string
|
||||
{
|
||||
$event = $this->prepareEvent($payload, $scope);
|
||||
|
||||
if (null === $event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->transport->send($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function captureLastError(?Scope $scope = null): ?string
|
||||
{
|
||||
$error = error_get_last();
|
||||
|
||||
if (null === $error || !isset($error['message'][0])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$exception = new \ErrorException(@$error['message'], 0, @$error['type'], @$error['file'], @$error['line']);
|
||||
|
||||
return $this->captureException($exception, $scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @psalm-template T of IntegrationInterface
|
||||
*/
|
||||
public function getIntegration(string $className): ?IntegrationInterface
|
||||
{
|
||||
/** @psalm-var T|null */
|
||||
return $this->integrations[$className] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function flush(?int $timeout = null): PromiseInterface
|
||||
{
|
||||
if (!$this->transport instanceof ClosableTransportInterface) {
|
||||
return new FulfilledPromise(true);
|
||||
}
|
||||
|
||||
return $this->transport->close($timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles an event and prepares it to be sent of to Sentry.
|
||||
*
|
||||
* @param array<string, mixed> $payload The payload that will be converted to an Event
|
||||
* @param Scope|null $scope Optional scope which enriches the Event
|
||||
*
|
||||
* @return Event|null The prepared event object or null if it must be discarded
|
||||
*/
|
||||
private function prepareEvent(array $payload, ?Scope $scope = null): ?Event
|
||||
{
|
||||
$shouldReadSourceCodeExcerpts = !isset($this->integrations[FrameContextifierIntegration::class]) && null !== $this->options->getContextLines();
|
||||
|
||||
if ($this->options->shouldAttachStacktrace() && !isset($payload['exception']) && !isset($payload['stacktrace'])) {
|
||||
/** @psalm-suppress TooManyArguments */
|
||||
$event = $this->eventFactory->createWithStacktrace($payload, $shouldReadSourceCodeExcerpts);
|
||||
} else {
|
||||
/** @psalm-suppress TooManyArguments */
|
||||
$event = $this->eventFactory->create($payload, $shouldReadSourceCodeExcerpts);
|
||||
}
|
||||
|
||||
$sampleRate = $this->options->getSampleRate();
|
||||
|
||||
if ($sampleRate < 1 && mt_rand(1, 100) / 100.0 > $sampleRate) {
|
||||
$this->logger->info('The event will be discarded because it has been sampled.', ['event' => $event]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (null !== $scope) {
|
||||
$previousEvent = $event;
|
||||
$event = $scope->applyToEvent($event, $payload);
|
||||
|
||||
if (null === $event) {
|
||||
$this->logger->info('The event will be discarded because one of the event processors returned `null`.', ['event' => $previousEvent]);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$previousEvent = $event;
|
||||
$event = ($this->options->getBeforeSendCallback())($event);
|
||||
|
||||
if (null === $event) {
|
||||
$this->logger->info('The event will be discarded because the "before_send" callback returned `null`.', ['event' => $previousEvent]);
|
||||
}
|
||||
|
||||
return $event;
|
||||
}
|
||||
}
|
||||
345
vendor/sentry/sentry/src/ClientBuilder.php
vendored
Normal file
345
vendor/sentry/sentry/src/ClientBuilder.php
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
use Http\Client\Common\Plugin as PluginInterface;
|
||||
use Http\Client\HttpAsyncClient;
|
||||
use Http\Discovery\MessageFactoryDiscovery;
|
||||
use Http\Discovery\StreamFactoryDiscovery;
|
||||
use Http\Discovery\UriFactoryDiscovery;
|
||||
use Http\Message\MessageFactory as MessageFactoryInterface;
|
||||
use Http\Message\StreamFactory as StreamFactoryInterface;
|
||||
use Http\Message\UriFactory as UriFactoryInterface;
|
||||
use Jean85\PrettyVersions;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Sentry\HttpClient\HttpClientFactory;
|
||||
use Sentry\HttpClient\PluggableHttpClientFactory;
|
||||
use Sentry\Serializer\RepresentationSerializer;
|
||||
use Sentry\Serializer\RepresentationSerializerInterface;
|
||||
use Sentry\Serializer\Serializer;
|
||||
use Sentry\Serializer\SerializerInterface;
|
||||
use Sentry\Transport\DefaultTransportFactory;
|
||||
use Sentry\Transport\TransportFactoryInterface;
|
||||
use Sentry\Transport\TransportInterface;
|
||||
|
||||
/**
|
||||
* The default implementation of {@link ClientBuilderInterface}.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class ClientBuilder implements ClientBuilderInterface
|
||||
{
|
||||
/**
|
||||
* @var Options The client options
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @var UriFactoryInterface|null The PSR-7 URI factory
|
||||
*/
|
||||
private $uriFactory;
|
||||
|
||||
/**
|
||||
* @var StreamFactoryInterface|null The PSR-17 stream factory
|
||||
*/
|
||||
private $streamFactory;
|
||||
|
||||
/**
|
||||
* @var MessageFactoryInterface|null The PSR-7 message factory
|
||||
*/
|
||||
private $messageFactory;
|
||||
|
||||
/**
|
||||
* @var TransportFactoryInterface|null The transport factory
|
||||
*/
|
||||
private $transportFactory;
|
||||
|
||||
/**
|
||||
* @var TransportInterface|null The transport
|
||||
*/
|
||||
private $transport;
|
||||
|
||||
/**
|
||||
* @var HttpAsyncClient|null The HTTP client
|
||||
*/
|
||||
private $httpClient;
|
||||
|
||||
/**
|
||||
* @var PluginInterface[] The list of Httplug plugins
|
||||
*/
|
||||
private $httpClientPlugins = [];
|
||||
|
||||
/**
|
||||
* @var SerializerInterface|null The serializer to be injected in the client
|
||||
*/
|
||||
private $serializer;
|
||||
|
||||
/**
|
||||
* @var RepresentationSerializerInterface|null The representation serializer to be injected in the client
|
||||
*/
|
||||
private $representationSerializer;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface|null A PSR-3 logger to log internal errors and debug messages
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var string The SDK identifier, to be used in {@see Event} and {@see SentryAuth}
|
||||
*/
|
||||
private $sdkIdentifier = Client::SDK_IDENTIFIER;
|
||||
|
||||
/**
|
||||
* @var string The SDK version of the Client
|
||||
*/
|
||||
private $sdkVersion;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param Options|null $options The client options
|
||||
*/
|
||||
public function __construct(Options $options = null)
|
||||
{
|
||||
$this->options = $options ?? new Options();
|
||||
$this->sdkVersion = PrettyVersions::getVersion('sentry/sentry')->getPrettyVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(array $options = []): ClientBuilderInterface
|
||||
{
|
||||
return new static(new Options($options));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOptions(): Options
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUriFactory(UriFactoryInterface $uriFactory): ClientBuilderInterface
|
||||
{
|
||||
@trigger_error(sprintf('Method %s() is deprecated since version 2.3 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->uriFactory = $uriFactory;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setMessageFactory(MessageFactoryInterface $messageFactory): ClientBuilderInterface
|
||||
{
|
||||
@trigger_error(sprintf('Method %s() is deprecated since version 2.3 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->messageFactory = $messageFactory;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setTransport(TransportInterface $transport): ClientBuilderInterface
|
||||
{
|
||||
@trigger_error(sprintf('Method %s() is deprecated since version 2.3 and will be removed in 3.0. Use the setTransportFactory() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->transport = $transport;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setHttpClient(HttpAsyncClient $httpClient): ClientBuilderInterface
|
||||
{
|
||||
@trigger_error(sprintf('Method %s() is deprecated since version 2.3 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->httpClient = $httpClient;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addHttpClientPlugin(PluginInterface $plugin): ClientBuilderInterface
|
||||
{
|
||||
@trigger_error(sprintf('Method %s() is deprecated since version 2.3 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->httpClientPlugins[] = $plugin;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function removeHttpClientPlugin(string $className): ClientBuilderInterface
|
||||
{
|
||||
@trigger_error(sprintf('Method %s() is deprecated since version 2.3 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
foreach ($this->httpClientPlugins as $index => $httpClientPlugin) {
|
||||
if (!$httpClientPlugin instanceof $className) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($this->httpClientPlugins[$index]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setSerializer(SerializerInterface $serializer): ClientBuilderInterface
|
||||
{
|
||||
$this->serializer = $serializer;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRepresentationSerializer(RepresentationSerializerInterface $representationSerializer): ClientBuilderInterface
|
||||
{
|
||||
$this->representationSerializer = $representationSerializer;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setLogger(LoggerInterface $logger): ClientBuilderInterface
|
||||
{
|
||||
$this->logger = $logger;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setSdkIdentifier(string $sdkIdentifier): ClientBuilderInterface
|
||||
{
|
||||
$this->sdkIdentifier = $sdkIdentifier;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setSdkVersion(string $sdkVersion): ClientBuilderInterface
|
||||
{
|
||||
$this->sdkVersion = $sdkVersion;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version of the SDK package that generated this Event using the Packagist name.
|
||||
*
|
||||
* @param string $packageName The package name that will be used to get the version from (i.e. "sentry/sentry")
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated since version 2.2, to be removed in 3.0
|
||||
*/
|
||||
public function setSdkVersionByPackageName(string $packageName): ClientBuilderInterface
|
||||
{
|
||||
@trigger_error(sprintf('Method %s() is deprecated since version 2.2 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->sdkVersion = PrettyVersions::getVersion($packageName)->getPrettyVersion();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClient(): ClientInterface
|
||||
{
|
||||
$this->transport = $this->transport ?? $this->createTransportInstance();
|
||||
|
||||
return new Client($this->options, $this->transport, $this->createEventFactory(), $this->logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transport factory.
|
||||
*
|
||||
* @param TransportFactoryInterface $transportFactory The transport factory
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTransportFactory(TransportFactoryInterface $transportFactory): ClientBuilderInterface
|
||||
{
|
||||
$this->transportFactory = $transportFactory;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of the transport mechanism.
|
||||
*/
|
||||
private function createTransportInstance(): TransportInterface
|
||||
{
|
||||
if (null !== $this->transport) {
|
||||
return $this->transport;
|
||||
}
|
||||
|
||||
$transportFactory = $this->transportFactory ?? $this->createDefaultTransportFactory();
|
||||
|
||||
return $transportFactory->create($this->options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate the {@see EventFactory} with the configured serializers.
|
||||
*/
|
||||
private function createEventFactory(): EventFactoryInterface
|
||||
{
|
||||
$this->serializer = $this->serializer ?? new Serializer($this->options);
|
||||
$this->representationSerializer = $this->representationSerializer ?? new RepresentationSerializer($this->options);
|
||||
|
||||
return new EventFactory($this->serializer, $this->representationSerializer, $this->options, $this->sdkIdentifier, $this->sdkVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of the {@see DefaultTransportFactory} factory.
|
||||
*/
|
||||
private function createDefaultTransportFactory(): DefaultTransportFactory
|
||||
{
|
||||
$this->messageFactory = $this->messageFactory ?? MessageFactoryDiscovery::find();
|
||||
$this->uriFactory = $this->uriFactory ?? UriFactoryDiscovery::find();
|
||||
$this->streamFactory = $this->streamFactory ?? StreamFactoryDiscovery::find();
|
||||
|
||||
$httpClientFactory = new HttpClientFactory(
|
||||
$this->uriFactory,
|
||||
$this->messageFactory,
|
||||
$this->streamFactory,
|
||||
$this->httpClient,
|
||||
$this->sdkIdentifier,
|
||||
$this->sdkVersion
|
||||
);
|
||||
|
||||
if (!empty($this->httpClientPlugins)) {
|
||||
$httpClientFactory = new PluggableHttpClientFactory($httpClientFactory, $this->httpClientPlugins);
|
||||
}
|
||||
|
||||
return new DefaultTransportFactory($this->messageFactory, $httpClientFactory, $this->logger);
|
||||
}
|
||||
}
|
||||
153
vendor/sentry/sentry/src/ClientBuilderInterface.php
vendored
Normal file
153
vendor/sentry/sentry/src/ClientBuilderInterface.php
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
use Http\Client\Common\Plugin as PluginInterface;
|
||||
use Http\Client\HttpAsyncClient;
|
||||
use Http\Message\MessageFactory as MessageFactoryInterface;
|
||||
use Http\Message\UriFactory as UriFactoryInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Sentry\Serializer\RepresentationSerializerInterface;
|
||||
use Sentry\Serializer\SerializerInterface;
|
||||
use Sentry\Transport\TransportFactoryInterface;
|
||||
use Sentry\Transport\TransportInterface;
|
||||
|
||||
/**
|
||||
* A configurable builder for Client objects.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*
|
||||
* @method self setTransportFactory(TransportFactoryInterface $transportFactory)
|
||||
* @method self setLogger(LoggerInterface $logger)
|
||||
*/
|
||||
interface ClientBuilderInterface
|
||||
{
|
||||
/**
|
||||
* Creates a new instance of this builder.
|
||||
*
|
||||
* @param array<string, mixed> $options The client options, in naked array form
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function create(array $options = []): self;
|
||||
|
||||
/**
|
||||
* The options that will be used to create the {@see Client}.
|
||||
*/
|
||||
public function getOptions(): Options;
|
||||
|
||||
/**
|
||||
* Sets the factory to use to create URIs.
|
||||
*
|
||||
* @param UriFactoryInterface $uriFactory The factory
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated Since version 2.3, to be removed in 3.0
|
||||
*/
|
||||
public function setUriFactory(UriFactoryInterface $uriFactory): self;
|
||||
|
||||
/**
|
||||
* Sets the factory to use to create PSR-7 messages.
|
||||
*
|
||||
* @param MessageFactoryInterface $messageFactory The factory
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated Since version 2.3, to be removed in 3.0
|
||||
*/
|
||||
public function setMessageFactory(MessageFactoryInterface $messageFactory): self;
|
||||
|
||||
/**
|
||||
* Sets the transport that will be used to send events.
|
||||
*
|
||||
* @param TransportInterface $transport The transport
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated Since version 2.3, to be removed in 3.0
|
||||
*/
|
||||
public function setTransport(TransportInterface $transport): self;
|
||||
|
||||
/**
|
||||
* Sets the HTTP client.
|
||||
*
|
||||
* @param HttpAsyncClient $httpClient The HTTP client
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated Since version 2.3, to be removed in 3.0
|
||||
*/
|
||||
public function setHttpClient(HttpAsyncClient $httpClient): self;
|
||||
|
||||
/**
|
||||
* Adds a new HTTP client plugin to the end of the plugins chain.
|
||||
*
|
||||
* @param PluginInterface $plugin The plugin instance
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated Since version 2.3, to be removed in 3.0
|
||||
*/
|
||||
public function addHttpClientPlugin(PluginInterface $plugin): self;
|
||||
|
||||
/**
|
||||
* Removes a HTTP client plugin by its fully qualified class name (FQCN).
|
||||
*
|
||||
* @param string $className The class name
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated Since version 2.3, to be removed in 3.0
|
||||
*/
|
||||
public function removeHttpClientPlugin(string $className): self;
|
||||
|
||||
/**
|
||||
* Gets the instance of the client built using the configured options.
|
||||
*/
|
||||
public function getClient(): ClientInterface;
|
||||
|
||||
/**
|
||||
* Sets a serializer instance to be injected as a dependency of the client.
|
||||
*
|
||||
* @param SerializerInterface $serializer The serializer to be used by the client to fill the events
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSerializer(SerializerInterface $serializer): self;
|
||||
|
||||
/**
|
||||
* Sets a representation serializer instance to be injected as a dependency of the client.
|
||||
*
|
||||
* @param RepresentationSerializerInterface $representationSerializer The representation serializer, used to serialize function
|
||||
* arguments in stack traces, to have string representation
|
||||
* of non-string values
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRepresentationSerializer(RepresentationSerializerInterface $representationSerializer): self;
|
||||
|
||||
/**
|
||||
* Sets the SDK identifier to be passed onto {@see Event} and HTTP User-Agent header.
|
||||
*
|
||||
* @param string $sdkIdentifier The SDK identifier to be sent in {@see Event} and HTTP User-Agent headers
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function setSdkIdentifier(string $sdkIdentifier): self;
|
||||
|
||||
/**
|
||||
* Sets the SDK version to be passed onto {@see Event} and HTTP User-Agent header.
|
||||
*
|
||||
* @param string $sdkVersion The version of the SDK in use, to be sent alongside the SDK identifier
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function setSdkVersion(string $sdkVersion): self;
|
||||
}
|
||||
66
vendor/sentry/sentry/src/ClientInterface.php
vendored
Normal file
66
vendor/sentry/sentry/src/ClientInterface.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
use Sentry\Integration\IntegrationInterface;
|
||||
use Sentry\State\Scope;
|
||||
|
||||
/**
|
||||
* This interface must be implemented by all Raven client classes.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
interface ClientInterface
|
||||
{
|
||||
/**
|
||||
* Returns the options of the client.
|
||||
*/
|
||||
public function getOptions(): Options;
|
||||
|
||||
/**
|
||||
* Logs a message.
|
||||
*
|
||||
* @param string $message The message (primary description) for the event
|
||||
* @param Severity $level The level of the message to be sent
|
||||
* @param Scope|null $scope An optional scope keeping the state
|
||||
*/
|
||||
public function captureMessage(string $message, ?Severity $level = null, ?Scope $scope = null): ?string;
|
||||
|
||||
/**
|
||||
* Logs an exception.
|
||||
*
|
||||
* @param \Throwable $exception The exception object
|
||||
* @param Scope|null $scope An optional scope keeping the state
|
||||
*/
|
||||
public function captureException(\Throwable $exception, ?Scope $scope = null): ?string;
|
||||
|
||||
/**
|
||||
* Logs the most recent error (obtained with {@link error_get_last}).
|
||||
*
|
||||
* @param Scope|null $scope An optional scope keeping the state
|
||||
*/
|
||||
public function captureLastError(?Scope $scope = null): ?string;
|
||||
|
||||
/**
|
||||
* Captures a new event using the provided data.
|
||||
*
|
||||
* @param array<string, mixed> $payload The data of the event being captured
|
||||
* @param Scope|null $scope An optional scope keeping the state
|
||||
*/
|
||||
public function captureEvent(array $payload, ?Scope $scope = null): ?string;
|
||||
|
||||
/**
|
||||
* Returns the integration instance if it is installed on the client.
|
||||
*
|
||||
* @param string $className The FQCN of the integration
|
||||
*
|
||||
* @psalm-template T of IntegrationInterface
|
||||
*
|
||||
* @psalm-param class-string<T> $className
|
||||
*
|
||||
* @psalm-return T|null
|
||||
*/
|
||||
public function getIntegration(string $className): ?IntegrationInterface;
|
||||
}
|
||||
190
vendor/sentry/sentry/src/Context/Context.php
vendored
Normal file
190
vendor/sentry/sentry/src/Context/Context.php
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Context;
|
||||
|
||||
/**
|
||||
* This class stores generic information that will be attached to an event
|
||||
* being sent.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*
|
||||
* @psalm-template T
|
||||
*
|
||||
* @template-implements \ArrayAccess<string, T>
|
||||
* @template-implements \IteratorAggregate<string, T>
|
||||
*/
|
||||
class Context implements \ArrayAccess, \JsonSerializable, \IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* This constant defines the alias used for the user context.
|
||||
*
|
||||
* @deprecated To be removed in 3.0 because unused
|
||||
*/
|
||||
public const CONTEXT_USER = 'user';
|
||||
|
||||
/**
|
||||
* This constant defines the alias used for the runtime context.
|
||||
*
|
||||
* @deprecated To be removed in 3.0 because unused
|
||||
*/
|
||||
public const CONTEXT_RUNTIME = 'runtime';
|
||||
|
||||
/**
|
||||
* This constant defines the alias used for the tags context.
|
||||
*
|
||||
* @deprecated To be removed in 3.0 because unused
|
||||
*/
|
||||
public const CONTEXT_TAGS = 'tags';
|
||||
|
||||
/**
|
||||
* This constant defines the alias used for the extra context.
|
||||
*
|
||||
* @deprecated To be removed in 3.0 because unused
|
||||
*/
|
||||
public const CONTEXT_EXTRA = 'extra';
|
||||
|
||||
/**
|
||||
* This constant defines the alias used for the server OS context.
|
||||
*
|
||||
* @deprecated To be removed in 3.0 because unused
|
||||
*/
|
||||
public const CONTEXT_SERVER_OS = 'server_os';
|
||||
|
||||
/**
|
||||
* @var array The data stored in this object
|
||||
*
|
||||
* @psalm-var array<string, T>
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $data The initial data to store
|
||||
*
|
||||
* @psalm-param array<string, T> $data
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the given data with the existing one, recursively or not, according
|
||||
* to the value of the `$recursive` parameter.
|
||||
*
|
||||
* @param array $data The data to merge
|
||||
* @param bool $recursive Whether to merge the data recursively or not
|
||||
*
|
||||
* @psalm-param array<string, T> $data
|
||||
*/
|
||||
public function merge(array $data, bool $recursive = false): void
|
||||
{
|
||||
$this->data = $recursive ? array_merge_recursive($this->data, $data) : array_merge($this->data, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets each element of the array to the value of the corresponding key in
|
||||
* the given input data.
|
||||
*
|
||||
* @param array $data The data to set
|
||||
*
|
||||
* @psalm-param array<string, T> $data
|
||||
*/
|
||||
public function setData(array $data): void
|
||||
{
|
||||
foreach ($data as $index => $value) {
|
||||
$this->data[$index] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all the data contained in this object with the given one.
|
||||
*
|
||||
* @param array $data The data to set
|
||||
*
|
||||
* @psalm-param array<string, T> $data
|
||||
*/
|
||||
public function replaceData(array $data): void
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the entire data contained in this object.
|
||||
*/
|
||||
public function clear(): void
|
||||
{
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the object is not storing any data.
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return empty($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array representation of the data stored by the object.
|
||||
*
|
||||
* @psalm-return array<string, T>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
return isset($this->data[$offset]) || \array_key_exists($offset, $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->data[$offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
$this->data[$offset] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
unset($this->data[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @psalm-return array<string, T>
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIterator(): \Traversable
|
||||
{
|
||||
return new \ArrayIterator($this->data);
|
||||
}
|
||||
}
|
||||
157
vendor/sentry/sentry/src/Context/RuntimeContext.php
vendored
Normal file
157
vendor/sentry/sentry/src/Context/RuntimeContext.php
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Context;
|
||||
|
||||
use Sentry\Util\PHPVersion;
|
||||
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
|
||||
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* This class is a specialized implementation of the {@see Context} class that
|
||||
* stores information about the current runtime.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*
|
||||
* @final since version 2.3
|
||||
*
|
||||
* @template-extends Context<string>
|
||||
*/
|
||||
class RuntimeContext extends Context
|
||||
{
|
||||
/**
|
||||
* @var OptionsResolver The options resolver
|
||||
*/
|
||||
private $resolver;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws UndefinedOptionsException If any of the options are not supported
|
||||
* by the context
|
||||
* @throws InvalidOptionsException If any of the options don't fulfill the
|
||||
* specified validation rules
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
$this->resolver = new OptionsResolver();
|
||||
|
||||
$this->configureOptions($this->resolver);
|
||||
|
||||
parent::__construct($this->resolver->resolve($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws UndefinedOptionsException If any of the options are not supported
|
||||
* by the context
|
||||
* @throws InvalidOptionsException If any of the options don't fulfill the
|
||||
* specified validation rules
|
||||
*/
|
||||
public function merge(array $data, bool $recursive = false): void
|
||||
{
|
||||
$data = $this->resolver->resolve($data);
|
||||
|
||||
parent::merge($data, $recursive);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws UndefinedOptionsException If any of the options are not supported
|
||||
* by the context
|
||||
* @throws InvalidOptionsException If any of the options don't fulfill the
|
||||
* specified validation rules
|
||||
*/
|
||||
public function setData(array $data): void
|
||||
{
|
||||
$data = $this->resolver->resolve($data);
|
||||
|
||||
parent::setData($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws UndefinedOptionsException If any of the options are not supported
|
||||
* by the context
|
||||
* @throws InvalidOptionsException If any of the options don't fulfill the
|
||||
* specified validation rules
|
||||
*/
|
||||
public function replaceData(array $data): void
|
||||
{
|
||||
$data = $this->resolver->resolve($data);
|
||||
|
||||
parent::replaceData($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws UndefinedOptionsException If any of the options are not supported
|
||||
* by the context
|
||||
* @throws InvalidOptionsException If any of the options don't fulfill the
|
||||
* specified validation rules
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
$data = $this->resolver->resolve([$offset => $value]);
|
||||
|
||||
parent::offsetSet($offset, $data[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the runtime.
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->data['name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the runtime.
|
||||
*
|
||||
* @param string $name The name
|
||||
*/
|
||||
public function setName(string $name): void
|
||||
{
|
||||
$this->offsetSet('name', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version of the runtime.
|
||||
*/
|
||||
public function getVersion(): string
|
||||
{
|
||||
return $this->data['version'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version of the runtime.
|
||||
*
|
||||
* @param string $version The version
|
||||
*/
|
||||
public function setVersion(string $version): void
|
||||
{
|
||||
$this->offsetSet('version', $version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options of the context.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options
|
||||
*/
|
||||
private function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'name' => 'php',
|
||||
'version' => PHPVersion::parseVersion(),
|
||||
]);
|
||||
|
||||
$resolver->setAllowedTypes('name', 'string');
|
||||
$resolver->setAllowedTypes('version', 'string');
|
||||
}
|
||||
}
|
||||
196
vendor/sentry/sentry/src/Context/ServerOsContext.php
vendored
Normal file
196
vendor/sentry/sentry/src/Context/ServerOsContext.php
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Context;
|
||||
|
||||
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
|
||||
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* This class is a specialized implementation of the {@see Context} class that
|
||||
* stores information about the operating system of the server.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*
|
||||
* @final since version 2.3
|
||||
*
|
||||
* @template-extends Context<string>
|
||||
*/
|
||||
class ServerOsContext extends Context
|
||||
{
|
||||
/**
|
||||
* @var OptionsResolver The options resolver
|
||||
*/
|
||||
private $resolver;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws UndefinedOptionsException If any of the options are not supported
|
||||
* by the context
|
||||
* @throws InvalidOptionsException If any of the options don't fulfill the
|
||||
* specified validation rules
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
$this->resolver = new OptionsResolver();
|
||||
|
||||
$this->configureOptions($this->resolver);
|
||||
|
||||
parent::__construct($this->resolver->resolve($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws UndefinedOptionsException If any of the options are not supported
|
||||
* by the context
|
||||
* @throws InvalidOptionsException If any of the options don't fulfill the
|
||||
* specified validation rules
|
||||
*/
|
||||
public function merge(array $data, bool $recursive = false): void
|
||||
{
|
||||
$data = $this->resolver->resolve($data);
|
||||
|
||||
parent::merge($data, $recursive);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws UndefinedOptionsException If any of the options are not supported
|
||||
* by the context
|
||||
* @throws InvalidOptionsException If any of the options don't fulfill the
|
||||
* specified validation rules
|
||||
*/
|
||||
public function setData(array $data): void
|
||||
{
|
||||
$data = $this->resolver->resolve($data);
|
||||
|
||||
parent::setData($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws UndefinedOptionsException If any of the options are not supported
|
||||
* by the context
|
||||
* @throws InvalidOptionsException If any of the options don't fulfill the
|
||||
* specified validation rules
|
||||
*/
|
||||
public function replaceData(array $data): void
|
||||
{
|
||||
$data = $this->resolver->resolve($data);
|
||||
|
||||
parent::replaceData($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws UndefinedOptionsException If any of the options are not supported
|
||||
* by the context
|
||||
* @throws InvalidOptionsException If any of the options don't fulfill the
|
||||
* specified validation rules
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
$data = $this->resolver->resolve([$offset => $value]);
|
||||
|
||||
parent::offsetSet($offset, $data[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the operating system.
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->data['name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the operating system.
|
||||
*
|
||||
* @param string $name The name
|
||||
*/
|
||||
public function setName(string $name): void
|
||||
{
|
||||
$this->offsetSet('name', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version of the operating system.
|
||||
*/
|
||||
public function getVersion(): string
|
||||
{
|
||||
return $this->data['version'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version of the operating system.
|
||||
*
|
||||
* @param string $version The version
|
||||
*/
|
||||
public function setVersion(string $version): void
|
||||
{
|
||||
$this->offsetSet('version', $version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the build of the operating system.
|
||||
*/
|
||||
public function getBuild(): string
|
||||
{
|
||||
return $this->data['build'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the build of the operating system.
|
||||
*
|
||||
* @param string $build The build
|
||||
*/
|
||||
public function setBuild(string $build): void
|
||||
{
|
||||
$this->offsetSet('build', $build);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version of the kernel of the operating system.
|
||||
*/
|
||||
public function getKernelVersion(): string
|
||||
{
|
||||
return $this->data['kernel_version'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version of the kernel of the operating system.
|
||||
*
|
||||
* @param string $kernelVersion The kernel version
|
||||
*/
|
||||
public function setKernelVersion(string $kernelVersion): void
|
||||
{
|
||||
$this->offsetSet('kernel_version', $kernelVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the options of the context.
|
||||
*
|
||||
* @param OptionsResolver $resolver The resolver for the options
|
||||
*/
|
||||
private function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'name' => php_uname('s'),
|
||||
'version' => php_uname('r'),
|
||||
'build' => php_uname('v'),
|
||||
'kernel_version' => php_uname('a'),
|
||||
]);
|
||||
|
||||
$resolver->setAllowedTypes('name', 'string');
|
||||
$resolver->setAllowedTypes('version', 'string');
|
||||
$resolver->setAllowedTypes('build', 'string');
|
||||
$resolver->setAllowedTypes('kernel_version', 'string');
|
||||
}
|
||||
}
|
||||
87
vendor/sentry/sentry/src/Context/TagsContext.php
vendored
Normal file
87
vendor/sentry/sentry/src/Context/TagsContext.php
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Context;
|
||||
|
||||
/**
|
||||
* This class is a specialized version of the base `Context` adapted to work
|
||||
* for the tags context.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*
|
||||
* @final since version 2.3
|
||||
*
|
||||
* @template-extends Context<string>
|
||||
*/
|
||||
class TagsContext extends Context
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function merge(array $data, bool $recursive = false): void
|
||||
{
|
||||
if ($recursive) {
|
||||
throw new \InvalidArgumentException('The tags context does not allow recursive merging of its data.');
|
||||
}
|
||||
|
||||
parent::merge(self::sanitizeData($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setData(array $data): void
|
||||
{
|
||||
parent::setData(self::sanitizeData($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function replaceData(array $data): void
|
||||
{
|
||||
parent::replaceData(self::sanitizeData($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if (is_numeric($value)) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
if (!\is_string($value)) {
|
||||
throw new \InvalidArgumentException('The $value argument must be a string.');
|
||||
}
|
||||
|
||||
parent::offsetSet($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes the given data by converting numeric values to strings.
|
||||
*
|
||||
* @param array<string, string> $data The data to sanitize
|
||||
*
|
||||
* @return array<string, string>
|
||||
*
|
||||
* @throws \InvalidArgumentException If any of the values of the input data
|
||||
* is not a number or a string
|
||||
*/
|
||||
private static function sanitizeData(array $data): array
|
||||
{
|
||||
foreach ($data as &$value) {
|
||||
if (is_numeric($value)) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
if (!\is_string($value)) {
|
||||
throw new \InvalidArgumentException('The $data argument must contains a simple array of string values.');
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
86
vendor/sentry/sentry/src/Context/UserContext.php
vendored
Normal file
86
vendor/sentry/sentry/src/Context/UserContext.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Context;
|
||||
|
||||
/**
|
||||
* This class is a specialized version of the base `Context` adapted to work
|
||||
* for the user context.
|
||||
*
|
||||
* @template-extends Context<mixed>
|
||||
*/
|
||||
final class UserContext extends Context
|
||||
{
|
||||
/**
|
||||
* Gets the ID of the user.
|
||||
*/
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->data['id'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ID of the user.
|
||||
*
|
||||
* @param string|null $id The ID
|
||||
*/
|
||||
public function setId(?string $id): void
|
||||
{
|
||||
$this->data['id'] = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the username of the user.
|
||||
*/
|
||||
public function getUsername(): ?string
|
||||
{
|
||||
return $this->data['username'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the username of the user.
|
||||
*
|
||||
* @param string|null $username The username
|
||||
*/
|
||||
public function setUsername(?string $username): void
|
||||
{
|
||||
$this->data['username'] = $username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the email of the user.
|
||||
*/
|
||||
public function getEmail(): ?string
|
||||
{
|
||||
return $this->data['email'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the email of the user.
|
||||
*
|
||||
* @param string|null $email The email
|
||||
*/
|
||||
public function setEmail(?string $email): void
|
||||
{
|
||||
$this->data['email'] = $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ip address of the user.
|
||||
*/
|
||||
public function getIpAddress(): ?string
|
||||
{
|
||||
return $this->data['ip_address'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ip address of the user.
|
||||
*
|
||||
* @param string|null $ipAddress The ip address
|
||||
*/
|
||||
public function setIpAddress(?string $ipAddress): void
|
||||
{
|
||||
$this->data['ip_address'] = $ipAddress;
|
||||
}
|
||||
}
|
||||
228
vendor/sentry/sentry/src/Dsn.php
vendored
Normal file
228
vendor/sentry/sentry/src/Dsn.php
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
/**
|
||||
* This class represents a Sentry DSN that can be obtained from the Settings
|
||||
* page of a project.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class Dsn
|
||||
{
|
||||
/**
|
||||
* @var string The protocol to be used to access the resource
|
||||
*/
|
||||
private $scheme;
|
||||
|
||||
/**
|
||||
* @var string The host that holds the resource
|
||||
*/
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* @var int The port on which the resource is exposed
|
||||
*/
|
||||
private $port;
|
||||
|
||||
/**
|
||||
* @var string The public key to authenticate the SDK
|
||||
*/
|
||||
private $publicKey;
|
||||
|
||||
/**
|
||||
* @var string|null The secret key to authenticate the SDK
|
||||
*/
|
||||
private $secretKey;
|
||||
|
||||
/**
|
||||
* @var int The ID of the resource to access
|
||||
*/
|
||||
private $projectId;
|
||||
|
||||
/**
|
||||
* @var string The specific resource that the web client wants to access
|
||||
*/
|
||||
private $path;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param string $scheme The protocol to be used to access the resource
|
||||
* @param string $host The host that holds the resource
|
||||
* @param int $port The port on which the resource is exposed
|
||||
* @param int $projectId The ID of the resource to access
|
||||
* @param string $path The specific resource that the web client wants to access
|
||||
* @param string $publicKey The public key to authenticate the SDK
|
||||
* @param string|null $secretKey The secret key to authenticate the SDK
|
||||
*/
|
||||
private function __construct(string $scheme, string $host, int $port, int $projectId, string $path, string $publicKey, ?string $secretKey)
|
||||
{
|
||||
$this->scheme = $scheme;
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->publicKey = $publicKey;
|
||||
$this->secretKey = $secretKey;
|
||||
$this->path = $path;
|
||||
$this->projectId = $projectId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of this class by parsing the given string.
|
||||
*
|
||||
* @param string $value The string to parse
|
||||
*/
|
||||
public static function createFromString(string $value): self
|
||||
{
|
||||
$parsedDsn = parse_url($value);
|
||||
|
||||
if (false === $parsedDsn) {
|
||||
throw new \InvalidArgumentException(sprintf('The "%s" DSN is invalid.', $value));
|
||||
}
|
||||
|
||||
foreach (['scheme', 'host', 'path', 'user'] as $component) {
|
||||
if (!isset($parsedDsn[$component]) || (isset($parsedDsn[$component]) && empty($parsedDsn[$component]))) {
|
||||
throw new \InvalidArgumentException(sprintf('The "%s" DSN must contain a scheme, a host, a user and a path component.', $value));
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($parsedDsn['pass']) && empty($parsedDsn['pass'])) {
|
||||
throw new \InvalidArgumentException(sprintf('The "%s" DSN must contain a valid secret key.', $value));
|
||||
}
|
||||
|
||||
/** @psalm-suppress PossiblyUndefinedArrayOffset */
|
||||
if (!\in_array($parsedDsn['scheme'], ['http', 'https'], true)) {
|
||||
throw new \InvalidArgumentException(sprintf('The scheme of the "%s" DSN must be either "http" or "https".', $value));
|
||||
}
|
||||
|
||||
/** @psalm-suppress PossiblyUndefinedArrayOffset */
|
||||
$segmentPaths = explode('/', $parsedDsn['path']);
|
||||
$projectId = array_pop($segmentPaths);
|
||||
|
||||
if (!ctype_digit($projectId)) {
|
||||
throw new \InvalidArgumentException('"%s" DSN must contain a valid project ID.');
|
||||
}
|
||||
|
||||
$lastSlashPosition = strrpos($parsedDsn['path'], '/');
|
||||
$path = $parsedDsn['path'];
|
||||
|
||||
if (false !== $lastSlashPosition) {
|
||||
$path = substr($parsedDsn['path'], 0, $lastSlashPosition);
|
||||
}
|
||||
|
||||
/** @psalm-suppress PossiblyUndefinedArrayOffset */
|
||||
return new self(
|
||||
$parsedDsn['scheme'],
|
||||
$parsedDsn['host'],
|
||||
$parsedDsn['port'] ?? ('http' === $parsedDsn['scheme'] ? 80 : 443),
|
||||
(int) $projectId,
|
||||
$path,
|
||||
$parsedDsn['user'],
|
||||
$parsedDsn['pass'] ?? null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the protocol to be used to access the resource.
|
||||
*/
|
||||
public function getScheme(): string
|
||||
{
|
||||
return $this->scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the host that holds the resource.
|
||||
*/
|
||||
public function getHost(): string
|
||||
{
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the port on which the resource is exposed.
|
||||
*/
|
||||
public function getPort(): int
|
||||
{
|
||||
return $this->port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the specific resource that the web client wants to access.
|
||||
*/
|
||||
public function getPath(): string
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ID of the resource to access.
|
||||
*/
|
||||
public function getProjectId(): int
|
||||
{
|
||||
return $this->projectId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public key to authenticate the SDK.
|
||||
*/
|
||||
public function getPublicKey(): string
|
||||
{
|
||||
return $this->publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the secret key to authenticate the SDK.
|
||||
*/
|
||||
public function getSecretKey(): ?string
|
||||
{
|
||||
return $this->secretKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL of the API endpoint to use to post an event to Sentry.
|
||||
*/
|
||||
public function getStoreApiEndpointUrl(): string
|
||||
{
|
||||
$url = $this->scheme . '://' . $this->host;
|
||||
|
||||
if (('http' === $this->scheme && 80 !== $this->port) || ('https' === $this->scheme && 443 !== $this->port)) {
|
||||
$url .= ':' . $this->port;
|
||||
}
|
||||
|
||||
if (null !== $this->path) {
|
||||
$url .= $this->path;
|
||||
}
|
||||
|
||||
$url .= '/api/' . $this->projectId . '/store/';
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://www.php.net/manual/en/language.oop5.magic.php#object.tostring
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
$url = $this->scheme . '://' . $this->publicKey;
|
||||
|
||||
if (null !== $this->secretKey) {
|
||||
$url .= ':' . $this->secretKey;
|
||||
}
|
||||
|
||||
$url .= '@' . $this->host;
|
||||
|
||||
if (('http' === $this->scheme && 80 !== $this->port) || ('https' === $this->scheme && 443 !== $this->port)) {
|
||||
$url .= ':' . $this->port;
|
||||
}
|
||||
|
||||
if (null !== $this->path) {
|
||||
$url .= $this->path;
|
||||
}
|
||||
|
||||
$url .= '/' . $this->projectId;
|
||||
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
499
vendor/sentry/sentry/src/ErrorHandler.php
vendored
Normal file
499
vendor/sentry/sentry/src/ErrorHandler.php
vendored
Normal file
@@ -0,0 +1,499 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
use Sentry\Exception\FatalErrorException;
|
||||
use Sentry\Exception\SilencedErrorException;
|
||||
|
||||
/**
|
||||
* This class implements a simple error handler that catches all configured
|
||||
* error types and relays them to all configured listeners. Registering this
|
||||
* error handler more than once is not supported and will lead to nasty
|
||||
* problems. The code is based on the Symfony ErrorHandler component.
|
||||
*/
|
||||
final class ErrorHandler
|
||||
{
|
||||
/**
|
||||
* The default amount of bytes of memory to reserve for the fatal error handler.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public const DEFAULT_RESERVED_MEMORY_SIZE = 10240;
|
||||
|
||||
/**
|
||||
* @var self|null The current registered handler (this class is a singleton)
|
||||
*/
|
||||
private static $handlerInstance;
|
||||
|
||||
/**
|
||||
* @var callable[] List of listeners that will act on each captured error
|
||||
*
|
||||
* @psalm-var (callable(\ErrorException): void)[]
|
||||
*/
|
||||
private $errorListeners = [];
|
||||
|
||||
/**
|
||||
* @var callable[] List of listeners that will act of each captured fatal error
|
||||
*
|
||||
* @psalm-var (callable(FatalErrorException): void)[]
|
||||
*/
|
||||
private $fatalErrorListeners = [];
|
||||
|
||||
/**
|
||||
* @var callable[] List of listeners that will act on each captured exception
|
||||
*
|
||||
* @psalm-var (callable(\Throwable): void)[]
|
||||
*/
|
||||
private $exceptionListeners = [];
|
||||
|
||||
/**
|
||||
* @var \ReflectionProperty A reflection cached instance that points to the
|
||||
* trace property of the exception objects
|
||||
*/
|
||||
private $exceptionReflection;
|
||||
|
||||
/**
|
||||
* @var callable|null The previous error handler, if any
|
||||
*/
|
||||
private $previousErrorHandler;
|
||||
|
||||
/**
|
||||
* @var callable|null The previous exception handler, if any
|
||||
*
|
||||
* @psalm-var null|callable(\Throwable): void
|
||||
*/
|
||||
private $previousExceptionHandler;
|
||||
|
||||
/**
|
||||
* @var bool Whether the error handler has been registered
|
||||
*/
|
||||
private $isErrorHandlerRegistered = false;
|
||||
|
||||
/**
|
||||
* @var bool Whether the exception handler has been registered
|
||||
*/
|
||||
private $isExceptionHandlerRegistered = false;
|
||||
|
||||
/**
|
||||
* @var bool Whether the fatal error handler has been registered
|
||||
*/
|
||||
private $isFatalErrorHandlerRegistered = false;
|
||||
|
||||
/**
|
||||
* @var string|null A portion of pre-allocated memory data that will be reclaimed
|
||||
* in case a fatal error occurs to handle it
|
||||
*/
|
||||
private static $reservedMemory;
|
||||
|
||||
/**
|
||||
* @var array List of error levels and their description
|
||||
*/
|
||||
private const ERROR_LEVELS_DESCRIPTION = [
|
||||
E_DEPRECATED => 'Deprecated',
|
||||
E_USER_DEPRECATED => 'User Deprecated',
|
||||
E_NOTICE => 'Notice',
|
||||
E_USER_NOTICE => 'User Notice',
|
||||
E_STRICT => 'Runtime Notice',
|
||||
E_WARNING => 'Warning',
|
||||
E_USER_WARNING => 'User Warning',
|
||||
E_COMPILE_WARNING => 'Compile Warning',
|
||||
E_CORE_WARNING => 'Core Warning',
|
||||
E_USER_ERROR => 'User Error',
|
||||
E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
|
||||
E_COMPILE_ERROR => 'Compile Error',
|
||||
E_PARSE => 'Parse Error',
|
||||
E_ERROR => 'Error',
|
||||
E_CORE_ERROR => 'Core Error',
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @throws \ReflectionException If hooking into the \Exception class to
|
||||
* make the `trace` property accessible fails
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
$this->exceptionReflection = new \ReflectionProperty(\Exception::class, 'trace');
|
||||
$this->exceptionReflection->setAccessible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current registered error handler; if none is present, it will
|
||||
* register it. Subsequent calls will not change the reserved memory size.
|
||||
*
|
||||
* @param int $reservedMemorySize The amount of memory to reserve for the
|
||||
* fatal error handler
|
||||
* @param bool $triggerDeprecation Whether to trigger the deprecation about
|
||||
* the usage of this method. This is used
|
||||
* to avoid errors when this method is called
|
||||
* from other methods of this class until
|
||||
* their implementation and behavior of
|
||||
* registering all handlers can be changed
|
||||
*
|
||||
* @deprecated since version 2.1, to be removed in 3.0.
|
||||
*/
|
||||
public static function registerOnce(int $reservedMemorySize = self::DEFAULT_RESERVED_MEMORY_SIZE, bool $triggerDeprecation = true): self
|
||||
{
|
||||
if ($triggerDeprecation) {
|
||||
@trigger_error(sprintf('Method %s() is deprecated since version 2.1 and will be removed in 3.0. Please use the registerOnceErrorHandler(), registerOnceFatalErrorHandler() or registerOnceExceptionHandler() methods instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (null === self::$handlerInstance) {
|
||||
self::$handlerInstance = new self();
|
||||
}
|
||||
|
||||
self::registerOnceErrorHandler();
|
||||
self::registerOnceFatalErrorHandler($reservedMemorySize);
|
||||
self::registerOnceExceptionHandler();
|
||||
|
||||
return self::$handlerInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the error handler once and returns its instance.
|
||||
*/
|
||||
public static function registerOnceErrorHandler(): self
|
||||
{
|
||||
if (null === self::$handlerInstance) {
|
||||
self::$handlerInstance = new self();
|
||||
}
|
||||
|
||||
if (self::$handlerInstance->isErrorHandlerRegistered) {
|
||||
return self::$handlerInstance;
|
||||
}
|
||||
|
||||
$errorHandlerCallback = \Closure::fromCallable([self::$handlerInstance, 'handleError']);
|
||||
|
||||
self::$handlerInstance->isErrorHandlerRegistered = true;
|
||||
self::$handlerInstance->previousErrorHandler = set_error_handler($errorHandlerCallback);
|
||||
|
||||
if (null === self::$handlerInstance->previousErrorHandler) {
|
||||
restore_error_handler();
|
||||
|
||||
// Specifying the error types caught by the error handler with the
|
||||
// first call to the set_error_handler method would cause the PHP
|
||||
// bug https://bugs.php.net/63206 if the handler is not the first
|
||||
// one in the chain of handlers
|
||||
set_error_handler($errorHandlerCallback, E_ALL);
|
||||
}
|
||||
|
||||
return self::$handlerInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the fatal error handler and reserves a certain amount of memory
|
||||
* that will be reclaimed to handle the errors (to prevent out of memory
|
||||
* issues while handling them) and returns its instance.
|
||||
*
|
||||
* @param int $reservedMemorySize The amount of memory to reserve for the fatal
|
||||
* error handler expressed in bytes
|
||||
*/
|
||||
public static function registerOnceFatalErrorHandler(int $reservedMemorySize = self::DEFAULT_RESERVED_MEMORY_SIZE): self
|
||||
{
|
||||
if ($reservedMemorySize <= 0) {
|
||||
throw new \InvalidArgumentException('The $reservedMemorySize argument must be greater than 0.');
|
||||
}
|
||||
|
||||
if (null === self::$handlerInstance) {
|
||||
self::$handlerInstance = new self();
|
||||
}
|
||||
|
||||
if (self::$handlerInstance->isFatalErrorHandlerRegistered) {
|
||||
return self::$handlerInstance;
|
||||
}
|
||||
|
||||
self::$handlerInstance->isFatalErrorHandlerRegistered = true;
|
||||
self::$reservedMemory = str_repeat('x', $reservedMemorySize);
|
||||
|
||||
register_shutdown_function(\Closure::fromCallable([self::$handlerInstance, 'handleFatalError']));
|
||||
|
||||
return self::$handlerInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the exception handler, effectively replacing the current one
|
||||
* and returns its instance. The previous one will be saved anyway and
|
||||
* called when appropriate.
|
||||
*/
|
||||
public static function registerOnceExceptionHandler(): self
|
||||
{
|
||||
if (null === self::$handlerInstance) {
|
||||
self::$handlerInstance = new self();
|
||||
}
|
||||
|
||||
if (self::$handlerInstance->isExceptionHandlerRegistered) {
|
||||
return self::$handlerInstance;
|
||||
}
|
||||
|
||||
self::$handlerInstance->isExceptionHandlerRegistered = true;
|
||||
self::$handlerInstance->previousExceptionHandler = set_exception_handler(\Closure::fromCallable([self::$handlerInstance, 'handleException']));
|
||||
|
||||
return self::$handlerInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to the current error handler to be called upon each
|
||||
* invoked captured error; if no handler is registered, this method will
|
||||
* instantiate and register it.
|
||||
*
|
||||
* @param callable $listener A callable that will act as a listener;
|
||||
* this callable will receive a single
|
||||
* \ErrorException argument
|
||||
*
|
||||
* @psalm-param callable(\ErrorException): void $listener
|
||||
*
|
||||
* @deprecated since version 2.1, to be removed in 3.0
|
||||
*/
|
||||
public static function addErrorListener(callable $listener): void
|
||||
{
|
||||
@trigger_error(sprintf('Method %s() is deprecated since version 2.1 and will be removed in 3.0. Use the addErrorHandlerListener() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
/** @psalm-suppress DeprecatedMethod */
|
||||
$handler = self::registerOnce(self::DEFAULT_RESERVED_MEMORY_SIZE, false);
|
||||
$handler->errorListeners[] = $listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to the current error handler to be called upon each
|
||||
* invoked captured fatal error; if no handler is registered, this method
|
||||
* will instantiate and register it.
|
||||
*
|
||||
* @param callable $listener A callable that will act as a listener;
|
||||
* this callable will receive a single
|
||||
* \ErrorException argument
|
||||
*
|
||||
* @psalm-param callable(FatalErrorException): void $listener
|
||||
*
|
||||
* @deprecated since version 2.1, to be removed in 3.0
|
||||
*/
|
||||
public static function addFatalErrorListener(callable $listener): void
|
||||
{
|
||||
@trigger_error(sprintf('Method %s() is deprecated since version 2.1 and will be removed in 3.0. Use the addFatalErrorHandlerListener() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
/** @psalm-suppress DeprecatedMethod */
|
||||
$handler = self::registerOnce(self::DEFAULT_RESERVED_MEMORY_SIZE, false);
|
||||
$handler->fatalErrorListeners[] = $listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to the current error handler to be called upon each
|
||||
* invoked captured exception; if no handler is registered, this method
|
||||
* will instantiate and register it.
|
||||
*
|
||||
* @param callable $listener A callable that will act as a listener;
|
||||
* this callable will receive a single
|
||||
* \Throwable argument
|
||||
*
|
||||
* @psalm-param callable(\Throwable): void $listener
|
||||
*
|
||||
* @deprecated since version 2.1, to be removed in 3.0
|
||||
*/
|
||||
public static function addExceptionListener(callable $listener): void
|
||||
{
|
||||
@trigger_error(sprintf('Method %s() is deprecated since version 2.1 and will be removed in 3.0. Use the addExceptionHandlerListener() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
/** @psalm-suppress DeprecatedMethod */
|
||||
$handler = self::registerOnce(self::DEFAULT_RESERVED_MEMORY_SIZE, false);
|
||||
$handler->exceptionListeners[] = $listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to the current error handler that will be called every
|
||||
* time an error is captured.
|
||||
*
|
||||
* @param callable $listener A callable that will act as a listener
|
||||
* and that must accept a single argument
|
||||
* of type \ErrorException
|
||||
*
|
||||
* @psalm-param callable(\ErrorException): void $listener
|
||||
*/
|
||||
public function addErrorHandlerListener(callable $listener): void
|
||||
{
|
||||
$this->errorListeners[] = $listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to the current error handler that will be called every
|
||||
* time a fatal error handler is captured.
|
||||
*
|
||||
* @param callable $listener A callable that will act as a listener
|
||||
* and that must accept a single argument
|
||||
* of type \Sentry\Exception\FatalErrorException
|
||||
*
|
||||
* @psalm-param callable(FatalErrorException): void $listener
|
||||
*/
|
||||
public function addFatalErrorHandlerListener(callable $listener): void
|
||||
{
|
||||
$this->fatalErrorListeners[] = $listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to the current error handler that will be called every
|
||||
* time an exception is captured.
|
||||
*
|
||||
* @param callable $listener A callable that will act as a listener
|
||||
* and that must accept a single argument
|
||||
* of type \Throwable
|
||||
*
|
||||
* @psalm-param callable(\Throwable): void $listener
|
||||
*/
|
||||
public function addExceptionHandlerListener(callable $listener): void
|
||||
{
|
||||
$this->exceptionListeners[] = $listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles errors by capturing them through the client according to the
|
||||
* configured bit field.
|
||||
*
|
||||
* @param int $level The level of the error raised, represented by
|
||||
* one of the E_* constants
|
||||
* @param string $message The error message
|
||||
* @param string $file The filename the error was raised in
|
||||
* @param int $line The line number the error was raised at
|
||||
* @param array<string, mixed>|null $errcontext The error context (deprecated since PHP 7.2)
|
||||
*
|
||||
* @return bool If the function returns `false` then the PHP native error
|
||||
* handler will be called
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function handleError(int $level, string $message, string $file, int $line, ?array $errcontext = []): bool
|
||||
{
|
||||
if (0 === error_reporting()) {
|
||||
$errorAsException = new SilencedErrorException(self::ERROR_LEVELS_DESCRIPTION[$level] . ': ' . $message, 0, $level, $file, $line);
|
||||
} else {
|
||||
$errorAsException = new \ErrorException(self::ERROR_LEVELS_DESCRIPTION[$level] . ': ' . $message, 0, $level, $file, $line);
|
||||
}
|
||||
|
||||
$backtrace = $this->cleanBacktraceFromErrorHandlerFrames($errorAsException->getTrace(), $errorAsException->getFile(), $errorAsException->getLine());
|
||||
|
||||
$this->exceptionReflection->setValue($errorAsException, $backtrace);
|
||||
|
||||
$this->invokeListeners($this->errorListeners, $errorAsException);
|
||||
|
||||
if (null !== $this->previousErrorHandler) {
|
||||
return false !== ($this->previousErrorHandler)($level, $message, $file, $line, $errcontext);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to handle a fatal error if any and relay them to the listeners.
|
||||
* It only tries to do this if we still have some reserved memory at
|
||||
* disposal. This method is used as callback of a shutdown function.
|
||||
*/
|
||||
private function handleFatalError(): void
|
||||
{
|
||||
// If there is not enough memory that can be used to handle the error
|
||||
// do nothing
|
||||
if (null === self::$reservedMemory) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::$reservedMemory = null;
|
||||
$error = error_get_last();
|
||||
|
||||
if (!empty($error) && $error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING)) {
|
||||
$errorAsException = new FatalErrorException(self::ERROR_LEVELS_DESCRIPTION[$error['type']] . ': ' . $error['message'], 0, $error['type'], $error['file'], $error['line']);
|
||||
|
||||
$this->exceptionReflection->setValue($errorAsException, []);
|
||||
|
||||
$this->invokeListeners($this->errorListeners, $errorAsException);
|
||||
$this->invokeListeners($this->fatalErrorListeners, $errorAsException);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the given exception by passing it to all the listeners,
|
||||
* then forwarding it to another handler.
|
||||
*
|
||||
* @param \Throwable $exception The exception to handle
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function handleException(\Throwable $exception): void
|
||||
{
|
||||
$this->invokeListeners($this->exceptionListeners, $exception);
|
||||
|
||||
$previousExceptionHandlerException = $exception;
|
||||
|
||||
// Unset the previous exception handler to prevent infinite loop in case
|
||||
// we need to handle an exception thrown from it
|
||||
$previousExceptionHandler = $this->previousExceptionHandler;
|
||||
$this->previousExceptionHandler = null;
|
||||
|
||||
try {
|
||||
if (null !== $previousExceptionHandler) {
|
||||
$previousExceptionHandler($exception);
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (\Throwable $previousExceptionHandlerException) {
|
||||
// This `catch` statement is here to forcefully override the
|
||||
// $previousExceptionHandlerException variable with the exception
|
||||
// we just caught
|
||||
}
|
||||
|
||||
// If the instance of the exception we're handling is the same as the one
|
||||
// caught from the previous exception handler then we give it back to the
|
||||
// native PHP handler to prevent an infinite loop
|
||||
if ($exception === $previousExceptionHandlerException) {
|
||||
// Disable the fatal error handler or the error will be reported twice
|
||||
self::$reservedMemory = null;
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$this->handleException($previousExceptionHandlerException);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans and returns the backtrace without the first frames that belong to
|
||||
* this error handler.
|
||||
*
|
||||
* @param array<int, mixed> $backtrace The backtrace to clear
|
||||
* @param string $file The filename the backtrace was raised in
|
||||
* @param int $line The line number the backtrace was raised at
|
||||
*
|
||||
* @return array<int, mixed>
|
||||
*/
|
||||
private function cleanBacktraceFromErrorHandlerFrames(array $backtrace, string $file, int $line): array
|
||||
{
|
||||
$cleanedBacktrace = $backtrace;
|
||||
$index = 0;
|
||||
|
||||
while ($index < \count($backtrace)) {
|
||||
if (isset($backtrace[$index]['file'], $backtrace[$index]['line']) && $backtrace[$index]['line'] === $line && $backtrace[$index]['file'] === $file) {
|
||||
$cleanedBacktrace = \array_slice($cleanedBacktrace, 1 + $index);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
++$index;
|
||||
}
|
||||
|
||||
return $cleanedBacktrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes all the listeners and pass the exception to all of them.
|
||||
*
|
||||
* @param callable[] $listeners The array of listeners to be called
|
||||
* @param \Throwable $throwable The exception to be passed onto listeners
|
||||
*/
|
||||
private function invokeListeners(array $listeners, \Throwable $throwable): void
|
||||
{
|
||||
foreach ($listeners as $listener) {
|
||||
try {
|
||||
$listener($throwable);
|
||||
} catch (\Throwable $exception) {
|
||||
// Do nothing as this should be as transparent as possible
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
704
vendor/sentry/sentry/src/Event.php
vendored
Normal file
704
vendor/sentry/sentry/src/Event.php
vendored
Normal file
@@ -0,0 +1,704 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
use Jean85\PrettyVersions;
|
||||
use Sentry\Context\Context;
|
||||
use Sentry\Context\RuntimeContext;
|
||||
use Sentry\Context\ServerOsContext;
|
||||
use Sentry\Context\TagsContext;
|
||||
use Sentry\Context\UserContext;
|
||||
|
||||
/**
|
||||
* This is the base class for classes containing event data.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class Event implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @var EventId The ID
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var string The date and time of when this event was generated
|
||||
*/
|
||||
private $timestamp;
|
||||
|
||||
/**
|
||||
* @var Severity The severity of this event
|
||||
*/
|
||||
private $level;
|
||||
|
||||
/**
|
||||
* @var string|null The name of the logger which created the record
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var string|null the name of the transaction (or culprit) which caused this exception
|
||||
*/
|
||||
private $transaction;
|
||||
|
||||
/**
|
||||
* @var string|null The name of the server (e.g. the host name)
|
||||
*/
|
||||
private $serverName;
|
||||
|
||||
/**
|
||||
* @var string|null The release of the program
|
||||
*/
|
||||
private $release;
|
||||
|
||||
/**
|
||||
* @var string|null The error message
|
||||
*/
|
||||
private $message;
|
||||
|
||||
/**
|
||||
* @var string|null The formatted error message
|
||||
*/
|
||||
private $messageFormatted;
|
||||
|
||||
/**
|
||||
* @var mixed[] The parameters to use to format the message
|
||||
*/
|
||||
private $messageParams = [];
|
||||
|
||||
/**
|
||||
* @var string|null The environment where this event generated (e.g. production)
|
||||
*/
|
||||
private $environment;
|
||||
|
||||
/**
|
||||
* @var array<string, string> A list of relevant modules and their versions
|
||||
*/
|
||||
private $modules = [];
|
||||
|
||||
/**
|
||||
* @var array<string, mixed> The request data
|
||||
*/
|
||||
private $request = [];
|
||||
|
||||
/**
|
||||
* @var ServerOsContext The server OS context data
|
||||
*/
|
||||
private $serverOsContext;
|
||||
|
||||
/**
|
||||
* @var RuntimeContext The runtime context data
|
||||
*/
|
||||
private $runtimeContext;
|
||||
|
||||
/**
|
||||
* @var UserContext The user context data
|
||||
*/
|
||||
private $userContext;
|
||||
|
||||
/**
|
||||
* @var array<string, array<string, mixed>> An arbitrary mapping of additional contexts associated to this event
|
||||
*/
|
||||
private $contexts = [];
|
||||
|
||||
/**
|
||||
* @var Context<mixed> An arbitrary mapping of additional metadata
|
||||
*/
|
||||
private $extraContext;
|
||||
|
||||
/**
|
||||
* @var TagsContext A List of tags associated to this event
|
||||
*/
|
||||
private $tagsContext;
|
||||
|
||||
/**
|
||||
* @var string[] An array of strings used to dictate the deduplication of this event
|
||||
*/
|
||||
private $fingerprint = [];
|
||||
|
||||
/**
|
||||
* @var Breadcrumb[] The associated breadcrumbs
|
||||
*/
|
||||
private $breadcrumbs = [];
|
||||
|
||||
/**
|
||||
* @var array<int, array<string, mixed>> The exceptions
|
||||
*
|
||||
* @psalm-var list<array{
|
||||
* type: class-string,
|
||||
* value: string,
|
||||
* stacktrace: Stacktrace
|
||||
* }>
|
||||
*/
|
||||
private $exceptions = [];
|
||||
|
||||
/**
|
||||
* @var Stacktrace|null The stacktrace that generated this event
|
||||
*/
|
||||
private $stacktrace;
|
||||
|
||||
/**
|
||||
* @var string The Sentry SDK identifier
|
||||
*/
|
||||
private $sdkIdentifier = Client::SDK_IDENTIFIER;
|
||||
|
||||
/**
|
||||
* @var string The Sentry SDK version
|
||||
*/
|
||||
private $sdkVersion;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param EventId|null $eventId The ID of the event
|
||||
*/
|
||||
public function __construct(?EventId $eventId = null)
|
||||
{
|
||||
$this->id = $eventId ?? EventId::generate();
|
||||
$this->timestamp = gmdate('Y-m-d\TH:i:s\Z');
|
||||
$this->level = Severity::error();
|
||||
$this->serverOsContext = new ServerOsContext();
|
||||
$this->runtimeContext = new RuntimeContext();
|
||||
$this->userContext = new UserContext();
|
||||
$this->extraContext = new Context();
|
||||
$this->tagsContext = new TagsContext();
|
||||
$this->sdkVersion = PrettyVersions::getVersion('sentry/sentry')->getPrettyVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the UUID of this event.
|
||||
*
|
||||
* @return string|EventId
|
||||
*/
|
||||
public function getId(bool $returnAsString = true)
|
||||
{
|
||||
if ($returnAsString) {
|
||||
@trigger_error(sprintf('Calling the method %s() and expecting it to return a string is deprecated since version 2.4 and will stop working in 3.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return (string) $this->id;
|
||||
}
|
||||
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the identifier of the SDK package that generated this event.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function getSdkIdentifier(): string
|
||||
{
|
||||
return $this->sdkIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the identifier of the SDK package that generated this event.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function setSdkIdentifier(string $sdkIdentifier): void
|
||||
{
|
||||
$this->sdkIdentifier = $sdkIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version of the SDK package that generated this Event.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function getSdkVersion(): string
|
||||
{
|
||||
return $this->sdkVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version of the SDK package that generated this Event.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function setSdkVersion(string $sdkVersion): void
|
||||
{
|
||||
$this->sdkVersion = $sdkVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the timestamp of when this event was generated.
|
||||
*/
|
||||
public function getTimestamp(): string
|
||||
{
|
||||
return $this->timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the severity of this event.
|
||||
*/
|
||||
public function getLevel(): Severity
|
||||
{
|
||||
return $this->level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the severity of this event.
|
||||
*
|
||||
* @param Severity $level The severity
|
||||
*/
|
||||
public function setLevel(Severity $level): void
|
||||
{
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the logger which created the event.
|
||||
*/
|
||||
public function getLogger(): ?string
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the logger which created the event.
|
||||
*
|
||||
* @param string|null $logger The logger name
|
||||
*/
|
||||
public function setLogger(?string $logger): void
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the transaction (or culprit) which caused this
|
||||
* exception.
|
||||
*/
|
||||
public function getTransaction(): ?string
|
||||
{
|
||||
return $this->transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the transaction (or culprit) which caused this
|
||||
* exception.
|
||||
*
|
||||
* @param string|null $transaction The transaction name
|
||||
*/
|
||||
public function setTransaction(?string $transaction): void
|
||||
{
|
||||
$this->transaction = $transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the server.
|
||||
*/
|
||||
public function getServerName(): ?string
|
||||
{
|
||||
return $this->serverName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the server.
|
||||
*
|
||||
* @param string|null $serverName The server name
|
||||
*/
|
||||
public function setServerName(?string $serverName): void
|
||||
{
|
||||
$this->serverName = $serverName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the release of the program.
|
||||
*/
|
||||
public function getRelease(): ?string
|
||||
{
|
||||
return $this->release;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the release of the program.
|
||||
*
|
||||
* @param string|null $release The release
|
||||
*/
|
||||
public function setRelease(?string $release): void
|
||||
{
|
||||
$this->release = $release;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the error message.
|
||||
*/
|
||||
public function getMessage(): ?string
|
||||
{
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the formatted message.
|
||||
*/
|
||||
public function getMessageFormatted(): ?string
|
||||
{
|
||||
return $this->messageFormatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parameters to use to format the message.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getMessageParams(): array
|
||||
{
|
||||
return $this->messageParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the error message.
|
||||
*
|
||||
* @param string $message The message
|
||||
* @param mixed[] $params The parameters to use to format the message
|
||||
* @param string|null $formatted The formatted message
|
||||
*/
|
||||
public function setMessage(string $message, array $params = [], ?string $formatted = null): void
|
||||
{
|
||||
$this->message = $message;
|
||||
$this->messageParams = $params;
|
||||
$this->messageFormatted = $formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of relevant modules and their versions.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getModules(): array
|
||||
{
|
||||
return $this->modules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a list of relevant modules and their versions.
|
||||
*
|
||||
* @param array<string, string> $modules
|
||||
*/
|
||||
public function setModules(array $modules): void
|
||||
{
|
||||
$this->modules = $modules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the request data.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getRequest(): array
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the request data.
|
||||
*
|
||||
* @param array<string, mixed> $request The request data
|
||||
*/
|
||||
public function setRequest(array $request): void
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an arbitrary mapping of additional contexts.
|
||||
*
|
||||
* @return array<string, array<string, mixed>>
|
||||
*/
|
||||
public function getContexts(): array
|
||||
{
|
||||
return $this->contexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data of the context with the given name.
|
||||
*
|
||||
* @param string $name The name that uniquely identifies the context
|
||||
* @param array<string, mixed> $data The data of the context
|
||||
*/
|
||||
public function setContext(string $name, array $data): self
|
||||
{
|
||||
$this->contexts[$name] = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an arbitrary mapping of additional metadata.
|
||||
*
|
||||
* @return Context<mixed>
|
||||
*/
|
||||
public function getExtraContext(): Context
|
||||
{
|
||||
return $this->extraContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of tags.
|
||||
*/
|
||||
public function getTagsContext(): TagsContext
|
||||
{
|
||||
return $this->tagsContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user context.
|
||||
*/
|
||||
public function getUserContext(): UserContext
|
||||
{
|
||||
return $this->userContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server OS context.
|
||||
*/
|
||||
public function getServerOsContext(): ServerOsContext
|
||||
{
|
||||
return $this->serverOsContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the runtime context data.
|
||||
*/
|
||||
public function getRuntimeContext(): RuntimeContext
|
||||
{
|
||||
return $this->runtimeContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of strings used to dictate the deduplication of this
|
||||
* event.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getFingerprint(): array
|
||||
{
|
||||
return $this->fingerprint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an array of strings used to dictate the deduplication of this
|
||||
* event.
|
||||
*
|
||||
* @param string[] $fingerprint The strings
|
||||
*/
|
||||
public function setFingerprint(array $fingerprint): void
|
||||
{
|
||||
$this->fingerprint = $fingerprint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the environment in which this event was generated.
|
||||
*/
|
||||
public function getEnvironment(): ?string
|
||||
{
|
||||
return $this->environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the environment in which this event was generated.
|
||||
*
|
||||
* @param string|null $environment The name of the environment
|
||||
*/
|
||||
public function setEnvironment(?string $environment): void
|
||||
{
|
||||
$this->environment = $environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the breadcrumbs.
|
||||
*
|
||||
* @return Breadcrumb[]
|
||||
*/
|
||||
public function getBreadcrumbs(): array
|
||||
{
|
||||
return $this->breadcrumbs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new breadcrumbs to the event.
|
||||
*
|
||||
* @param Breadcrumb[] $breadcrumbs The breadcrumb array
|
||||
*/
|
||||
public function setBreadcrumb(array $breadcrumbs): void
|
||||
{
|
||||
$this->breadcrumbs = $breadcrumbs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exception.
|
||||
*
|
||||
* @return array<int, array<string, mixed>>
|
||||
*
|
||||
* @psalm-return list<array{
|
||||
* type: class-string,
|
||||
* value: string,
|
||||
* stacktrace: Stacktrace
|
||||
* }>
|
||||
*/
|
||||
public function getExceptions(): array
|
||||
{
|
||||
return $this->exceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the exceptions.
|
||||
*
|
||||
* @param array<int, array<string, mixed>> $exceptions The exceptions
|
||||
*
|
||||
* @psalm-param list<array{
|
||||
* type: class-string,
|
||||
* value: string,
|
||||
* stacktrace: Stacktrace
|
||||
* }> $exceptions
|
||||
*/
|
||||
public function setExceptions(array $exceptions): void
|
||||
{
|
||||
$this->exceptions = $exceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stacktrace that generated this event.
|
||||
*/
|
||||
public function getStacktrace(): ?Stacktrace
|
||||
{
|
||||
return $this->stacktrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stacktrace that generated this event.
|
||||
*
|
||||
* @param Stacktrace|null $stacktrace The stacktrace instance
|
||||
*/
|
||||
public function setStacktrace(?Stacktrace $stacktrace): void
|
||||
{
|
||||
$this->stacktrace = $stacktrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the event as an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
$data = [
|
||||
'event_id' => (string) $this->id,
|
||||
'timestamp' => $this->timestamp,
|
||||
'level' => (string) $this->level,
|
||||
'platform' => 'php',
|
||||
'sdk' => [
|
||||
'name' => $this->sdkIdentifier,
|
||||
'version' => $this->getSdkVersion(),
|
||||
],
|
||||
];
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$data['logger'] = $this->logger;
|
||||
}
|
||||
|
||||
if (null !== $this->transaction) {
|
||||
$data['transaction'] = $this->transaction;
|
||||
}
|
||||
|
||||
if (null !== $this->serverName) {
|
||||
$data['server_name'] = $this->serverName;
|
||||
}
|
||||
|
||||
if (null !== $this->release) {
|
||||
$data['release'] = $this->release;
|
||||
}
|
||||
|
||||
if (null !== $this->environment) {
|
||||
$data['environment'] = $this->environment;
|
||||
}
|
||||
|
||||
if (!empty($this->fingerprint)) {
|
||||
$data['fingerprint'] = $this->fingerprint;
|
||||
}
|
||||
|
||||
if (!empty($this->modules)) {
|
||||
$data['modules'] = $this->modules;
|
||||
}
|
||||
|
||||
if (!$this->extraContext->isEmpty()) {
|
||||
$data['extra'] = $this->extraContext->toArray();
|
||||
}
|
||||
|
||||
if (!$this->tagsContext->isEmpty()) {
|
||||
$data['tags'] = $this->tagsContext->toArray();
|
||||
}
|
||||
|
||||
if (!$this->userContext->isEmpty()) {
|
||||
$data['user'] = $this->userContext->toArray();
|
||||
}
|
||||
|
||||
if (!$this->serverOsContext->isEmpty()) {
|
||||
$data['contexts']['os'] = $this->serverOsContext->toArray();
|
||||
}
|
||||
|
||||
if (!$this->runtimeContext->isEmpty()) {
|
||||
$data['contexts']['runtime'] = $this->runtimeContext->toArray();
|
||||
}
|
||||
|
||||
if (!empty($this->contexts)) {
|
||||
$data['contexts'] = array_merge($data['contexts'] ?? [], $this->contexts);
|
||||
}
|
||||
|
||||
if (!empty($this->breadcrumbs)) {
|
||||
$data['breadcrumbs']['values'] = $this->breadcrumbs;
|
||||
}
|
||||
|
||||
foreach (array_reverse($this->exceptions) as $exception) {
|
||||
$exceptionData = [
|
||||
'type' => $exception['type'],
|
||||
'value' => $exception['value'],
|
||||
];
|
||||
|
||||
if (isset($exception['stacktrace'])) {
|
||||
$exceptionData['stacktrace'] = [
|
||||
'frames' => $exception['stacktrace']->toArray(),
|
||||
];
|
||||
}
|
||||
|
||||
$data['exception']['values'][] = $exceptionData;
|
||||
}
|
||||
|
||||
if (null !== $this->stacktrace) {
|
||||
$data['stacktrace'] = [
|
||||
'frames' => $this->stacktrace->toArray(),
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($this->request)) {
|
||||
$data['request'] = $this->request;
|
||||
}
|
||||
|
||||
if (null !== $this->message) {
|
||||
if (empty($this->messageParams)) {
|
||||
$data['message'] = $this->message;
|
||||
} else {
|
||||
$data['message'] = [
|
||||
'message' => $this->message,
|
||||
'params' => $this->messageParams,
|
||||
'formatted' => $this->messageFormatted ?? vsprintf($this->message, $this->messageParams),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
}
|
||||
162
vendor/sentry/sentry/src/EventFactory.php
vendored
Normal file
162
vendor/sentry/sentry/src/EventFactory.php
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
use Sentry\Exception\EventCreationException;
|
||||
use Sentry\Serializer\RepresentationSerializerInterface;
|
||||
use Sentry\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
* Factory for the {@see Event} class.
|
||||
*/
|
||||
final class EventFactory implements EventFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @var SerializerInterface The serializer
|
||||
*/
|
||||
private $serializer;
|
||||
|
||||
/**
|
||||
* @var RepresentationSerializerInterface The representation serializer
|
||||
*/
|
||||
private $representationSerializer;
|
||||
|
||||
/**
|
||||
* @var Options The Sentry options
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @var string The Sentry SDK identifier
|
||||
*/
|
||||
private $sdkIdentifier;
|
||||
|
||||
/**
|
||||
* @var string the SDK version of the Client
|
||||
*/
|
||||
private $sdkVersion;
|
||||
|
||||
/**
|
||||
* EventFactory constructor.
|
||||
*
|
||||
* @param SerializerInterface $serializer The serializer
|
||||
* @param RepresentationSerializerInterface $representationSerializer The serializer for function arguments
|
||||
* @param Options $options The SDK configuration options
|
||||
* @param string $sdkIdentifier The Sentry SDK identifier
|
||||
* @param string $sdkVersion The Sentry SDK version
|
||||
*/
|
||||
public function __construct(SerializerInterface $serializer, RepresentationSerializerInterface $representationSerializer, Options $options, string $sdkIdentifier, string $sdkVersion)
|
||||
{
|
||||
$this->serializer = $serializer;
|
||||
$this->representationSerializer = $representationSerializer;
|
||||
$this->options = $options;
|
||||
$this->sdkIdentifier = $sdkIdentifier;
|
||||
$this->sdkVersion = $sdkVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createWithStacktrace(array $payload/*, bool $shouldReadSourceCodeExcerpts = true*/): Event
|
||||
{
|
||||
if (!isset($payload['stacktrace']) || !$payload['stacktrace'] instanceof Stacktrace) {
|
||||
$payload['stacktrace'] = Stacktrace::createFromBacktrace(
|
||||
$this->options,
|
||||
$this->serializer,
|
||||
$this->representationSerializer,
|
||||
debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS),
|
||||
__FILE__,
|
||||
__LINE__ - 6,
|
||||
\func_num_args() > 1 ? func_get_arg(1) : true
|
||||
);
|
||||
}
|
||||
|
||||
return $this->create($payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function create(array $payload/*, bool $shouldReadSourceCodeExcerpts = true*/): Event
|
||||
{
|
||||
try {
|
||||
$event = new Event();
|
||||
} catch (\Throwable $exception) {
|
||||
throw new EventCreationException($exception);
|
||||
}
|
||||
|
||||
$event->setSdkIdentifier($this->sdkIdentifier);
|
||||
$event->setSdkVersion($this->sdkVersion);
|
||||
$event->setServerName($this->options->getServerName());
|
||||
$event->setRelease($this->options->getRelease());
|
||||
$event->getTagsContext()->merge($this->options->getTags());
|
||||
$event->setEnvironment($this->options->getEnvironment());
|
||||
|
||||
if (isset($payload['logger'])) {
|
||||
$event->setLogger($payload['logger']);
|
||||
}
|
||||
|
||||
$message = isset($payload['message']) ? mb_substr($payload['message'], 0, $this->options->getMaxValueLength()) : null;
|
||||
$messageParams = $payload['message_params'] ?? [];
|
||||
$messageFormatted = isset($payload['message_formatted']) ? mb_substr($payload['message_formatted'], 0, $this->options->getMaxValueLength()) : null;
|
||||
|
||||
if (null !== $message) {
|
||||
$event->setMessage($message, $messageParams, $messageFormatted);
|
||||
}
|
||||
|
||||
if (isset($payload['exception']) && $payload['exception'] instanceof \Throwable) {
|
||||
$this->addThrowableToEvent($event, $payload['exception'], \func_num_args() > 1 ? func_get_arg(1) : true);
|
||||
}
|
||||
|
||||
if (isset($payload['level']) && $payload['level'] instanceof Severity) {
|
||||
$event->setLevel($payload['level']);
|
||||
}
|
||||
|
||||
if (isset($payload['stacktrace']) && $payload['stacktrace'] instanceof Stacktrace) {
|
||||
$event->setStacktrace($payload['stacktrace']);
|
||||
}
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the given exception in the passed event.
|
||||
*
|
||||
* @param Event $event The event that will be enriched with the
|
||||
* exception
|
||||
* @param \Throwable $exception The exception that will be processed and
|
||||
* added to the event
|
||||
* @param bool $shouldReadSourceCodeExcerpts Whether to read the source code excerpts
|
||||
* using the legacy method instead of using
|
||||
* the integration
|
||||
*/
|
||||
private function addThrowableToEvent(Event $event, \Throwable $exception, bool $shouldReadSourceCodeExcerpts): void
|
||||
{
|
||||
if ($exception instanceof \ErrorException) {
|
||||
$event->setLevel(Severity::fromError($exception->getSeverity()));
|
||||
}
|
||||
|
||||
$exceptions = [];
|
||||
$currentException = $exception;
|
||||
|
||||
do {
|
||||
$exceptions[] = [
|
||||
'type' => \get_class($currentException),
|
||||
'value' => $currentException->getMessage(),
|
||||
'stacktrace' => Stacktrace::createFromBacktrace(
|
||||
$this->options,
|
||||
$this->serializer,
|
||||
$this->representationSerializer,
|
||||
$currentException->getTrace(),
|
||||
$currentException->getFile(),
|
||||
$currentException->getLine(),
|
||||
$shouldReadSourceCodeExcerpts
|
||||
),
|
||||
];
|
||||
} while ($currentException = $currentException->getPrevious());
|
||||
|
||||
$event->setExceptions($exceptions);
|
||||
}
|
||||
}
|
||||
25
vendor/sentry/sentry/src/EventFactoryInterface.php
vendored
Normal file
25
vendor/sentry/sentry/src/EventFactoryInterface.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
/**
|
||||
* Factory for the {@see Event} class.
|
||||
*/
|
||||
interface EventFactoryInterface
|
||||
{
|
||||
/**
|
||||
* Create an {@see Event} with a stacktrace attached to it.
|
||||
*
|
||||
* @param array<string, mixed> $payload The data to be attached to the Event
|
||||
*/
|
||||
public function createWithStacktrace(array $payload): Event;
|
||||
|
||||
/**
|
||||
* Create an {@see Event} from a data payload.
|
||||
*
|
||||
* @param array<string, mixed> $payload The data to be attached to the Event
|
||||
*/
|
||||
public function create(array $payload): Event;
|
||||
}
|
||||
45
vendor/sentry/sentry/src/EventId.php
vendored
Normal file
45
vendor/sentry/sentry/src/EventId.php
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
/**
|
||||
* This class represents an event ID.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class EventId
|
||||
{
|
||||
/**
|
||||
* @var string The ID
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param string $value The ID
|
||||
*/
|
||||
public function __construct(string $value)
|
||||
{
|
||||
if (!preg_match('/^[a-f0-9]{32}$/i', $value)) {
|
||||
throw new \InvalidArgumentException('The $value argument must be a 32 characters long hexadecimal string.');
|
||||
}
|
||||
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new event ID.
|
||||
*/
|
||||
public static function generate(): self
|
||||
{
|
||||
return new self(str_replace('-', '', uuid_create(UUID_TYPE_RANDOM)));
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
22
vendor/sentry/sentry/src/Exception/EventCreationException.php
vendored
Normal file
22
vendor/sentry/sentry/src/Exception/EventCreationException.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Exception;
|
||||
|
||||
/**
|
||||
* This exception is thrown when an issue is preventing the creation of an {@see Event}.
|
||||
*/
|
||||
class EventCreationException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
/**
|
||||
* EventCreationException constructor.
|
||||
*
|
||||
* @param \Throwable $previous The original error that was thrown while
|
||||
* instantiating an {@see Event}
|
||||
*/
|
||||
public function __construct(\Throwable $previous)
|
||||
{
|
||||
parent::__construct('Unable to instantiate an event', 0, $previous);
|
||||
}
|
||||
}
|
||||
14
vendor/sentry/sentry/src/Exception/ExceptionInterface.php
vendored
Normal file
14
vendor/sentry/sentry/src/Exception/ExceptionInterface.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Exception;
|
||||
|
||||
/**
|
||||
* This interface must be implemented by all exception classes of this library.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
interface ExceptionInterface
|
||||
{
|
||||
}
|
||||
14
vendor/sentry/sentry/src/Exception/FatalErrorException.php
vendored
Normal file
14
vendor/sentry/sentry/src/Exception/FatalErrorException.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Exception;
|
||||
|
||||
/**
|
||||
* This exception is thrown when a fatal error occurs.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class FatalErrorException extends \ErrorException
|
||||
{
|
||||
}
|
||||
15
vendor/sentry/sentry/src/Exception/InvalidArgumentException.php
vendored
Normal file
15
vendor/sentry/sentry/src/Exception/InvalidArgumentException.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Exception;
|
||||
|
||||
/**
|
||||
* This class represents an exception thrown if an argument does not match with
|
||||
* the expected value.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
9
vendor/sentry/sentry/src/Exception/JsonException.php
vendored
Normal file
9
vendor/sentry/sentry/src/Exception/JsonException.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Exception;
|
||||
|
||||
final class JsonException extends \Exception
|
||||
{
|
||||
}
|
||||
23
vendor/sentry/sentry/src/Exception/MissingProjectIdCredentialException.php
vendored
Normal file
23
vendor/sentry/sentry/src/Exception/MissingProjectIdCredentialException.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Exception;
|
||||
|
||||
use Throwable;
|
||||
|
||||
@trigger_error(sprintf('The %s class is deprecated since version 2.4 and will be removed in 3.0.', MissingProjectIdCredentialException::class), E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* This exception is thrown during the sending of an event when the project ID
|
||||
* is not provided in the DSN.
|
||||
*
|
||||
* @deprecated since version 2.4, to be removed in 3.0
|
||||
*/
|
||||
final class MissingProjectIdCredentialException extends \RuntimeException
|
||||
{
|
||||
public function __construct(?Throwable $previous = null)
|
||||
{
|
||||
parent::__construct('The project ID of the DSN is required to authenticate with the Sentry server.', 0, $previous);
|
||||
}
|
||||
}
|
||||
23
vendor/sentry/sentry/src/Exception/MissingPublicKeyCredentialException.php
vendored
Normal file
23
vendor/sentry/sentry/src/Exception/MissingPublicKeyCredentialException.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Exception;
|
||||
|
||||
use Throwable;
|
||||
|
||||
@trigger_error(sprintf('The %s class is deprecated since version 2.4 and will be removed in 3.0.', MissingProjectIdCredentialException::class), E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* This exception is thrown during the sending of an event when the public key
|
||||
* is not provided in the DSN.
|
||||
*
|
||||
* @deprecated since version 2.4, to be removed in 3.0
|
||||
*/
|
||||
final class MissingPublicKeyCredentialException extends \RuntimeException
|
||||
{
|
||||
public function __construct(?Throwable $previous = null)
|
||||
{
|
||||
parent::__construct('The public key of the DSN is required to authenticate with the Sentry server.', 0, $previous);
|
||||
}
|
||||
}
|
||||
13
vendor/sentry/sentry/src/Exception/SilencedErrorException.php
vendored
Normal file
13
vendor/sentry/sentry/src/Exception/SilencedErrorException.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Exception;
|
||||
|
||||
/**
|
||||
* Error that has been captured by the {@see ErrorHandler}, but that was silenced
|
||||
* with `@` in the source code.
|
||||
*/
|
||||
final class SilencedErrorException extends \ErrorException
|
||||
{
|
||||
}
|
||||
24
vendor/sentry/sentry/src/FlushableClientInterface.php
vendored
Normal file
24
vendor/sentry/sentry/src/FlushableClientInterface.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
|
||||
/**
|
||||
* This interface can be implemented by clients to support flushing of events
|
||||
* on-demand.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
interface FlushableClientInterface extends ClientInterface
|
||||
{
|
||||
/**
|
||||
* Flushes the queue of events pending to be sent. If a timeout is provided
|
||||
* and the queue takes longer to drain, the promise resolves with `false`.
|
||||
*
|
||||
* @param int|null $timeout Maximum time in seconds the client should wait
|
||||
*/
|
||||
public function flush(?int $timeout = null): PromiseInterface;
|
||||
}
|
||||
285
vendor/sentry/sentry/src/Frame.php
vendored
Normal file
285
vendor/sentry/sentry/src/Frame.php
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
/**
|
||||
* This class represents a single frame of a stacktrace.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class Frame implements \JsonSerializable
|
||||
{
|
||||
private const INTERNAL_FRAME_FILENAME = '[internal]';
|
||||
|
||||
/**
|
||||
* @var string|null The name of the function being called
|
||||
*/
|
||||
private $functionName;
|
||||
|
||||
/**
|
||||
* @var string The file where the frame originated
|
||||
*/
|
||||
private $file;
|
||||
|
||||
/**
|
||||
* @var string The absolute path to the source file
|
||||
*/
|
||||
private $absoluteFilePath;
|
||||
|
||||
/**
|
||||
* @var int The line at which the frame originated
|
||||
*/
|
||||
private $line;
|
||||
|
||||
/**
|
||||
* @var string[] A list of source code lines before the one where the frame
|
||||
* originated
|
||||
*/
|
||||
private $preContext = [];
|
||||
|
||||
/**
|
||||
* @var string|null The source code written at the line number of the file that
|
||||
* originated this frame
|
||||
*/
|
||||
private $contextLine;
|
||||
|
||||
/**
|
||||
* @var string[] A list of source code lines after the one where the frame
|
||||
* originated
|
||||
*/
|
||||
private $postContext = [];
|
||||
|
||||
/**
|
||||
* @var bool Flag telling whether the frame is related to the execution of
|
||||
* the relevant code in this stacktrace
|
||||
*/
|
||||
private $inApp;
|
||||
|
||||
/**
|
||||
* @var array<string, mixed> A mapping of variables which were available within
|
||||
* this frame (usually context-locals)
|
||||
*/
|
||||
private $vars = [];
|
||||
|
||||
/**
|
||||
* Initializes a new instance of this class using the provided information.
|
||||
*
|
||||
* @param string|null $functionName The name of the function being called
|
||||
* @param string $file The file where the frame originated
|
||||
* @param string|null $absoluteFilePath The absolute path to the source file
|
||||
* @param int $line The line at which the frame originated
|
||||
* @param array<string, mixed> $vars A mapping of variables which were available
|
||||
* within the frame
|
||||
* @param bool $inApp Whether the frame is related to the
|
||||
* execution of code relevant to the
|
||||
* application
|
||||
*/
|
||||
public function __construct(?string $functionName, string $file, int $line, ?string $absoluteFilePath = null, array $vars = [], bool $inApp = true)
|
||||
{
|
||||
$this->functionName = $functionName;
|
||||
$this->file = $file;
|
||||
$this->absoluteFilePath = $absoluteFilePath ?? $file;
|
||||
$this->line = $line;
|
||||
$this->vars = $vars;
|
||||
$this->inApp = $inApp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the function being called.
|
||||
*/
|
||||
public function getFunctionName(): ?string
|
||||
{
|
||||
return $this->functionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file where the frame originated.
|
||||
*/
|
||||
public function getFile(): string
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the absolute path to the source file.
|
||||
*/
|
||||
public function getAbsoluteFilePath(): string
|
||||
{
|
||||
return $this->absoluteFilePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the line at which the frame originated.
|
||||
*/
|
||||
public function getLine(): int
|
||||
{
|
||||
return $this->line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of source code lines before the one where the frame originated.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPreContext(): array
|
||||
{
|
||||
return $this->preContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a list of source code lines before the one where the frame originated.
|
||||
*
|
||||
* @param string[] $preContext The source code lines
|
||||
*/
|
||||
public function setPreContext(array $preContext): void
|
||||
{
|
||||
$this->preContext = $preContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source code written at the line number of the file that originated
|
||||
* this frame.
|
||||
*/
|
||||
public function getContextLine(): ?string
|
||||
{
|
||||
return $this->contextLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source code written at the line number of the file that originated
|
||||
* this frame.
|
||||
*
|
||||
* @param string|null $contextLine The source code line
|
||||
*/
|
||||
public function setContextLine(?string $contextLine): void
|
||||
{
|
||||
$this->contextLine = $contextLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of source code lines after the one where the frame originated.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPostContext(): array
|
||||
{
|
||||
return $this->postContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a list of source code lines after the one where the frame originated.
|
||||
*
|
||||
* @param string[] $postContext The source code lines
|
||||
*/
|
||||
public function setPostContext(array $postContext): void
|
||||
{
|
||||
$this->postContext = $postContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the frame is related to the execution of the relevant code
|
||||
* in this stacktrace.
|
||||
*/
|
||||
public function isInApp(): bool
|
||||
{
|
||||
return $this->inApp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the frame is related to the execution of the relevant code
|
||||
* in this stacktrace.
|
||||
*
|
||||
* @param bool $inApp flag indicating whether the frame is application-related
|
||||
*/
|
||||
public function setIsInApp(bool $inApp): void
|
||||
{
|
||||
$this->inApp = $inApp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a mapping of variables which were available within this frame
|
||||
* (usually context-locals).
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getVars(): array
|
||||
{
|
||||
return $this->vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a mapping of variables which were available within this frame
|
||||
* (usually context-locals).
|
||||
*
|
||||
* @param array<string, mixed> $vars The variables
|
||||
*/
|
||||
public function setVars(array $vars): void
|
||||
{
|
||||
$this->vars = $vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the frame is internal.
|
||||
*/
|
||||
public function isInternal(): bool
|
||||
{
|
||||
return self::INTERNAL_FRAME_FILENAME === $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array representation of the data of this frame modeled according
|
||||
* to the specifications of the Sentry SDK Stacktrace Interface.
|
||||
*
|
||||
* @psalm-return array{
|
||||
* function: string|null,
|
||||
* filename: string,
|
||||
* lineno: int,
|
||||
* in_app: bool,
|
||||
* abs_path: string,
|
||||
* pre_context?: string[],
|
||||
* context_line?: string,
|
||||
* post_context?: string[],
|
||||
* vars?: array<string, mixed>
|
||||
* }
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
$result = [
|
||||
'function' => $this->functionName,
|
||||
'filename' => $this->file,
|
||||
'lineno' => $this->line,
|
||||
'in_app' => $this->inApp,
|
||||
'abs_path' => $this->absoluteFilePath,
|
||||
];
|
||||
|
||||
if (0 !== \count($this->preContext)) {
|
||||
$result['pre_context'] = $this->preContext;
|
||||
}
|
||||
|
||||
if (null !== $this->contextLine) {
|
||||
$result['context_line'] = $this->contextLine;
|
||||
}
|
||||
|
||||
if (0 !== \count($this->postContext)) {
|
||||
$result['post_context'] = $this->postContext;
|
||||
}
|
||||
|
||||
if (!empty($this->vars)) {
|
||||
$result['vars'] = $this->vars;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
}
|
||||
79
vendor/sentry/sentry/src/HttpClient/Authentication/SentryAuthentication.php
vendored
Normal file
79
vendor/sentry/sentry/src/HttpClient/Authentication/SentryAuthentication.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\HttpClient\Authentication;
|
||||
|
||||
use Http\Message\Authentication as AuthenticationInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Sentry\Client;
|
||||
use Sentry\Dsn;
|
||||
use Sentry\Options;
|
||||
|
||||
/**
|
||||
* This authentication method sends the requests along with a X-Sentry-Auth
|
||||
* header.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class SentryAuthentication implements AuthenticationInterface
|
||||
{
|
||||
/**
|
||||
* @var Options The Sentry client configuration
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @var string The SDK identifier
|
||||
*/
|
||||
private $sdkIdentifier;
|
||||
|
||||
/**
|
||||
* @var string The SDK version
|
||||
*/
|
||||
private $sdkVersion;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Options $options The Sentry client configuration
|
||||
* @param string $sdkIdentifier The Sentry SDK identifier in use
|
||||
* @param string $sdkVersion The Sentry SDK version in use
|
||||
*/
|
||||
public function __construct(Options $options, string $sdkIdentifier, string $sdkVersion)
|
||||
{
|
||||
$this->options = $options;
|
||||
$this->sdkIdentifier = $sdkIdentifier;
|
||||
$this->sdkVersion = $sdkVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function authenticate(RequestInterface $request): RequestInterface
|
||||
{
|
||||
$dsn = $this->options->getDsn(false);
|
||||
|
||||
if (!$dsn instanceof Dsn) {
|
||||
return $request;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'sentry_version' => Client::PROTOCOL_VERSION,
|
||||
'sentry_client' => $this->sdkIdentifier . '/' . $this->sdkVersion,
|
||||
'sentry_key' => $dsn->getPublicKey(),
|
||||
];
|
||||
|
||||
if (null !== $dsn->getSecretKey()) {
|
||||
$data['sentry_secret'] = $dsn->getSecretKey();
|
||||
}
|
||||
|
||||
$headers = [];
|
||||
|
||||
foreach ($data as $headerKey => $headerValue) {
|
||||
$headers[] = $headerKey . '=' . $headerValue;
|
||||
}
|
||||
|
||||
return $request->withHeader('X-Sentry-Auth', 'Sentry ' . implode(', ', $headers));
|
||||
}
|
||||
}
|
||||
163
vendor/sentry/sentry/src/HttpClient/HttpClientFactory.php
vendored
Normal file
163
vendor/sentry/sentry/src/HttpClient/HttpClientFactory.php
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\HttpClient;
|
||||
|
||||
use GuzzleHttp\RequestOptions as GuzzleHttpClientOptions;
|
||||
use Http\Adapter\Guzzle6\Client as GuzzleHttpClient;
|
||||
use Http\Client\Common\Plugin\AuthenticationPlugin;
|
||||
use Http\Client\Common\Plugin\DecoderPlugin;
|
||||
use Http\Client\Common\Plugin\ErrorPlugin;
|
||||
use Http\Client\Common\Plugin\HeaderSetPlugin;
|
||||
use Http\Client\Common\Plugin\RetryPlugin;
|
||||
use Http\Client\Common\PluginClient;
|
||||
use Http\Client\Curl\Client as CurlHttpClient;
|
||||
use Http\Client\HttpAsyncClient as HttpAsyncClientInterface;
|
||||
use Http\Discovery\HttpAsyncClientDiscovery;
|
||||
use Http\Message\ResponseFactory as ResponseFactoryInterface;
|
||||
use Http\Message\StreamFactory as StreamFactoryInterface;
|
||||
use Http\Message\UriFactory as UriFactoryInterface;
|
||||
use Sentry\HttpClient\Authentication\SentryAuthentication;
|
||||
use Sentry\HttpClient\Plugin\GzipEncoderPlugin;
|
||||
use Sentry\Options;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@HttpClientFactoryInterface} interface that uses
|
||||
* Httplug to autodiscover the HTTP client if none is passed by the user.
|
||||
*/
|
||||
final class HttpClientFactory implements HttpClientFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @var int The timeout of the request in seconds
|
||||
*/
|
||||
private const DEFAULT_HTTP_TIMEOUT = 5;
|
||||
|
||||
/**
|
||||
* @var int The default number of seconds to wait while trying to connect
|
||||
* to a server
|
||||
*/
|
||||
private const DEFAULT_HTTP_CONNECT_TIMEOUT = 2;
|
||||
|
||||
/**
|
||||
* @var UriFactoryInterface The PSR-7 URI factory
|
||||
*/
|
||||
private $uriFactory;
|
||||
|
||||
/**
|
||||
* @var ResponseFactoryInterface The PSR-7 response factory
|
||||
*/
|
||||
private $responseFactory;
|
||||
|
||||
/**
|
||||
* @var StreamFactoryInterface The PSR-17 stream factory
|
||||
*/
|
||||
private $streamFactory;
|
||||
|
||||
/**
|
||||
* @var HttpAsyncClientInterface|null The HTTP client
|
||||
*/
|
||||
private $httpClient;
|
||||
|
||||
/**
|
||||
* @var string The name of the SDK
|
||||
*/
|
||||
private $sdkIdentifier;
|
||||
|
||||
/**
|
||||
* @var string The version of the SDK
|
||||
*/
|
||||
private $sdkVersion;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param UriFactoryInterface $uriFactory The PSR-7 URI factory
|
||||
* @param ResponseFactoryInterface $responseFactory The PSR-7 response factory
|
||||
* @param StreamFactoryInterface $streamFactory The PSR-17 stream factory
|
||||
* @param HttpAsyncClientInterface|null $httpClient The HTTP client
|
||||
* @param string $sdkIdentifier The SDK identifier
|
||||
* @param string $sdkVersion The SDK version
|
||||
*/
|
||||
public function __construct(
|
||||
UriFactoryInterface $uriFactory,
|
||||
ResponseFactoryInterface $responseFactory,
|
||||
StreamFactoryInterface $streamFactory,
|
||||
?HttpAsyncClientInterface $httpClient,
|
||||
string $sdkIdentifier,
|
||||
string $sdkVersion
|
||||
) {
|
||||
$this->uriFactory = $uriFactory;
|
||||
$this->responseFactory = $responseFactory;
|
||||
$this->streamFactory = $streamFactory;
|
||||
$this->httpClient = $httpClient;
|
||||
$this->sdkIdentifier = $sdkIdentifier;
|
||||
$this->sdkVersion = $sdkVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function create(Options $options): HttpAsyncClientInterface
|
||||
{
|
||||
if (null === $options->getDsn(false)) {
|
||||
throw new \RuntimeException('Cannot create an HTTP client without the Sentry DSN set in the options.');
|
||||
}
|
||||
|
||||
$httpClient = $this->httpClient;
|
||||
|
||||
if (null !== $httpClient && null !== $options->getHttpProxy()) {
|
||||
throw new \RuntimeException('The "http_proxy" option does not work together with a custom HTTP client.');
|
||||
}
|
||||
|
||||
if (null === $httpClient) {
|
||||
if (class_exists(GuzzleHttpClient::class)) {
|
||||
/** @psalm-suppress UndefinedClass */
|
||||
$guzzleConfig = [
|
||||
GuzzleHttpClientOptions::TIMEOUT => self::DEFAULT_HTTP_TIMEOUT,
|
||||
GuzzleHttpClientOptions::CONNECT_TIMEOUT => self::DEFAULT_HTTP_CONNECT_TIMEOUT,
|
||||
];
|
||||
|
||||
if (null !== $options->getHttpProxy()) {
|
||||
/** @psalm-suppress UndefinedClass */
|
||||
$guzzleConfig[GuzzleHttpClientOptions::PROXY] = $options->getHttpProxy();
|
||||
}
|
||||
|
||||
/** @psalm-suppress InvalidPropertyAssignmentValue */
|
||||
$httpClient = GuzzleHttpClient::createWithConfig($guzzleConfig);
|
||||
} elseif (class_exists(CurlHttpClient::class)) {
|
||||
$curlConfig = [
|
||||
CURLOPT_TIMEOUT => self::DEFAULT_HTTP_TIMEOUT,
|
||||
CURLOPT_CONNECTTIMEOUT => self::DEFAULT_HTTP_CONNECT_TIMEOUT,
|
||||
];
|
||||
|
||||
if (null !== $options->getHttpProxy()) {
|
||||
$curlConfig[CURLOPT_PROXY] = $options->getHttpProxy();
|
||||
}
|
||||
|
||||
/** @psalm-suppress InvalidPropertyAssignmentValue */
|
||||
$httpClient = new CurlHttpClient(null, null, $curlConfig);
|
||||
} elseif (null !== $options->getHttpProxy()) {
|
||||
throw new \RuntimeException('The "http_proxy" option requires either the "php-http/curl-client" or the "php-http/guzzle6-adapter" package to be installed.');
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $httpClient) {
|
||||
$httpClient = HttpAsyncClientDiscovery::find();
|
||||
}
|
||||
|
||||
$httpClientPlugins = [
|
||||
new HeaderSetPlugin(['User-Agent' => $this->sdkIdentifier . '/' . $this->sdkVersion]),
|
||||
new AuthenticationPlugin(new SentryAuthentication($options, $this->sdkIdentifier, $this->sdkVersion)),
|
||||
new RetryPlugin(['retries' => $options->getSendAttempts()]),
|
||||
new ErrorPlugin(),
|
||||
];
|
||||
|
||||
if ($options->isCompressionEnabled()) {
|
||||
$httpClientPlugins[] = new GzipEncoderPlugin($this->streamFactory);
|
||||
$httpClientPlugins[] = new DecoderPlugin();
|
||||
}
|
||||
|
||||
return new PluginClient($httpClient, $httpClientPlugins);
|
||||
}
|
||||
}
|
||||
22
vendor/sentry/sentry/src/HttpClient/HttpClientFactoryInterface.php
vendored
Normal file
22
vendor/sentry/sentry/src/HttpClient/HttpClientFactoryInterface.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\HttpClient;
|
||||
|
||||
use Http\Client\HttpAsyncClient as HttpAsyncClientInterface;
|
||||
use Sentry\Options;
|
||||
|
||||
/**
|
||||
* This interface defines a contract for classes willing to serve as factories
|
||||
* for the HTTP client.
|
||||
*/
|
||||
interface HttpClientFactoryInterface
|
||||
{
|
||||
/**
|
||||
* Create HTTP Client wrapped with configured plugins.
|
||||
*
|
||||
* @param Options $options The client options
|
||||
*/
|
||||
public function create(Options $options): HttpAsyncClientInterface;
|
||||
}
|
||||
54
vendor/sentry/sentry/src/HttpClient/PluggableHttpClientFactory.php
vendored
Normal file
54
vendor/sentry/sentry/src/HttpClient/PluggableHttpClientFactory.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\HttpClient;
|
||||
|
||||
use Http\Client\Common\Plugin as HttpClientPluginInterface;
|
||||
use Http\Client\Common\PluginClient;
|
||||
use Http\Client\HttpAsyncClient as HttpAsyncClientInterface;
|
||||
use Sentry\Options;
|
||||
|
||||
/**
|
||||
* This factory can be used to decorate an HTTP client with a list of plugins.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*
|
||||
* @deprecated since version 2.3, to be removed in 3.0
|
||||
*/
|
||||
final class PluggableHttpClientFactory implements HttpClientFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @var HttpClientFactoryInterface The HTTP factory being decorated
|
||||
*/
|
||||
private $decoratedHttpClientFactory;
|
||||
|
||||
/**
|
||||
* @var HttpClientPluginInterface[] The list of plugins to add to the HTTP client
|
||||
*/
|
||||
private $httpClientPlugins;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param HttpClientFactoryInterface $decoratedHttpClientFactory The HTTP factory being decorated
|
||||
* @param HttpClientPluginInterface[] $httpClientPlugins The list of plugins to add to the HTTP client
|
||||
*/
|
||||
public function __construct(HttpClientFactoryInterface $decoratedHttpClientFactory, array $httpClientPlugins)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since version 2.3 and will be removed in 3.0.', self::class), E_USER_DEPRECATED);
|
||||
|
||||
$this->decoratedHttpClientFactory = $decoratedHttpClientFactory;
|
||||
$this->httpClientPlugins = $httpClientPlugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function create(Options $options): HttpAsyncClientInterface
|
||||
{
|
||||
$httpClient = $this->decoratedHttpClientFactory->create($options);
|
||||
|
||||
return new PluginClient($httpClient, $this->httpClientPlugins);
|
||||
}
|
||||
}
|
||||
72
vendor/sentry/sentry/src/HttpClient/Plugin/GzipEncoderPlugin.php
vendored
Normal file
72
vendor/sentry/sentry/src/HttpClient/Plugin/GzipEncoderPlugin.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\HttpClient\Plugin;
|
||||
|
||||
use Http\Client\Common\Plugin as PluginInterface;
|
||||
use Http\Discovery\StreamFactoryDiscovery;
|
||||
use Http\Message\StreamFactory as HttplugStreamFactoryInterface;
|
||||
use Http\Promise\Promise as PromiseInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\StreamFactoryInterface;
|
||||
|
||||
/**
|
||||
* This plugin encodes the request body by compressing it with Gzip.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class GzipEncoderPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @var HttplugStreamFactoryInterface|StreamFactoryInterface The PSR-17 stream factory
|
||||
*/
|
||||
private $streamFactory;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param HttplugStreamFactoryInterface|StreamFactoryInterface|null $streamFactory The stream factory
|
||||
*
|
||||
* @throws \RuntimeException If the zlib extension is not enabled
|
||||
*/
|
||||
public function __construct($streamFactory = null)
|
||||
{
|
||||
if (!\extension_loaded('zlib')) {
|
||||
throw new \RuntimeException('The "zlib" extension must be enabled to use this plugin.');
|
||||
}
|
||||
|
||||
if (null === $streamFactory) {
|
||||
@trigger_error(sprintf('A PSR-17 stream factory is needed as argument of the constructor of the "%s" class since version 2.1.3 and will be required in 3.0.', self::class), E_USER_DEPRECATED);
|
||||
} elseif (!$streamFactory instanceof HttplugStreamFactoryInterface && !$streamFactory instanceof StreamFactoryInterface) {
|
||||
throw new \InvalidArgumentException(sprintf('The $streamFactory argument must be an instance of either the "%s" or the "%s" interface.', HttplugStreamFactoryInterface::class, StreamFactoryInterface::class));
|
||||
}
|
||||
|
||||
$this->streamFactory = $streamFactory ?? StreamFactoryDiscovery::find();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function handleRequest(RequestInterface $request, callable $next, callable $first): PromiseInterface
|
||||
{
|
||||
$requestBody = $request->getBody();
|
||||
|
||||
if ($requestBody->isSeekable()) {
|
||||
$requestBody->rewind();
|
||||
}
|
||||
|
||||
// Instead of using a stream filter we have to compress the whole request
|
||||
// body in one go to work around a PHP bug. See https://github.com/getsentry/sentry-php/pull/877
|
||||
$encodedBody = gzcompress($requestBody->getContents(), -1, ZLIB_ENCODING_GZIP);
|
||||
|
||||
if (false === $encodedBody) {
|
||||
throw new \RuntimeException('Failed to GZIP-encode the request body.');
|
||||
}
|
||||
|
||||
$request = $request->withHeader('Content-Encoding', 'gzip');
|
||||
$request = $request->withBody($this->streamFactory->createStream($encodedBody));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
84
vendor/sentry/sentry/src/Integration/ErrorListenerIntegration.php
vendored
Normal file
84
vendor/sentry/sentry/src/Integration/ErrorListenerIntegration.php
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Integration;
|
||||
|
||||
use Sentry\ErrorHandler;
|
||||
use Sentry\Exception\FatalErrorException;
|
||||
use Sentry\Exception\SilencedErrorException;
|
||||
use Sentry\Options;
|
||||
use Sentry\SentrySdk;
|
||||
|
||||
/**
|
||||
* This integration hooks into the global error handlers and emits events to
|
||||
* Sentry.
|
||||
*/
|
||||
final class ErrorListenerIntegration implements IntegrationInterface
|
||||
{
|
||||
/**
|
||||
* @var Options|null The options, to know which error level to use
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @var bool Whether to handle fatal errors or not
|
||||
*/
|
||||
private $handleFatalErrors;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Options|null $options The options to be used with this integration
|
||||
* @param bool $handleFatalErrors Whether to handle fatal errors or not
|
||||
*/
|
||||
public function __construct(?Options $options = null, bool $handleFatalErrors = true)
|
||||
{
|
||||
if (null !== $options) {
|
||||
@trigger_error(sprintf('Passing the options as argument of the constructor of the "%s" class is deprecated since version 2.1 and will not work in 3.0.', self::class), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if ($handleFatalErrors) {
|
||||
@trigger_error(sprintf('Handling fatal errors with the "%s" class is deprecated since version 2.1. Use the "%s" integration instead.', self::class, FatalErrorListenerIntegration::class), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->options = $options;
|
||||
$this->handleFatalErrors = $handleFatalErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setupOnce(): void
|
||||
{
|
||||
/** @psalm-suppress DeprecatedMethod */
|
||||
$errorHandler = ErrorHandler::registerOnce(ErrorHandler::DEFAULT_RESERVED_MEMORY_SIZE, false);
|
||||
$errorHandler->addErrorHandlerListener(function (\ErrorException $exception): void {
|
||||
if (!$this->handleFatalErrors && $exception instanceof FatalErrorException) {
|
||||
return;
|
||||
}
|
||||
|
||||
$currentHub = SentrySdk::getCurrentHub();
|
||||
$integration = $currentHub->getIntegration(self::class);
|
||||
$client = $currentHub->getClient();
|
||||
|
||||
// The client bound to the current hub, if any, could not have this
|
||||
// integration enabled. If this is the case, bail out
|
||||
if (null === $integration || null === $client) {
|
||||
return;
|
||||
}
|
||||
|
||||
$options = $this->options ?? $client->getOptions();
|
||||
|
||||
if ($exception instanceof SilencedErrorException && !$options->shouldCaptureSilencedErrors()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!($options->getErrorTypes() & $exception->getSeverity())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$currentHub->captureException($exception);
|
||||
});
|
||||
}
|
||||
}
|
||||
36
vendor/sentry/sentry/src/Integration/ExceptionListenerIntegration.php
vendored
Normal file
36
vendor/sentry/sentry/src/Integration/ExceptionListenerIntegration.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Integration;
|
||||
|
||||
use Sentry\ErrorHandler;
|
||||
use Sentry\SentrySdk;
|
||||
|
||||
/**
|
||||
* This integration hooks into the global error handlers and emits events to
|
||||
* Sentry.
|
||||
*/
|
||||
final class ExceptionListenerIntegration implements IntegrationInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setupOnce(): void
|
||||
{
|
||||
/** @psalm-suppress DeprecatedMethod */
|
||||
$errorHandler = ErrorHandler::registerOnce(ErrorHandler::DEFAULT_RESERVED_MEMORY_SIZE, false);
|
||||
$errorHandler->addExceptionHandlerListener(static function (\Throwable $exception): void {
|
||||
$currentHub = SentrySdk::getCurrentHub();
|
||||
$integration = $currentHub->getIntegration(self::class);
|
||||
|
||||
// The client bound to the current hub, if any, could not have this
|
||||
// integration enabled. If this is the case, bail out
|
||||
if (null === $integration) {
|
||||
return;
|
||||
}
|
||||
|
||||
$currentHub->captureException($exception);
|
||||
});
|
||||
}
|
||||
}
|
||||
64
vendor/sentry/sentry/src/Integration/FatalErrorListenerIntegration.php
vendored
Normal file
64
vendor/sentry/sentry/src/Integration/FatalErrorListenerIntegration.php
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Integration;
|
||||
|
||||
use Sentry\ErrorHandler;
|
||||
use Sentry\Exception\FatalErrorException;
|
||||
use Sentry\Options;
|
||||
use Sentry\SentrySdk;
|
||||
|
||||
/**
|
||||
* This integration hooks into the error handler and captures fatal errors.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class FatalErrorListenerIntegration implements IntegrationInterface
|
||||
{
|
||||
/**
|
||||
* @var Options|null The options, to know which error level to use
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Options|null $options The options to be used with this integration
|
||||
*/
|
||||
public function __construct(?Options $options = null)
|
||||
{
|
||||
if (null !== $options) {
|
||||
@trigger_error(sprintf('Passing the options as argument of the constructor of the "%s" class is deprecated since version 2.1 and will not work in 3.0.', self::class), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setupOnce(): void
|
||||
{
|
||||
$errorHandler = ErrorHandler::registerOnceFatalErrorHandler();
|
||||
$errorHandler->addFatalErrorHandlerListener(function (FatalErrorException $exception): void {
|
||||
$currentHub = SentrySdk::getCurrentHub();
|
||||
$integration = $currentHub->getIntegration(self::class);
|
||||
$client = $currentHub->getClient();
|
||||
|
||||
// The client bound to the current hub, if any, could not have this
|
||||
// integration enabled. If this is the case, bail out
|
||||
if (null === $integration || null === $client) {
|
||||
return;
|
||||
}
|
||||
|
||||
$options = $this->options ?? $client->getOptions();
|
||||
|
||||
if (!($options->getErrorTypes() & $exception->getSeverity())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$currentHub->captureException($exception);
|
||||
});
|
||||
}
|
||||
}
|
||||
152
vendor/sentry/sentry/src/Integration/FrameContextifierIntegration.php
vendored
Normal file
152
vendor/sentry/sentry/src/Integration/FrameContextifierIntegration.php
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Integration;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Sentry\Event;
|
||||
use Sentry\SentrySdk;
|
||||
use Sentry\Stacktrace;
|
||||
use Sentry\State\Scope;
|
||||
|
||||
/**
|
||||
* This integration reads excerpts of code around the line that originated an
|
||||
* error.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class FrameContextifierIntegration implements IntegrationInterface
|
||||
{
|
||||
/**
|
||||
* @var LoggerInterface A PSR-3 logger
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* Creates a new instance of this integration.
|
||||
*
|
||||
* @param LoggerInterface $logger A PSR-3 logger
|
||||
*/
|
||||
public function __construct(?LoggerInterface $logger = null)
|
||||
{
|
||||
$this->logger = $logger ?? new NullLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setupOnce(): void
|
||||
{
|
||||
Scope::addGlobalEventProcessor(static function (Event $event): Event {
|
||||
$client = SentrySdk::getCurrentHub()->getClient();
|
||||
|
||||
if (null === $client) {
|
||||
return $event;
|
||||
}
|
||||
|
||||
$maxContextLines = $client->getOptions()->getContextLines();
|
||||
$integration = $client->getIntegration(self::class);
|
||||
|
||||
if (null === $integration || null === $maxContextLines) {
|
||||
return $event;
|
||||
}
|
||||
|
||||
$stacktrace = $event->getStacktrace();
|
||||
|
||||
if (null !== $stacktrace) {
|
||||
$integration->addContextToStacktraceFrames($maxContextLines, $stacktrace);
|
||||
}
|
||||
|
||||
foreach ($event->getExceptions() as $exception) {
|
||||
if (!isset($exception['stacktrace'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$integration->addContextToStacktraceFrames($maxContextLines, $exception['stacktrace']);
|
||||
}
|
||||
|
||||
return $event;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Contextifies the frames of the given stacktrace.
|
||||
*
|
||||
* @param int $maxContextLines The maximum number of lines of code to read
|
||||
* @param Stacktrace $stacktrace The stacktrace object
|
||||
*/
|
||||
private function addContextToStacktraceFrames(int $maxContextLines, Stacktrace $stacktrace): void
|
||||
{
|
||||
foreach ($stacktrace->getFrames() as $frame) {
|
||||
if ($frame->isInternal()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sourceCodeExcerpt = $this->getSourceCodeExcerpt($maxContextLines, $frame->getAbsoluteFilePath(), $frame->getLine());
|
||||
|
||||
$frame->setPreContext($sourceCodeExcerpt['pre_context']);
|
||||
$frame->setContextLine($sourceCodeExcerpt['context_line']);
|
||||
$frame->setPostContext($sourceCodeExcerpt['post_context']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an excerpt of the source code around a given line.
|
||||
*
|
||||
* @param int $maxContextLines The maximum number of lines of code to read
|
||||
* @param string $filePath The file path
|
||||
* @param int $lineNumber The line to centre about
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*
|
||||
* @psalm-return array{
|
||||
* pre_context: string[],
|
||||
* context_line: string|null,
|
||||
* post_context: string[]
|
||||
* }
|
||||
*/
|
||||
private function getSourceCodeExcerpt(int $maxContextLines, string $filePath, int $lineNumber): array
|
||||
{
|
||||
$frame = [
|
||||
'pre_context' => [],
|
||||
'context_line' => null,
|
||||
'post_context' => [],
|
||||
];
|
||||
|
||||
$target = max(0, ($lineNumber - ($maxContextLines + 1)));
|
||||
$currentLineNumber = $target + 1;
|
||||
|
||||
try {
|
||||
$file = new \SplFileObject($filePath);
|
||||
$file->seek($target);
|
||||
|
||||
while (!$file->eof()) {
|
||||
/** @var string $line */
|
||||
$line = $file->current();
|
||||
$line = rtrim($line, "\r\n");
|
||||
|
||||
if ($currentLineNumber === $lineNumber) {
|
||||
$frame['context_line'] = $line;
|
||||
} elseif ($currentLineNumber < $lineNumber) {
|
||||
$frame['pre_context'][] = $line;
|
||||
} elseif ($currentLineNumber > $lineNumber) {
|
||||
$frame['post_context'][] = $line;
|
||||
}
|
||||
|
||||
++$currentLineNumber;
|
||||
|
||||
if ($currentLineNumber > $lineNumber + $maxContextLines) {
|
||||
break;
|
||||
}
|
||||
|
||||
$file->next();
|
||||
}
|
||||
} catch (\Throwable $exception) {
|
||||
$this->logger->warning(sprintf('Failed to get the source code excerpt for the file "%s".', $filePath));
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
}
|
||||
53
vendor/sentry/sentry/src/Integration/Handler.php
vendored
Normal file
53
vendor/sentry/sentry/src/Integration/Handler.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Integration;
|
||||
|
||||
/**
|
||||
* This class handles the state of already installed integrations.
|
||||
* It makes sure to call {@link IntegrationInterface::setupOnce} only once per integration.
|
||||
*
|
||||
* @internal since version 2.4
|
||||
*/
|
||||
final class Handler
|
||||
{
|
||||
/**
|
||||
* @var array<string, bool> The registered integrations
|
||||
*/
|
||||
private static $integrations = [];
|
||||
|
||||
/**
|
||||
* Calls {@link IntegrationInterface::setupOnce} for all passed integrations
|
||||
* if it hasn't been called yet.
|
||||
*
|
||||
* @param IntegrationInterface[] $integrations The integrations
|
||||
*
|
||||
* @return array<string, IntegrationInterface>
|
||||
*
|
||||
* @psalm-return array<class-string<IntegrationInterface>, IntegrationInterface>
|
||||
*/
|
||||
public static function setupIntegrations(array $integrations): array
|
||||
{
|
||||
$integrationIndex = [];
|
||||
|
||||
/* @var IntegrationInterface $integration */
|
||||
foreach ($integrations as $integration) {
|
||||
$className = \get_class($integration);
|
||||
|
||||
if (!$integration instanceof IntegrationInterface) {
|
||||
throw new \InvalidArgumentException(sprintf('Expecting integration implementing %s interface, got %s', IntegrationInterface::class, $className));
|
||||
}
|
||||
|
||||
if (!isset(self::$integrations[$className])) {
|
||||
self::$integrations[$className] = true;
|
||||
|
||||
$integration->setupOnce();
|
||||
}
|
||||
|
||||
$integrationIndex[$className] = $integration;
|
||||
}
|
||||
|
||||
return $integrationIndex;
|
||||
}
|
||||
}
|
||||
102
vendor/sentry/sentry/src/Integration/IgnoreErrorsIntegration.php
vendored
Normal file
102
vendor/sentry/sentry/src/Integration/IgnoreErrorsIntegration.php
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Integration;
|
||||
|
||||
use Sentry\Event;
|
||||
use Sentry\SentrySdk;
|
||||
use Sentry\State\Scope;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* This integration decides whether an event should not be captured according
|
||||
* to a series of options that must match with its data.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class IgnoreErrorsIntegration implements IntegrationInterface
|
||||
{
|
||||
/**
|
||||
* @var array<string, mixed> The options
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* Creates a new instance of this integration and configures it with the
|
||||
* given options.
|
||||
*
|
||||
* @param array<string, mixed> $options The options
|
||||
*
|
||||
* @psalm-param array{
|
||||
* ignore_exceptions?: bool
|
||||
* } $options
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$resolver = new OptionsResolver();
|
||||
$resolver->setDefaults([
|
||||
'ignore_exceptions' => [],
|
||||
]);
|
||||
|
||||
$resolver->setAllowedTypes('ignore_exceptions', ['array']);
|
||||
|
||||
$this->options = $resolver->resolve($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setupOnce(): void
|
||||
{
|
||||
Scope::addGlobalEventProcessor(static function (Event $event): ?Event {
|
||||
$integration = SentrySdk::getCurrentHub()->getIntegration(self::class);
|
||||
|
||||
if (null !== $integration && $integration->shouldDropEvent($event, $integration->options)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $event;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given event should be dropped according to the options
|
||||
* that configures the current instance of this integration.
|
||||
*
|
||||
* @param Event $event The event to check
|
||||
* @param array<string, mixed> $options The options of the integration
|
||||
*/
|
||||
private function shouldDropEvent(Event $event, array $options): bool
|
||||
{
|
||||
if ($this->isIgnoredException($event, $options)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given event should be dropped or not according to the
|
||||
* criteria defined in the integration's options.
|
||||
*
|
||||
* @param Event $event The event instance
|
||||
* @param array<string, mixed> $options The options of the integration
|
||||
*/
|
||||
private function isIgnoredException(Event $event, array $options): bool
|
||||
{
|
||||
$exceptions = $event->getExceptions();
|
||||
|
||||
if (empty($exceptions) || !isset($exceptions[0]['type'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($options['ignore_exceptions'] as $ignoredException) {
|
||||
if (is_a($exceptions[0]['type'], $ignoredException, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
17
vendor/sentry/sentry/src/Integration/IntegrationInterface.php
vendored
Normal file
17
vendor/sentry/sentry/src/Integration/IntegrationInterface.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Integration;
|
||||
|
||||
/**
|
||||
* This interface defines a contract that must be implemented by integrations,
|
||||
* bindings or hooks that integrate certain frameworks or environments with the SDK.
|
||||
*/
|
||||
interface IntegrationInterface
|
||||
{
|
||||
/**
|
||||
* Initializes the current integration by registering it once.
|
||||
*/
|
||||
public function setupOnce(): void;
|
||||
}
|
||||
73
vendor/sentry/sentry/src/Integration/ModulesIntegration.php
vendored
Normal file
73
vendor/sentry/sentry/src/Integration/ModulesIntegration.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Integration;
|
||||
|
||||
use Jean85\PrettyVersions;
|
||||
use PackageVersions\Versions;
|
||||
use Sentry\Event;
|
||||
use Sentry\SentrySdk;
|
||||
use Sentry\State\Scope;
|
||||
|
||||
/**
|
||||
* This integration logs with the event details all the versions of the packages
|
||||
* installed with Composer; the root project is included too.
|
||||
*/
|
||||
final class ModulesIntegration implements IntegrationInterface
|
||||
{
|
||||
/**
|
||||
* @var array<string, string> The list of installed vendors
|
||||
*/
|
||||
private static $loadedModules = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setupOnce(): void
|
||||
{
|
||||
Scope::addGlobalEventProcessor(static function (Event $event): Event {
|
||||
$integration = SentrySdk::getCurrentHub()->getIntegration(self::class);
|
||||
|
||||
// The integration could be bound to a client that is not the one
|
||||
// attached to the current hub. If this is the case, bail out
|
||||
if (null !== $integration) {
|
||||
$integration->processEvent($event);
|
||||
}
|
||||
|
||||
return $event;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the information gathered by this integration to the event.
|
||||
*
|
||||
* @param self $self The instance of this integration
|
||||
* @param Event $event The event that will be enriched with the modules
|
||||
*
|
||||
* @deprecated since version 2.4, to be removed in 3.0
|
||||
*/
|
||||
public static function applyToEvent(self $self, Event $event): void
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated since version 2.4 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$self->processEvent($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gathers information about the versions of the installed dependencies of
|
||||
* the application and sets them on the event.
|
||||
*
|
||||
* @param Event $event The event
|
||||
*/
|
||||
private function processEvent(Event $event): void
|
||||
{
|
||||
if (empty(self::$loadedModules)) {
|
||||
foreach (Versions::VERSIONS as $package => $rawVersion) {
|
||||
self::$loadedModules[$package] = PrettyVersions::getVersion($package)->getPrettyVersion();
|
||||
}
|
||||
}
|
||||
|
||||
$event->setModules(self::$loadedModules);
|
||||
}
|
||||
}
|
||||
27
vendor/sentry/sentry/src/Integration/RequestFetcher.php
vendored
Normal file
27
vendor/sentry/sentry/src/Integration/RequestFetcher.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Integration;
|
||||
|
||||
use GuzzleHttp\Psr7\ServerRequest;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
/**
|
||||
* Default implementation for RequestFetcherInterface. Creates a request object
|
||||
* from the PHP superglobals.
|
||||
*/
|
||||
final class RequestFetcher implements RequestFetcherInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fetchRequest(): ?ServerRequestInterface
|
||||
{
|
||||
if (!isset($_SERVER['REQUEST_METHOD']) || \PHP_SAPI === 'cli') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ServerRequest::fromGlobals();
|
||||
}
|
||||
}
|
||||
19
vendor/sentry/sentry/src/Integration/RequestFetcherInterface.php
vendored
Normal file
19
vendor/sentry/sentry/src/Integration/RequestFetcherInterface.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Integration;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
/**
|
||||
* Allows customizing the request information that is attached to the logged event.
|
||||
* An implementation of this interface can be passed to RequestIntegration.
|
||||
*/
|
||||
interface RequestFetcherInterface
|
||||
{
|
||||
/**
|
||||
* Returns the PSR-7 request object that will be attached to the logged event.
|
||||
*/
|
||||
public function fetchRequest(): ?ServerRequestInterface;
|
||||
}
|
||||
246
vendor/sentry/sentry/src/Integration/RequestIntegration.php
vendored
Normal file
246
vendor/sentry/sentry/src/Integration/RequestIntegration.php
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Integration;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use Sentry\Event;
|
||||
use Sentry\Exception\JsonException;
|
||||
use Sentry\Options;
|
||||
use Sentry\SentrySdk;
|
||||
use Sentry\State\Scope;
|
||||
use Sentry\Util\JSON;
|
||||
|
||||
/**
|
||||
* This integration collects information from the request and attaches them to
|
||||
* the event.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class RequestIntegration implements IntegrationInterface
|
||||
{
|
||||
/**
|
||||
* This constant represents the size limit in bytes beyond which the body
|
||||
* of the request is not captured when the `max_request_body_size` option
|
||||
* is set to `small`.
|
||||
*/
|
||||
private const REQUEST_BODY_SMALL_MAX_CONTENT_LENGTH = 10 ** 3;
|
||||
|
||||
/**
|
||||
* This constant represents the size limit in bytes beyond which the body
|
||||
* of the request is not captured when the `max_request_body_size` option
|
||||
* is set to `medium`.
|
||||
*/
|
||||
private const REQUEST_BODY_MEDIUM_MAX_CONTENT_LENGTH = 10 ** 4;
|
||||
|
||||
/**
|
||||
* @var Options|null The client options
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @var RequestFetcherInterface PSR-7 request fetcher
|
||||
*/
|
||||
private $requestFetcher;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Options|null $options The client options
|
||||
* @param RequestFetcherInterface|null $requestFetcher PSR-7 request fetcher
|
||||
*/
|
||||
public function __construct(?Options $options = null, ?RequestFetcherInterface $requestFetcher = null)
|
||||
{
|
||||
if (null !== $options) {
|
||||
@trigger_error(sprintf('Passing the options as argument of the constructor of the "%s" class is deprecated since version 2.1 and will not work in 3.0.', self::class), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->options = $options;
|
||||
$this->requestFetcher = $requestFetcher ?? new RequestFetcher();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setupOnce(): void
|
||||
{
|
||||
Scope::addGlobalEventProcessor(function (Event $event): Event {
|
||||
$currentHub = SentrySdk::getCurrentHub();
|
||||
$integration = $currentHub->getIntegration(self::class);
|
||||
$client = $currentHub->getClient();
|
||||
|
||||
// The client bound to the current hub, if any, could not have this
|
||||
// integration enabled. If this is the case, bail out
|
||||
if (null === $integration || null === $client) {
|
||||
return $event;
|
||||
}
|
||||
|
||||
$this->processEvent($event, $this->options ?? $client->getOptions());
|
||||
|
||||
return $event;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the information gathered by the this integration to the event.
|
||||
*
|
||||
* @param self $self The current instance of the integration
|
||||
* @param Event $event The event that will be enriched with a request
|
||||
* @param ServerRequestInterface|null $request The Request that will be processed and added to the event
|
||||
*
|
||||
* @deprecated since version 2.1, to be removed in 3.0
|
||||
*/
|
||||
public static function applyToEvent(self $self, Event $event, ?ServerRequestInterface $request = null): void
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated since version 2.1 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
if (null === $self->options) {
|
||||
throw new \BadMethodCallException('The options of the integration must be set.');
|
||||
}
|
||||
|
||||
$self->processEvent($event, $self->options, $request);
|
||||
}
|
||||
|
||||
private function processEvent(Event $event, Options $options, ?ServerRequestInterface $request = null): void
|
||||
{
|
||||
if (null === $request) {
|
||||
$request = $this->requestFetcher->fetchRequest();
|
||||
}
|
||||
|
||||
if (null === $request) {
|
||||
return;
|
||||
}
|
||||
|
||||
$requestData = [
|
||||
'url' => (string) $request->getUri(),
|
||||
'method' => $request->getMethod(),
|
||||
];
|
||||
|
||||
if ($request->getUri()->getQuery()) {
|
||||
$requestData['query_string'] = $request->getUri()->getQuery();
|
||||
}
|
||||
|
||||
if ($options->shouldSendDefaultPii()) {
|
||||
$serverParams = $request->getServerParams();
|
||||
|
||||
if (isset($serverParams['REMOTE_ADDR'])) {
|
||||
$requestData['env']['REMOTE_ADDR'] = $serverParams['REMOTE_ADDR'];
|
||||
}
|
||||
|
||||
$requestData['cookies'] = $request->getCookieParams();
|
||||
$requestData['headers'] = $request->getHeaders();
|
||||
|
||||
$userContext = $event->getUserContext();
|
||||
|
||||
if (null === $userContext->getIpAddress() && isset($serverParams['REMOTE_ADDR'])) {
|
||||
$userContext->setIpAddress($serverParams['REMOTE_ADDR']);
|
||||
}
|
||||
} else {
|
||||
$requestData['headers'] = $this->removePiiFromHeaders($request->getHeaders());
|
||||
}
|
||||
|
||||
$requestBody = $this->captureRequestBody($options, $request);
|
||||
|
||||
if (!empty($requestBody)) {
|
||||
$requestData['data'] = $requestBody;
|
||||
}
|
||||
|
||||
$event->setRequest($requestData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes headers containing potential PII.
|
||||
*
|
||||
* @param array<string, array<int, string>> $headers Array containing request headers
|
||||
*
|
||||
* @return array<string, array<int, string>>
|
||||
*/
|
||||
private function removePiiFromHeaders(array $headers): array
|
||||
{
|
||||
$keysToRemove = ['authorization', 'cookie', 'set-cookie', 'remote_addr'];
|
||||
|
||||
return array_filter(
|
||||
$headers,
|
||||
static function (string $key) use ($keysToRemove): bool {
|
||||
return !\in_array(strtolower($key), $keysToRemove, true);
|
||||
},
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the decoded body of the request, if available. If the Content-Type
|
||||
* header contains "application/json" then the content is decoded and if
|
||||
* the parsing fails then the raw data is returned. If there are submitted
|
||||
* fields or files, all of their information are parsed and returned.
|
||||
*
|
||||
* @param Options $options The options of the client
|
||||
* @param ServerRequestInterface $serverRequest The server request
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function captureRequestBody(Options $options, ServerRequestInterface $serverRequest)
|
||||
{
|
||||
$maxRequestBodySize = $options->getMaxRequestBodySize();
|
||||
$requestBody = $serverRequest->getBody();
|
||||
|
||||
if (
|
||||
'none' === $maxRequestBodySize ||
|
||||
('small' === $maxRequestBodySize && $requestBody->getSize() > self::REQUEST_BODY_SMALL_MAX_CONTENT_LENGTH) ||
|
||||
('medium' === $maxRequestBodySize && $requestBody->getSize() > self::REQUEST_BODY_MEDIUM_MAX_CONTENT_LENGTH)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$requestData = $serverRequest->getParsedBody();
|
||||
$requestData = array_merge(
|
||||
$this->parseUploadedFiles($serverRequest->getUploadedFiles()),
|
||||
\is_array($requestData) ? $requestData : []
|
||||
);
|
||||
|
||||
if (!empty($requestData)) {
|
||||
return $requestData;
|
||||
}
|
||||
|
||||
if ('application/json' === $serverRequest->getHeaderLine('Content-Type')) {
|
||||
try {
|
||||
return JSON::decode($requestBody->getContents());
|
||||
} catch (JsonException $exception) {
|
||||
// Fallback to returning the raw data from the request body
|
||||
}
|
||||
}
|
||||
|
||||
return $requestBody->getContents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array with the same structure as $uploadedFiles, but replacing
|
||||
* each UploadedFileInterface with an array of info.
|
||||
*
|
||||
* @param array<string, mixed> $uploadedFiles The uploaded files info from a PSR-7 server request
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function parseUploadedFiles(array $uploadedFiles): array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($uploadedFiles as $key => $item) {
|
||||
if ($item instanceof UploadedFileInterface) {
|
||||
$result[$key] = [
|
||||
'client_filename' => $item->getClientFilename(),
|
||||
'client_media_type' => $item->getClientMediaType(),
|
||||
'size' => $item->getSize(),
|
||||
];
|
||||
} elseif (\is_array($item)) {
|
||||
$result[$key] = $this->parseUploadedFiles($item);
|
||||
} else {
|
||||
throw new \UnexpectedValueException(sprintf('Expected either an object implementing the "%s" interface or an array. Got: "%s".', UploadedFileInterface::class, \is_object($item) ? \get_class($item) : \gettype($item)));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
47
vendor/sentry/sentry/src/Integration/TransactionIntegration.php
vendored
Normal file
47
vendor/sentry/sentry/src/Integration/TransactionIntegration.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Integration;
|
||||
|
||||
use Sentry\Event;
|
||||
use Sentry\SentrySdk;
|
||||
use Sentry\State\Scope;
|
||||
|
||||
/**
|
||||
* This integration sets the `transaction` attribute of the event to the value
|
||||
* found in the raw event payload or to the value of the `PATH_INFO` server var
|
||||
* if present.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class TransactionIntegration implements IntegrationInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setupOnce(): void
|
||||
{
|
||||
Scope::addGlobalEventProcessor(static function (Event $event, array $payload): Event {
|
||||
$integration = SentrySdk::getCurrentHub()->getIntegration(self::class);
|
||||
|
||||
// The client bound to the current hub, if any, could not have this
|
||||
// integration enabled. If this is the case, bail out
|
||||
if (null === $integration) {
|
||||
return $event;
|
||||
}
|
||||
|
||||
if (null !== $event->getTransaction()) {
|
||||
return $event;
|
||||
}
|
||||
|
||||
if (isset($payload['transaction'])) {
|
||||
$event->setTransaction($payload['transaction']);
|
||||
} elseif (isset($_SERVER['PATH_INFO'])) {
|
||||
$event->setTransaction($_SERVER['PATH_INFO']);
|
||||
}
|
||||
|
||||
return $event;
|
||||
});
|
||||
}
|
||||
}
|
||||
102
vendor/sentry/sentry/src/Monolog/Handler.php
vendored
Normal file
102
vendor/sentry/sentry/src/Monolog/Handler.php
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Monolog;
|
||||
|
||||
use Monolog\Handler\AbstractProcessingHandler;
|
||||
use Monolog\Logger;
|
||||
use Sentry\Severity;
|
||||
use Sentry\State\HubInterface;
|
||||
use Sentry\State\Scope;
|
||||
|
||||
/**
|
||||
* This Monolog handler logs every message to a Sentry's server using the given
|
||||
* hub instance.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class Handler extends AbstractProcessingHandler
|
||||
{
|
||||
/**
|
||||
* @var HubInterface
|
||||
*/
|
||||
private $hub;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param HubInterface $hub The hub to which errors are reported
|
||||
* @param int|string $level The minimum logging level at which this
|
||||
* handler will be triggered
|
||||
* @param bool $bubble Whether the messages that are handled can
|
||||
* bubble up the stack or not
|
||||
*/
|
||||
public function __construct(HubInterface $hub, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
$this->hub = $hub;
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$payload = [
|
||||
'level' => self::getSeverityFromLevel($record['level']),
|
||||
'message' => $record['message'],
|
||||
'logger' => 'monolog.' . $record['channel'],
|
||||
];
|
||||
|
||||
if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
|
||||
$payload['exception'] = $record['context']['exception'];
|
||||
}
|
||||
|
||||
$this->hub->withScope(function (Scope $scope) use ($record, $payload): void {
|
||||
$scope->setExtra('monolog.channel', $record['channel']);
|
||||
$scope->setExtra('monolog.level', $record['level_name']);
|
||||
|
||||
if (isset($record['context']['extra']) && \is_array($record['context']['extra'])) {
|
||||
foreach ($record['context']['extra'] as $key => $value) {
|
||||
$scope->setExtra((string) $key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($record['context']['tags']) && \is_array($record['context']['tags'])) {
|
||||
foreach ($record['context']['tags'] as $key => $value) {
|
||||
$scope->setTag($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
$this->hub->captureEvent($payload);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the Monolog level into the Sentry severity.
|
||||
*
|
||||
* @param int $level The Monolog log level
|
||||
*/
|
||||
private static function getSeverityFromLevel(int $level): Severity
|
||||
{
|
||||
switch ($level) {
|
||||
case Logger::DEBUG:
|
||||
return Severity::debug();
|
||||
case Logger::INFO:
|
||||
case Logger::NOTICE:
|
||||
return Severity::info();
|
||||
case Logger::WARNING:
|
||||
return Severity::warning();
|
||||
case Logger::ERROR:
|
||||
return Severity::error();
|
||||
case Logger::CRITICAL:
|
||||
case Logger::ALERT:
|
||||
case Logger::EMERGENCY:
|
||||
return Severity::fatal();
|
||||
default:
|
||||
return Severity::info();
|
||||
}
|
||||
}
|
||||
}
|
||||
1075
vendor/sentry/sentry/src/Options.php
vendored
Normal file
1075
vendor/sentry/sentry/src/Options.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
64
vendor/sentry/sentry/src/SentrySdk.php
vendored
Normal file
64
vendor/sentry/sentry/src/SentrySdk.php
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
use Sentry\State\Hub;
|
||||
use Sentry\State\HubInterface;
|
||||
|
||||
/**
|
||||
* This class is the main entry point for all the most common SDK features.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class SentrySdk
|
||||
{
|
||||
/**
|
||||
* @var HubInterface|null The current hub
|
||||
*/
|
||||
private static $currentHub;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the SDK by creating a new hub instance each time this method
|
||||
* gets called.
|
||||
*/
|
||||
public static function init(): HubInterface
|
||||
{
|
||||
self::$currentHub = new Hub();
|
||||
|
||||
return self::$currentHub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current hub. If it's not initialized then creates a new instance
|
||||
* and sets it as current hub.
|
||||
*/
|
||||
public static function getCurrentHub(): HubInterface
|
||||
{
|
||||
if (null === self::$currentHub) {
|
||||
self::$currentHub = new Hub();
|
||||
}
|
||||
|
||||
return self::$currentHub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current hub.
|
||||
*
|
||||
* @param HubInterface $hub The hub to set
|
||||
*/
|
||||
public static function setCurrentHub(HubInterface $hub): HubInterface
|
||||
{
|
||||
self::$currentHub = $hub;
|
||||
|
||||
return $hub;
|
||||
}
|
||||
}
|
||||
368
vendor/sentry/sentry/src/Serializer/AbstractSerializer.php
vendored
Normal file
368
vendor/sentry/sentry/src/Serializer/AbstractSerializer.php
vendored
Normal file
@@ -0,0 +1,368 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace Sentry\Serializer;
|
||||
|
||||
use Sentry\Exception\InvalidArgumentException;
|
||||
use Sentry\Options;
|
||||
|
||||
/**
|
||||
* This helper is based on code from Facebook's Phabricator project.
|
||||
*
|
||||
* https://github.com/facebook/phabricator
|
||||
*
|
||||
* Specifically, it is an adaptation of the PhutilReadableSerializer class.
|
||||
*/
|
||||
abstract class AbstractSerializer
|
||||
{
|
||||
/**
|
||||
* The default mb detect order.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.mb-detect-encoding.php
|
||||
*/
|
||||
public const DEFAULT_MB_DETECT_ORDER = 'auto';
|
||||
|
||||
/**
|
||||
* Suggested detect order for western countries.
|
||||
*/
|
||||
public const WESTERN_MB_DETECT_ORDER = 'UTF-8, ASCII, ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16, Windows-1251, Windows-1252, Windows-1254';
|
||||
|
||||
/**
|
||||
* The maximum depth to reach when serializing recursively.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $maxDepth;
|
||||
|
||||
/**
|
||||
* This is the default mb detect order for the detection of encoding.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $mbDetectOrder = self::DEFAULT_MB_DETECT_ORDER;
|
||||
|
||||
/**
|
||||
* @var bool Flag to enable serialization of objects internal properties
|
||||
*/
|
||||
protected $serializeAllObjects = false;
|
||||
|
||||
/**
|
||||
* @var Options The Sentry options
|
||||
*/
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* AbstractSerializer constructor.
|
||||
*
|
||||
* @param Options $options The SDK configuration options
|
||||
*/
|
||||
public function __construct(Options $options, int $maxDepth = 3, ?string $mbDetectOrder = null)
|
||||
{
|
||||
$this->maxDepth = $maxDepth;
|
||||
|
||||
if (null != $mbDetectOrder) {
|
||||
$this->mbDetectOrder = $mbDetectOrder;
|
||||
}
|
||||
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize an object (recursively) into something safe for data
|
||||
* sanitization and encoding.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return string|bool|float|int|mixed[]|null
|
||||
*/
|
||||
protected function serializeRecursively($value, int $_depth = 0)
|
||||
{
|
||||
try {
|
||||
if ($_depth >= $this->maxDepth) {
|
||||
return $this->serializeValue($value);
|
||||
}
|
||||
|
||||
if (\is_callable($value)) {
|
||||
return $this->serializeCallableWithoutTypeHint($value);
|
||||
}
|
||||
|
||||
if (\is_array($value)) {
|
||||
$serializedArray = [];
|
||||
|
||||
foreach ($value as $k => $v) {
|
||||
$serializedArray[$k] = $this->serializeRecursively($v, $_depth + 1);
|
||||
}
|
||||
|
||||
return $serializedArray;
|
||||
}
|
||||
|
||||
if (\is_object($value)) {
|
||||
$classSerializers = $this->resolveClassSerializers($value);
|
||||
|
||||
// Try each serializer until there is none left or the serializer returned data
|
||||
foreach ($classSerializers as $classSerializer) {
|
||||
try {
|
||||
$serializedObjectData = $classSerializer($value);
|
||||
|
||||
if (\is_array($serializedObjectData)) {
|
||||
return [
|
||||
'class' => \get_class($value),
|
||||
'data' => $this->serializeRecursively($serializedObjectData, $_depth + 1),
|
||||
];
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// Ignore any exceptions generated by a class serializer
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->serializeAllObjects || ($value instanceof \stdClass)) {
|
||||
return $this->serializeObject($value, $_depth);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->serializeValue($value);
|
||||
} catch (\Throwable $error) {
|
||||
if (\is_string($value)) {
|
||||
return $value . ' {serialization error}';
|
||||
}
|
||||
|
||||
return '{serialization error}';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find class serializers for a object.
|
||||
*
|
||||
* Registered serializers with the `class_serializers` option take precedence over
|
||||
* objects implementing the `SerializableInterface`.
|
||||
*
|
||||
* @param object $object
|
||||
*
|
||||
* @return array<int, callable>
|
||||
*/
|
||||
protected function resolveClassSerializers($object): array
|
||||
{
|
||||
$serializers = [];
|
||||
|
||||
foreach ($this->options->getClassSerializers() as $type => $serializer) {
|
||||
if ($object instanceof $type) {
|
||||
$serializers[] = $serializer;
|
||||
}
|
||||
}
|
||||
|
||||
if ($object instanceof SerializableInterface) {
|
||||
$serializers[] = static function (SerializableInterface $object): ?array {
|
||||
return $object->toSentry();
|
||||
};
|
||||
}
|
||||
|
||||
return $serializers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $object
|
||||
* @param string[] $hashes
|
||||
*
|
||||
* @return mixed[]|string|bool|float|int|null
|
||||
*/
|
||||
protected function serializeObject($object, int $_depth = 0, array $hashes = [])
|
||||
{
|
||||
if ($_depth >= $this->maxDepth || \in_array(spl_object_hash($object), $hashes, true)) {
|
||||
return $this->serializeValue($object);
|
||||
}
|
||||
|
||||
$hashes[] = spl_object_hash($object);
|
||||
$serializedObject = [];
|
||||
|
||||
foreach ($object as $key => &$value) {
|
||||
if (\is_object($value)) {
|
||||
$serializedObject[$key] = $this->serializeObject($value, $_depth + 1, $hashes);
|
||||
} else {
|
||||
$serializedObject[$key] = $this->serializeRecursively($value, $_depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return $serializedObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the given value to a string.
|
||||
*
|
||||
* @param mixed $value The value to serialize
|
||||
*/
|
||||
protected function serializeString($value): string
|
||||
{
|
||||
$value = (string) $value;
|
||||
|
||||
// we always guarantee this is coerced, even if we can't detect encoding
|
||||
if ($currentEncoding = mb_detect_encoding($value, $this->mbDetectOrder)) {
|
||||
$value = mb_convert_encoding($value, 'UTF-8', $currentEncoding);
|
||||
} else {
|
||||
$value = mb_convert_encoding($value, 'UTF-8');
|
||||
}
|
||||
|
||||
if (mb_strlen($value) > $this->options->getMaxValueLength()) {
|
||||
$value = mb_substr($value, 0, $this->options->getMaxValueLength() - 10, 'UTF-8') . ' {clipped}';
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return string|bool|float|int|null
|
||||
*/
|
||||
protected function serializeValue($value)
|
||||
{
|
||||
if ((null === $value) || \is_bool($value) || is_numeric($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (\is_object($value)) {
|
||||
return 'Object ' . \get_class($value);
|
||||
}
|
||||
|
||||
if (\is_resource($value)) {
|
||||
return 'Resource ' . get_resource_type($value);
|
||||
}
|
||||
|
||||
if (\is_callable($value)) {
|
||||
return $this->serializeCallableWithoutTypeHint($value);
|
||||
}
|
||||
|
||||
if (\is_array($value)) {
|
||||
return 'Array of length ' . \count($value);
|
||||
}
|
||||
|
||||
return $this->serializeString($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is provided as a non-BC upgrade of serializeCallable,
|
||||
* since using the callable type raises a deprecation in some cases.
|
||||
*
|
||||
* @param callable|mixed $callable
|
||||
*/
|
||||
protected function serializeCallableWithoutTypeHint($callable): string
|
||||
{
|
||||
if (\is_string($callable) && !\function_exists($callable)) {
|
||||
return $callable;
|
||||
}
|
||||
|
||||
if (!\is_callable($callable)) {
|
||||
throw new InvalidArgumentException(sprintf('Expecting callable, got %s', \is_object($callable) ? \get_class($callable) : \gettype($callable)));
|
||||
}
|
||||
|
||||
return $this->serializeCallable($callable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use serializeCallableWithoutTypeHint instead (no type in argument).
|
||||
*
|
||||
* @see https://github.com/getsentry/sentry-php/pull/821
|
||||
*
|
||||
* @param callable $callable callable type to be removed in 3.0, see #821
|
||||
*/
|
||||
protected function serializeCallable(callable $callable): string
|
||||
{
|
||||
try {
|
||||
if (\is_array($callable)) {
|
||||
$reflection = new \ReflectionMethod($callable[0], $callable[1]);
|
||||
$class = $reflection->getDeclaringClass();
|
||||
} elseif ($callable instanceof \Closure || (\is_string($callable) && \function_exists($callable))) {
|
||||
$reflection = new \ReflectionFunction($callable);
|
||||
$class = null;
|
||||
} elseif (\is_object($callable) && method_exists($callable, '__invoke')) {
|
||||
$reflection = new \ReflectionMethod($callable, '__invoke');
|
||||
$class = $reflection->getDeclaringClass();
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Unrecognized type of callable');
|
||||
}
|
||||
} catch (\ReflectionException $exception) {
|
||||
return '{unserializable callable, reflection error}';
|
||||
}
|
||||
|
||||
$callableType = $reflection->isClosure() ? 'Lambda ' : 'Callable ';
|
||||
$callableReturnType = $reflection->getReturnType();
|
||||
|
||||
if ($callableReturnType instanceof \ReflectionNamedType) {
|
||||
$callableType .= $callableReturnType->getName() . ' ';
|
||||
}
|
||||
|
||||
if ($class) {
|
||||
$callableType .= $class->getName() . '::';
|
||||
}
|
||||
|
||||
return $callableType . $reflection->getName() . ' ' . $this->serializeCallableParameters($reflection);
|
||||
}
|
||||
|
||||
private function serializeCallableParameters(\ReflectionFunctionAbstract $reflection): string
|
||||
{
|
||||
$params = [];
|
||||
foreach ($reflection->getParameters() as &$param) {
|
||||
$reflectionType = $param->getType();
|
||||
if ($reflectionType instanceof \ReflectionNamedType) {
|
||||
$paramType = $reflectionType->getName();
|
||||
} else {
|
||||
$paramType = 'mixed';
|
||||
}
|
||||
|
||||
if ($param->allowsNull()) {
|
||||
$paramType .= '|null';
|
||||
}
|
||||
|
||||
$paramName = ($param->isPassedByReference() ? '&' : '') . $param->getName();
|
||||
|
||||
if ($param->isOptional()) {
|
||||
$paramName = '[' . $paramName . ']';
|
||||
}
|
||||
|
||||
$params[] = $paramType . ' ' . $paramName;
|
||||
}
|
||||
|
||||
return '[' . implode('; ', $params) . ']';
|
||||
}
|
||||
|
||||
public function getMbDetectOrder(): string
|
||||
{
|
||||
return $this->mbDetectOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setMbDetectOrder(string $mbDetectOrder): self
|
||||
{
|
||||
$this->mbDetectOrder = $mbDetectOrder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setSerializeAllObjects(bool $value): void
|
||||
{
|
||||
$this->serializeAllObjects = $value;
|
||||
}
|
||||
|
||||
public function getSerializeAllObjects(): bool
|
||||
{
|
||||
return $this->serializeAllObjects;
|
||||
}
|
||||
}
|
||||
65
vendor/sentry/sentry/src/Serializer/RepresentationSerializer.php
vendored
Normal file
65
vendor/sentry/sentry/src/Serializer/RepresentationSerializer.php
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Serializer;
|
||||
|
||||
/**
|
||||
* Serializes a value into a representation that should reasonably suggest
|
||||
* both the type and value, and be serializable into JSON.
|
||||
*/
|
||||
class RepresentationSerializer extends AbstractSerializer implements RepresentationSerializerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @psalm-suppress InvalidReturnType
|
||||
* @psalm-suppress InvalidReturnStatement
|
||||
*/
|
||||
public function representationSerialize($value)
|
||||
{
|
||||
$value = $this->serializeRecursively($value);
|
||||
|
||||
if (is_numeric($value)) {
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
if (\is_bool($value)) {
|
||||
return $value ? 'true' : 'false';
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overridden to return even basic types as strings.
|
||||
*
|
||||
* @param mixed $value The value that needs to be serialized
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function serializeValue($value)
|
||||
{
|
||||
if (null === $value) {
|
||||
return 'null';
|
||||
}
|
||||
|
||||
if (false === $value) {
|
||||
return 'false';
|
||||
}
|
||||
|
||||
if (true === $value) {
|
||||
return 'true';
|
||||
}
|
||||
|
||||
if (\is_float($value) && (int) $value == $value) {
|
||||
return $value . '.0';
|
||||
}
|
||||
|
||||
if (is_numeric($value)) {
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
return (string) parent::serializeValue($value);
|
||||
}
|
||||
}
|
||||
24
vendor/sentry/sentry/src/Serializer/RepresentationSerializerInterface.php
vendored
Normal file
24
vendor/sentry/sentry/src/Serializer/RepresentationSerializerInterface.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Serializer;
|
||||
|
||||
/**
|
||||
* Serializes a value into a representation that should reasonably suggest
|
||||
* both the type and value, and be serializable into JSON.
|
||||
*/
|
||||
interface RepresentationSerializerInterface
|
||||
{
|
||||
/**
|
||||
* Serialize an object (recursively) into something safe to be sent as a stacktrace frame argument.
|
||||
*
|
||||
* The main difference with the {@link SerializerInterface} is the fact that even basic types
|
||||
* (bool, int, float) are converted into strings, to avoid misrepresentations on the server side.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return mixed[]|string|null
|
||||
*/
|
||||
public function representationSerialize($value);
|
||||
}
|
||||
19
vendor/sentry/sentry/src/Serializer/SerializableInterface.php
vendored
Normal file
19
vendor/sentry/sentry/src/Serializer/SerializableInterface.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Serializer;
|
||||
|
||||
/**
|
||||
* This interface can be used to customize how an object is serialized in the
|
||||
* payload of an event.
|
||||
*/
|
||||
interface SerializableInterface
|
||||
{
|
||||
/**
|
||||
* Returns an array representation of the object for Sentry.
|
||||
*
|
||||
* @return mixed[]|null
|
||||
*/
|
||||
public function toSentry(): ?array;
|
||||
}
|
||||
19
vendor/sentry/sentry/src/Serializer/Serializer.php
vendored
Normal file
19
vendor/sentry/sentry/src/Serializer/Serializer.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Serializer;
|
||||
|
||||
/**
|
||||
* Basic serializer for the event data.
|
||||
*/
|
||||
class Serializer extends AbstractSerializer implements SerializerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function serialize($value)
|
||||
{
|
||||
return $this->serializeRecursively($value);
|
||||
}
|
||||
}
|
||||
20
vendor/sentry/sentry/src/Serializer/SerializerInterface.php
vendored
Normal file
20
vendor/sentry/sentry/src/Serializer/SerializerInterface.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Serializer;
|
||||
|
||||
/**
|
||||
* Basic serializer for the event data.
|
||||
*/
|
||||
interface SerializerInterface
|
||||
{
|
||||
/**
|
||||
* Serialize an object (recursively) into something safe to be sent in an Event.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return string|bool|float|int|object|mixed[]|null
|
||||
*/
|
||||
public function serialize($value);
|
||||
}
|
||||
173
vendor/sentry/sentry/src/Severity.php
vendored
Normal file
173
vendor/sentry/sentry/src/Severity.php
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
/**
|
||||
* This class represents an enum of severity levels an event can be associated
|
||||
* to.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class Severity
|
||||
{
|
||||
/**
|
||||
* This constant represents the "debug" severity level.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public const DEBUG = 'debug';
|
||||
|
||||
/**
|
||||
* This constant represents the "info" severity level.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public const INFO = 'info';
|
||||
|
||||
/**
|
||||
* This constant represents the "warning" severity level.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public const WARNING = 'warning';
|
||||
|
||||
/**
|
||||
* This constant represents the "error" severity level.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public const ERROR = 'error';
|
||||
|
||||
/**
|
||||
* This constant represents the "fatal" severity level.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public const FATAL = 'fatal';
|
||||
|
||||
/**
|
||||
* This constant contains the list of allowed enum values.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public const ALLOWED_SEVERITIES = [
|
||||
self::DEBUG,
|
||||
self::INFO,
|
||||
self::WARNING,
|
||||
self::ERROR,
|
||||
self::FATAL,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string The value of this enum instance
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $value The value this instance represents
|
||||
*/
|
||||
public function __construct(string $value = self::INFO)
|
||||
{
|
||||
if (!\in_array($value, self::ALLOWED_SEVERITIES, true)) {
|
||||
throw new \InvalidArgumentException(sprintf('The "%s" is not a valid enum value.', $value));
|
||||
}
|
||||
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a PHP Error constant into a Sentry log level group.
|
||||
*
|
||||
* @param int $severity PHP E_* error constant
|
||||
*
|
||||
* @return Severity
|
||||
*/
|
||||
public static function fromError(int $severity): self
|
||||
{
|
||||
switch ($severity) {
|
||||
case E_DEPRECATED:
|
||||
case E_USER_DEPRECATED:
|
||||
case E_WARNING:
|
||||
case E_USER_WARNING:
|
||||
return self::warning();
|
||||
case E_ERROR:
|
||||
case E_PARSE:
|
||||
case E_CORE_ERROR:
|
||||
case E_CORE_WARNING:
|
||||
case E_COMPILE_ERROR:
|
||||
case E_COMPILE_WARNING:
|
||||
return self::fatal();
|
||||
case E_RECOVERABLE_ERROR:
|
||||
case E_USER_ERROR:
|
||||
return self::error();
|
||||
case E_NOTICE:
|
||||
case E_USER_NOTICE:
|
||||
case E_STRICT:
|
||||
return self::info();
|
||||
default:
|
||||
return self::error();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of this enum for the "debug" value.
|
||||
*/
|
||||
public static function debug(): self
|
||||
{
|
||||
return new self(self::DEBUG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of this enum for the "info" value.
|
||||
*/
|
||||
public static function info(): self
|
||||
{
|
||||
return new self(self::INFO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of this enum for the "warning" value.
|
||||
*/
|
||||
public static function warning(): self
|
||||
{
|
||||
return new self(self::WARNING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of this enum for the "error" value.
|
||||
*/
|
||||
public static function error(): self
|
||||
{
|
||||
return new self(self::ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of this enum for the "fatal" value.
|
||||
*/
|
||||
public static function fatal(): self
|
||||
{
|
||||
return new self(self::FATAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether two object instances of this class are equal.
|
||||
*
|
||||
* @param self $other The object to compare
|
||||
*/
|
||||
public function isEqualTo(self $other): bool
|
||||
{
|
||||
return $this->value === (string) $other;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://www.php.net/manual/en/language.oop5.magic.php#object.tostring
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
45
vendor/sentry/sentry/src/Spool/MemorySpool.php
vendored
Normal file
45
vendor/sentry/sentry/src/Spool/MemorySpool.php
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Spool;
|
||||
|
||||
use Sentry\Event;
|
||||
use Sentry\Transport\TransportInterface;
|
||||
|
||||
/**
|
||||
* This spool stores the events in memory.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class MemorySpool implements SpoolInterface
|
||||
{
|
||||
/**
|
||||
* @var Event[] List of enqueued events
|
||||
*/
|
||||
private $events = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function queueEvent(Event $event): bool
|
||||
{
|
||||
$this->events[] = $event;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function flushQueue(TransportInterface $transport): void
|
||||
{
|
||||
if (empty($this->events)) {
|
||||
return;
|
||||
}
|
||||
|
||||
while ($event = array_pop($this->events)) {
|
||||
$transport->send($event);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
vendor/sentry/sentry/src/Spool/SpoolInterface.php
vendored
Normal file
33
vendor/sentry/sentry/src/Spool/SpoolInterface.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Spool;
|
||||
|
||||
use Sentry\Event;
|
||||
use Sentry\Transport\TransportInterface;
|
||||
|
||||
/**
|
||||
* This interface must be implemented by all classes willing to provide the
|
||||
* storage of a spool.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
interface SpoolInterface
|
||||
{
|
||||
/**
|
||||
* Queues an event.
|
||||
*
|
||||
* @param Event $event The event to store
|
||||
*
|
||||
* @return bool Whether the operation has succeeded
|
||||
*/
|
||||
public function queueEvent(Event $event): bool;
|
||||
|
||||
/**
|
||||
* Sends the events that are in the queue using the given transport.
|
||||
*
|
||||
* @param TransportInterface $transport The transport instance
|
||||
*/
|
||||
public function flushQueue(TransportInterface $transport): void;
|
||||
}
|
||||
509
vendor/sentry/sentry/src/Stacktrace.php
vendored
Normal file
509
vendor/sentry/sentry/src/Stacktrace.php
vendored
Normal file
@@ -0,0 +1,509 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
use Sentry\Serializer\RepresentationSerializerInterface;
|
||||
use Sentry\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
* This class contains all the information about an error stacktrace.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*
|
||||
* @final since version 2.3
|
||||
*/
|
||||
class Stacktrace implements \JsonSerializable
|
||||
{
|
||||
private const INTERNAL_FRAME_FILENAME = '[internal]';
|
||||
|
||||
private const ANONYMOUS_CLASS_PREFIX = "class@anonymous\x00";
|
||||
|
||||
/**
|
||||
* @var bool Flag indicating whether it's responsibility of this class to
|
||||
* read the source code excerpts for each frame
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @deprecated since version 2.4, to be removed in 3.0
|
||||
*/
|
||||
protected $shouldReadSourceCodeExcerpts = false;
|
||||
|
||||
/**
|
||||
* @var Options The client options
|
||||
*/
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* @var SerializerInterface The serializer
|
||||
*
|
||||
* @deprecated since version 2.4, to be removed in 3.0
|
||||
*/
|
||||
protected $serializer;
|
||||
|
||||
/**
|
||||
* @var RepresentationSerializerInterface The representation serializer
|
||||
*/
|
||||
protected $representationSerializer;
|
||||
|
||||
/**
|
||||
* @var Frame[] The frames that compose the stacktrace
|
||||
*/
|
||||
protected $frames = [];
|
||||
|
||||
/**
|
||||
* @var string[] The list of functions to import a file
|
||||
*/
|
||||
protected static $importStatements = [
|
||||
'include',
|
||||
'include_once',
|
||||
'require',
|
||||
'require_once',
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Options $options The client options
|
||||
* @param SerializerInterface $serializer The serializer
|
||||
* @param RepresentationSerializerInterface $representationSerializer The representation serializer
|
||||
*/
|
||||
public function __construct(Options $options, SerializerInterface $serializer, RepresentationSerializerInterface $representationSerializer/*, bool $shouldReadSourceCodeExcerpts = true*/)
|
||||
{
|
||||
if (\func_num_args() <= 3 || false !== func_get_arg(3)) {
|
||||
@trigger_error(sprintf('Relying on the "%s" class to contexify the frames of the stacktrace is deprecated since version 2.4 and will stop working in 3.0. Set the $shouldReadSourceCodeExcerpts parameter to "false" and use the "Sentry\Integration\FrameContextifierIntegration" integration instead.', self::class), E_USER_DEPRECATED);
|
||||
|
||||
$this->shouldReadSourceCodeExcerpts = true;
|
||||
}
|
||||
|
||||
$this->options = $options;
|
||||
$this->serializer = $serializer;
|
||||
$this->representationSerializer = $representationSerializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of this class from the given backtrace.
|
||||
*
|
||||
* @param Options $options The client options
|
||||
* @param SerializerInterface $serializer The serializer
|
||||
* @param RepresentationSerializerInterface $representationSerializer The representation serializer
|
||||
* @param array[] $backtrace The backtrace
|
||||
* @param string $file The file that originated the backtrace
|
||||
* @param int $line The line at which the backtrace originated
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function createFromBacktrace(Options $options, SerializerInterface $serializer, RepresentationSerializerInterface $representationSerializer, array $backtrace, string $file, int $line/*, bool $shouldReadSourceCodeExcerpts = true*/)
|
||||
{
|
||||
$stacktrace = new static($options, $serializer, $representationSerializer, \func_num_args() > 6 ? func_get_arg(6) : true);
|
||||
|
||||
foreach ($backtrace as $frame) {
|
||||
$stacktrace->addFrame($file, $line, $frame);
|
||||
|
||||
$file = $frame['file'] ?? self::INTERNAL_FRAME_FILENAME;
|
||||
$line = $frame['line'] ?? 0;
|
||||
}
|
||||
|
||||
// Add a final stackframe for the first method ever of this stacktrace
|
||||
$stacktrace->addFrame($file, $line, []);
|
||||
|
||||
return $stacktrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stacktrace frames.
|
||||
*
|
||||
* @return Frame[]
|
||||
*/
|
||||
public function getFrames(): array
|
||||
{
|
||||
return $this->frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the frame at the given index.
|
||||
*
|
||||
* @param int $index The index from which the frame should be get
|
||||
*
|
||||
* @throws \OutOfBoundsException
|
||||
*/
|
||||
public function getFrame(int $index): Frame
|
||||
{
|
||||
if ($index < 0 || $index >= \count($this->frames)) {
|
||||
throw new \OutOfBoundsException();
|
||||
}
|
||||
|
||||
return $this->frames[$index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new frame to the stacktrace.
|
||||
*
|
||||
* @param string $file The file where the frame originated
|
||||
* @param int $line The line at which the frame originated
|
||||
* @param array<string, mixed> $backtraceFrame The data of the frame to add
|
||||
*/
|
||||
public function addFrame(string $file, int $line, array $backtraceFrame): void
|
||||
{
|
||||
// The $file argument can be any of these formats:
|
||||
// </path/to/filename>
|
||||
// </path/to/filename>(<line number>) : eval()'d code
|
||||
// </path/to/filename>(<line number>) : runtime-created function
|
||||
if (preg_match('/^(.*)\((\d+)\) : (?:eval\(\)\'d code|runtime-created function)$/', $file, $matches)) {
|
||||
$file = $matches[1];
|
||||
$line = (int) $matches[2];
|
||||
}
|
||||
|
||||
if (isset($backtraceFrame['class']) && isset($backtraceFrame['function'])) {
|
||||
if (0 === strpos($backtraceFrame['class'], self::ANONYMOUS_CLASS_PREFIX)) {
|
||||
$backtraceFrame['class'] = self::ANONYMOUS_CLASS_PREFIX . $this->stripPrefixFromFilePath(substr($backtraceFrame['class'], \strlen(self::ANONYMOUS_CLASS_PREFIX)));
|
||||
}
|
||||
|
||||
$functionName = sprintf(
|
||||
'%s::%s',
|
||||
preg_replace('/0x[a-fA-F0-9]+$/', '', $backtraceFrame['class']),
|
||||
$backtraceFrame['function']
|
||||
);
|
||||
} elseif (isset($backtraceFrame['function'])) {
|
||||
$functionName = $backtraceFrame['function'];
|
||||
} else {
|
||||
$functionName = null;
|
||||
}
|
||||
|
||||
$frameArguments = $this->getFrameArguments($backtraceFrame);
|
||||
|
||||
foreach ($frameArguments as $argumentName => $argumentValue) {
|
||||
$argumentValue = $this->representationSerializer->representationSerialize($argumentValue);
|
||||
|
||||
if (\is_string($argumentValue)) {
|
||||
$frameArguments[(string) $argumentName] = mb_substr($argumentValue, 0, $this->options->getMaxValueLength());
|
||||
} else {
|
||||
$frameArguments[(string) $argumentName] = $argumentValue;
|
||||
}
|
||||
}
|
||||
|
||||
$frame = new Frame(
|
||||
$functionName,
|
||||
$this->stripPrefixFromFilePath($file),
|
||||
$line,
|
||||
$file,
|
||||
$frameArguments,
|
||||
$this->isFrameInApp($file, $functionName)
|
||||
);
|
||||
|
||||
if ($this->shouldReadSourceCodeExcerpts && null !== $this->options->getContextLines()) {
|
||||
$sourceCodeExcerpt = $this->getSourceCodeExcerpt($file, $line, $this->options->getContextLines());
|
||||
|
||||
if (isset($sourceCodeExcerpt['pre_context'])) {
|
||||
$frame->setPreContext($sourceCodeExcerpt['pre_context']);
|
||||
}
|
||||
|
||||
if (isset($sourceCodeExcerpt['context_line'])) {
|
||||
$frame->setContextLine($sourceCodeExcerpt['context_line']);
|
||||
}
|
||||
|
||||
if (isset($sourceCodeExcerpt['post_context'])) {
|
||||
$frame->setPostContext($sourceCodeExcerpt['post_context']);
|
||||
}
|
||||
}
|
||||
|
||||
array_unshift($this->frames, $frame);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the frame at the given index from the stacktrace.
|
||||
*
|
||||
* @param int $index The index of the frame
|
||||
*
|
||||
* @throws \OutOfBoundsException If the index is out of range
|
||||
*/
|
||||
public function removeFrame(int $index): void
|
||||
{
|
||||
if (!isset($this->frames[$index])) {
|
||||
throw new \OutOfBoundsException('Invalid frame index to remove.');
|
||||
}
|
||||
|
||||
array_splice($this->frames, $index, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stacktrace frames (this is the same as calling the getFrames
|
||||
* method).
|
||||
*
|
||||
* @return Frame[]
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return Frame[]
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an excerpt of the source code around a given line.
|
||||
*
|
||||
* @param string $path The file path
|
||||
* @param int $lineNumber The line to centre about
|
||||
* @param int $maxLinesToFetch The maximum number of lines to fetch
|
||||
*
|
||||
* @return array<string, string|string[]>
|
||||
*
|
||||
* @deprecated since version 2.4, to be removed in 3.0
|
||||
*
|
||||
* @psalm-return array{
|
||||
* pre_context?: string[],
|
||||
* context_line?: string,
|
||||
* post_context?: string[]
|
||||
* }
|
||||
*/
|
||||
protected function getSourceCodeExcerpt(string $path, int $lineNumber, int $maxLinesToFetch): array
|
||||
{
|
||||
if (@!is_readable($path) || !is_file($path)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$frame = [
|
||||
'pre_context' => [],
|
||||
'context_line' => '',
|
||||
'post_context' => [],
|
||||
];
|
||||
|
||||
$target = max(0, ($lineNumber - ($maxLinesToFetch + 1)));
|
||||
$currentLineNumber = $target + 1;
|
||||
|
||||
try {
|
||||
$file = new \SplFileObject($path);
|
||||
$file->seek($target);
|
||||
|
||||
while (!$file->eof()) {
|
||||
/** @var string $line */
|
||||
$line = $file->current();
|
||||
$line = rtrim($line, "\r\n");
|
||||
|
||||
if ($currentLineNumber == $lineNumber) {
|
||||
$frame['context_line'] = $line;
|
||||
} elseif ($currentLineNumber < $lineNumber) {
|
||||
$frame['pre_context'][] = $line;
|
||||
} elseif ($currentLineNumber > $lineNumber) {
|
||||
$frame['post_context'][] = $line;
|
||||
}
|
||||
|
||||
++$currentLineNumber;
|
||||
|
||||
if ($currentLineNumber > $lineNumber + $maxLinesToFetch) {
|
||||
break;
|
||||
}
|
||||
|
||||
$file->next();
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
// Do nothing, if any error occurs while trying to get the excerpts
|
||||
// it's not a drama
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes from the given file path the specified prefixes.
|
||||
*
|
||||
* @param string $filePath The path to the file
|
||||
*/
|
||||
protected function stripPrefixFromFilePath(string $filePath): string
|
||||
{
|
||||
foreach ($this->options->getPrefixes() as $prefix) {
|
||||
if (0 === mb_strpos($filePath, $prefix)) {
|
||||
return mb_substr($filePath, mb_strlen($prefix));
|
||||
}
|
||||
}
|
||||
|
||||
return $filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the values of the arguments of the given stackframe.
|
||||
*
|
||||
* @param array<string, mixed> $frame The frame from where arguments are retrieved
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function getFrameArgumentsValues(array $frame): array
|
||||
{
|
||||
if (empty($frame['args'])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
if (\is_string(array_keys($frame['args'])[0])) {
|
||||
$result = array_map([$this, 'serializeArgument'], $frame['args']);
|
||||
} else {
|
||||
$index = 0;
|
||||
foreach (array_values($frame['args']) as $argument) {
|
||||
$result['param' . (++$index)] = $this->serializeArgument($argument);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the arguments of the given stackframe.
|
||||
*
|
||||
* @param array<string, mixed> $frame The frame from where arguments are retrieved
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getFrameArguments(array $frame): array
|
||||
{
|
||||
if (!isset($frame['args'])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// The Reflection API seems more appropriate if we associate it with the frame
|
||||
// where the function is actually called (since we're treating them as function context)
|
||||
if (!isset($frame['function'])) {
|
||||
return $this->getFrameArgumentsValues($frame);
|
||||
}
|
||||
|
||||
if (false !== strpos($frame['function'], '__lambda_func')) {
|
||||
return $this->getFrameArgumentsValues($frame);
|
||||
}
|
||||
|
||||
if (false !== strpos($frame['function'], '{closure}')) {
|
||||
return $this->getFrameArgumentsValues($frame);
|
||||
}
|
||||
|
||||
if (isset($frame['class']) && 'Closure' === $frame['class']) {
|
||||
return $this->getFrameArgumentsValues($frame);
|
||||
}
|
||||
|
||||
if (\in_array($frame['function'], static::$importStatements, true)) {
|
||||
if (empty($frame['args'])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
'param1' => $this->serializeArgument($frame['args'][0]),
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
if (isset($frame['class'])) {
|
||||
if (method_exists($frame['class'], $frame['function'])) {
|
||||
$reflection = new \ReflectionMethod($frame['class'], $frame['function']);
|
||||
} elseif ('::' === $frame['type']) {
|
||||
$reflection = new \ReflectionMethod($frame['class'], '__callStatic');
|
||||
} else {
|
||||
$reflection = new \ReflectionMethod($frame['class'], '__call');
|
||||
}
|
||||
} elseif (\function_exists($frame['function'])) {
|
||||
$reflection = new \ReflectionFunction($frame['function']);
|
||||
} else {
|
||||
return $this->getFrameArgumentsValues($frame);
|
||||
}
|
||||
} catch (\ReflectionException $ex) {
|
||||
return $this->getFrameArgumentsValues($frame);
|
||||
}
|
||||
|
||||
$params = $reflection->getParameters();
|
||||
$args = [];
|
||||
|
||||
foreach ($frame['args'] as $index => $arg) {
|
||||
$arg = $this->serializeArgument($arg);
|
||||
|
||||
if (isset($params[$index])) {
|
||||
// Assign the argument by the parameter name
|
||||
$args[$params[$index]->getName()] = $arg;
|
||||
} else {
|
||||
$args['param' . $index] = $arg;
|
||||
}
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the given argument.
|
||||
*
|
||||
* @param mixed $arg The argument to serialize
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function serializeArgument($arg)
|
||||
{
|
||||
$maxValueLength = $this->options->getMaxValueLength();
|
||||
|
||||
if (\is_array($arg)) {
|
||||
$result = [];
|
||||
|
||||
foreach ($arg as $key => $value) {
|
||||
if (\is_string($value) || is_numeric($value)) {
|
||||
$result[$key] = mb_substr((string) $value, 0, $maxValueLength);
|
||||
} else {
|
||||
$result[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
} elseif (\is_string($arg) || is_numeric($arg)) {
|
||||
return mb_substr((string) $arg, 0, $maxValueLength);
|
||||
} else {
|
||||
return $arg;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a certain frame should be marked as "in app" or not.
|
||||
*
|
||||
* @param string $file The file to check
|
||||
* @param string|null $functionName The name of the function
|
||||
*/
|
||||
private function isFrameInApp(string $file, ?string $functionName): bool
|
||||
{
|
||||
if (self::INTERNAL_FRAME_FILENAME === $file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null !== $functionName && 0 === strpos($functionName, 'Sentry\\')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$projectRoot = $this->options->getProjectRoot();
|
||||
$excludedAppPaths = $this->options->getInAppExcludedPaths();
|
||||
$includedAppPaths = $this->options->getInAppIncludedPaths();
|
||||
$absoluteFilePath = @realpath($file) ?: $file;
|
||||
$isInApp = true;
|
||||
|
||||
if (null !== $projectRoot) {
|
||||
$isInApp = 0 === mb_strpos($absoluteFilePath, $projectRoot);
|
||||
}
|
||||
|
||||
foreach ($excludedAppPaths as $excludedAppPath) {
|
||||
if (0 === mb_strpos($absoluteFilePath, $excludedAppPath)) {
|
||||
$isInApp = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($includedAppPaths as $includedAppPath) {
|
||||
if (0 === mb_strpos($absoluteFilePath, $includedAppPath)) {
|
||||
$isInApp = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $isInApp;
|
||||
}
|
||||
}
|
||||
245
vendor/sentry/sentry/src/State/Hub.php
vendored
Normal file
245
vendor/sentry/sentry/src/State/Hub.php
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\State;
|
||||
|
||||
use Sentry\Breadcrumb;
|
||||
use Sentry\ClientInterface;
|
||||
use Sentry\Integration\IntegrationInterface;
|
||||
use Sentry\SentrySdk;
|
||||
use Sentry\Severity;
|
||||
|
||||
/**
|
||||
* This class is a basic implementation of the {@see HubInterface} interface.
|
||||
*/
|
||||
final class Hub implements HubInterface
|
||||
{
|
||||
/**
|
||||
* @var Layer[] The stack of client/scope pairs
|
||||
*/
|
||||
private $stack = [];
|
||||
|
||||
/**
|
||||
* @var string|null The ID of the last captured event
|
||||
*/
|
||||
private $lastEventId;
|
||||
|
||||
/**
|
||||
* Hub constructor.
|
||||
*
|
||||
* @param ClientInterface|null $client The client bound to the hub
|
||||
* @param Scope|null $scope The scope bound to the hub
|
||||
*/
|
||||
public function __construct(?ClientInterface $client = null, ?Scope $scope = null)
|
||||
{
|
||||
$this->stack[] = new Layer($client, $scope ?? new Scope());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClient(): ?ClientInterface
|
||||
{
|
||||
return $this->getStackTop()->getClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLastEventId(): ?string
|
||||
{
|
||||
return $this->lastEventId;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function pushScope(): Scope
|
||||
{
|
||||
$clonedScope = clone $this->getScope();
|
||||
|
||||
$this->stack[] = new Layer($this->getClient(), $clonedScope);
|
||||
|
||||
return $clonedScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function popScope(): bool
|
||||
{
|
||||
if (1 === \count($this->stack)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return null !== array_pop($this->stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withScope(callable $callback): void
|
||||
{
|
||||
$scope = $this->pushScope();
|
||||
|
||||
try {
|
||||
$callback($scope);
|
||||
} finally {
|
||||
$this->popScope();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function configureScope(callable $callback): void
|
||||
{
|
||||
$callback($this->getScope());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function bindClient(ClientInterface $client): void
|
||||
{
|
||||
$layer = $this->getStackTop();
|
||||
$layer->setClient($client);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function captureMessage(string $message, ?Severity $level = null): ?string
|
||||
{
|
||||
$client = $this->getClient();
|
||||
|
||||
if (null !== $client) {
|
||||
return $this->lastEventId = $client->captureMessage($message, $level, $this->getScope());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function captureException(\Throwable $exception): ?string
|
||||
{
|
||||
$client = $this->getClient();
|
||||
|
||||
if (null !== $client) {
|
||||
return $this->lastEventId = $client->captureException($exception, $this->getScope());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function captureEvent(array $payload): ?string
|
||||
{
|
||||
$client = $this->getClient();
|
||||
|
||||
if (null !== $client) {
|
||||
return $this->lastEventId = $client->captureEvent($payload, $this->getScope());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function captureLastError(): ?string
|
||||
{
|
||||
$client = $this->getClient();
|
||||
|
||||
if (null !== $client) {
|
||||
return $this->lastEventId = $client->captureLastError($this->getScope());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addBreadcrumb(Breadcrumb $breadcrumb): bool
|
||||
{
|
||||
$client = $this->getClient();
|
||||
|
||||
if (null === $client) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$options = $client->getOptions();
|
||||
$beforeBreadcrumbCallback = $options->getBeforeBreadcrumbCallback();
|
||||
$maxBreadcrumbs = $options->getMaxBreadcrumbs();
|
||||
|
||||
if ($maxBreadcrumbs <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$breadcrumb = $beforeBreadcrumbCallback($breadcrumb);
|
||||
|
||||
if (null !== $breadcrumb) {
|
||||
$this->getScope()->addBreadcrumb($breadcrumb, $maxBreadcrumbs);
|
||||
}
|
||||
|
||||
return null !== $breadcrumb;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getCurrent(): HubInterface
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since version 2.2 and will be removed in 3.0. Use SentrySdk::getCurrentHub() instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return SentrySdk::getCurrentHub();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function setCurrent(HubInterface $hub): HubInterface
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since version 2.2 and will be removed in 3.0. Use SentrySdk::setCurrentHub() instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
SentrySdk::setCurrentHub($hub);
|
||||
|
||||
return $hub;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIntegration(string $className): ?IntegrationInterface
|
||||
{
|
||||
$client = $this->getClient();
|
||||
|
||||
if (null !== $client) {
|
||||
return $client->getIntegration($className);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the scope bound to the top of the stack.
|
||||
*/
|
||||
private function getScope(): Scope
|
||||
{
|
||||
return $this->getStackTop()->getScope();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the topmost client/layer pair in the stack.
|
||||
*/
|
||||
private function getStackTop(): Layer
|
||||
{
|
||||
return $this->stack[\count($this->stack) - 1];
|
||||
}
|
||||
}
|
||||
183
vendor/sentry/sentry/src/State/HubAdapter.php
vendored
Normal file
183
vendor/sentry/sentry/src/State/HubAdapter.php
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\State;
|
||||
|
||||
use Sentry\Breadcrumb;
|
||||
use Sentry\ClientInterface;
|
||||
use Sentry\Integration\IntegrationInterface;
|
||||
use Sentry\SentrySdk;
|
||||
use Sentry\Severity;
|
||||
|
||||
/**
|
||||
* An implementation of {@see HubInterface} that uses {@see SentrySdk} internally
|
||||
* to manage the current hub.
|
||||
*/
|
||||
final class HubAdapter implements HubInterface
|
||||
{
|
||||
/**
|
||||
* @var self|null The single instance which forwards all calls to {@see SentrySdk}
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of this class. This is a singleton, so once initialized
|
||||
* you will always get the same instance.
|
||||
*/
|
||||
public static function getInstance(): self
|
||||
{
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClient(): ?ClientInterface
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->getClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLastEventId(): ?string
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->getLastEventId();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function pushScope(): Scope
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->pushScope();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function popScope(): bool
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->popScope();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withScope(callable $callback): void
|
||||
{
|
||||
SentrySdk::getCurrentHub()->withScope($callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function configureScope(callable $callback): void
|
||||
{
|
||||
SentrySdk::getCurrentHub()->configureScope($callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function bindClient(ClientInterface $client): void
|
||||
{
|
||||
SentrySdk::getCurrentHub()->bindClient($client);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function captureMessage(string $message, ?Severity $level = null): ?string
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->captureMessage($message, $level);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function captureException(\Throwable $exception): ?string
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->captureException($exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function captureEvent(array $payload): ?string
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->captureEvent($payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function captureLastError(): ?string
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->captureLastError();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addBreadcrumb(Breadcrumb $breadcrumb): bool
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->addBreadcrumb($breadcrumb);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getCurrent(): HubInterface
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since version 2.2 and will be removed in 3.0. Use SentrySdk::getCurrentHub() instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return SentrySdk::getCurrentHub();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function setCurrent(HubInterface $hub): HubInterface
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since version 2.2 and will be removed in 3.0. Use SentrySdk::getCurrentHub() instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return SentrySdk::setCurrentHub($hub);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIntegration(string $className): ?IntegrationInterface
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->getIntegration($className);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://www.php.net/manual/en/language.oop5.cloning.php#object.clone
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
throw new \BadMethodCallException('Cloning is forbidden.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://www.php.net/manual/en/language.oop5.magic.php#object.wakeup
|
||||
*/
|
||||
public function __wakeup()
|
||||
{
|
||||
throw new \BadMethodCallException('Unserializing instances of this class is forbidden.');
|
||||
}
|
||||
}
|
||||
138
vendor/sentry/sentry/src/State/HubInterface.php
vendored
Normal file
138
vendor/sentry/sentry/src/State/HubInterface.php
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\State;
|
||||
|
||||
use Sentry\Breadcrumb;
|
||||
use Sentry\ClientInterface;
|
||||
use Sentry\Integration\IntegrationInterface;
|
||||
use Sentry\Severity;
|
||||
|
||||
/**
|
||||
* This interface represent the class which is responsible for maintaining a
|
||||
* stack of pairs of clients and scopes. It is the main entry point to talk
|
||||
* with the Sentry client.
|
||||
*/
|
||||
interface HubInterface
|
||||
{
|
||||
/**
|
||||
* Gets the client bound to the top of the stack.
|
||||
*/
|
||||
public function getClient(): ?ClientInterface;
|
||||
|
||||
/**
|
||||
* Gets the ID of the last captured event.
|
||||
*/
|
||||
public function getLastEventId(): ?string;
|
||||
|
||||
/**
|
||||
* Creates a new scope to store context information that will be layered on
|
||||
* top of the current one. It is isolated, i.e. all breadcrumbs and context
|
||||
* information added to this scope will be removed once the scope ends. Be
|
||||
* sure to always remove this scope with {@see Hub::popScope} when the
|
||||
* operation finishes or throws.
|
||||
*/
|
||||
public function pushScope(): Scope;
|
||||
|
||||
/**
|
||||
* Removes a previously pushed scope from the stack. This restores the state
|
||||
* before the scope was pushed. All breadcrumbs and context information added
|
||||
* since the last call to {@see Hub::pushScope} are discarded.
|
||||
*/
|
||||
public function popScope(): bool;
|
||||
|
||||
/**
|
||||
* Creates a new scope with and executes the given operation within. The scope
|
||||
* is automatically removed once the operation finishes or throws.
|
||||
*
|
||||
* @param callable $callback The callback to be executed
|
||||
*/
|
||||
public function withScope(callable $callback): void;
|
||||
|
||||
/**
|
||||
* Calls the given callback passing to it the current scope so that any
|
||||
* operation can be run within its context.
|
||||
*
|
||||
* @param callable $callback The callback to be executed
|
||||
*/
|
||||
public function configureScope(callable $callback): void;
|
||||
|
||||
/**
|
||||
* Binds the given client to the current scope.
|
||||
*
|
||||
* @param ClientInterface $client The client
|
||||
*/
|
||||
public function bindClient(ClientInterface $client): void;
|
||||
|
||||
/**
|
||||
* Captures a message event and sends it to Sentry.
|
||||
*
|
||||
* @param string $message The message
|
||||
* @param Severity $level The severity level of the message
|
||||
*/
|
||||
public function captureMessage(string $message, ?Severity $level = null): ?string;
|
||||
|
||||
/**
|
||||
* Captures an exception event and sends it to Sentry.
|
||||
*
|
||||
* @param \Throwable $exception The exception
|
||||
*/
|
||||
public function captureException(\Throwable $exception): ?string;
|
||||
|
||||
/**
|
||||
* Captures a new event using the provided data.
|
||||
*
|
||||
* @param array<string, mixed> $payload The data of the event being captured
|
||||
*/
|
||||
public function captureEvent(array $payload): ?string;
|
||||
|
||||
/**
|
||||
* Captures an event that logs the last occurred error.
|
||||
*/
|
||||
public function captureLastError(): ?string;
|
||||
|
||||
/**
|
||||
* Records a new breadcrumb which will be attached to future events. They
|
||||
* will be added to subsequent events to provide more context on user's
|
||||
* actions prior to an error or crash.
|
||||
*
|
||||
* @param Breadcrumb $breadcrumb The breadcrumb to record
|
||||
*
|
||||
* @return bool Whether the breadcrumb was actually added to the current scope
|
||||
*/
|
||||
public function addBreadcrumb(Breadcrumb $breadcrumb): bool;
|
||||
|
||||
/**
|
||||
* Returns the current global Hub.
|
||||
*
|
||||
* @return HubInterface
|
||||
*
|
||||
* @deprecated since version 2.2, to be removed in 3.0
|
||||
*/
|
||||
public static function getCurrent(): self;
|
||||
|
||||
/**
|
||||
* Sets the Hub as the current.
|
||||
*
|
||||
* @param HubInterface $hub The Hub that will become the current one
|
||||
*
|
||||
* @return HubInterface
|
||||
*
|
||||
* @deprecated since version 2.2, to be removed in 3.0
|
||||
*/
|
||||
public static function setCurrent(self $hub): self;
|
||||
|
||||
/**
|
||||
* Gets the integration whose FQCN matches the given one if it's available on the current client.
|
||||
*
|
||||
* @param string $className The FQCN of the integration
|
||||
*
|
||||
* @psalm-template T of IntegrationInterface
|
||||
*
|
||||
* @psalm-param class-string<T> $className
|
||||
*
|
||||
* @psalm-return T|null
|
||||
*/
|
||||
public function getIntegration(string $className): ?IntegrationInterface;
|
||||
}
|
||||
82
vendor/sentry/sentry/src/State/Layer.php
vendored
Normal file
82
vendor/sentry/sentry/src/State/Layer.php
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\State;
|
||||
|
||||
use Sentry\ClientInterface;
|
||||
|
||||
/**
|
||||
* This class holds a pair of client and scope instances for each element in the
|
||||
* stack of a {@see Hub}.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Layer
|
||||
{
|
||||
/**
|
||||
* @var ClientInterface|null The client held by this layer
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @var Scope The scope held by this layer
|
||||
*/
|
||||
private $scope;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ClientInterface|null $client The client held by this layer
|
||||
* @param Scope $scope The scope held by this layer
|
||||
*/
|
||||
public function __construct(?ClientInterface $client, Scope $scope)
|
||||
{
|
||||
$this->client = $client;
|
||||
$this->scope = $scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the client held by this layer.
|
||||
*/
|
||||
public function getClient(): ?ClientInterface
|
||||
{
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the client held by this layer.
|
||||
*
|
||||
* @param ClientInterface|null $client The client instance
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setClient(?ClientInterface $client): self
|
||||
{
|
||||
$this->client = $client;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the scope held by this layer.
|
||||
*/
|
||||
public function getScope(): Scope
|
||||
{
|
||||
return $this->scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scope held by this layer.
|
||||
*
|
||||
* @param Scope $scope The scope instance
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setScope(Scope $scope): self
|
||||
{
|
||||
$this->scope = $scope;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
339
vendor/sentry/sentry/src/State/Scope.php
vendored
Normal file
339
vendor/sentry/sentry/src/State/Scope.php
vendored
Normal file
@@ -0,0 +1,339 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\State;
|
||||
|
||||
use Sentry\Breadcrumb;
|
||||
use Sentry\Context\Context;
|
||||
use Sentry\Context\TagsContext;
|
||||
use Sentry\Context\UserContext;
|
||||
use Sentry\Event;
|
||||
use Sentry\Severity;
|
||||
|
||||
/**
|
||||
* The scope holds data that should implicitly be sent with Sentry events. It
|
||||
* can hold context data, extra parameters, level overrides, fingerprints etc.
|
||||
*/
|
||||
final class Scope
|
||||
{
|
||||
/**
|
||||
* @var Breadcrumb[] The list of breadcrumbs recorded in this scope
|
||||
*/
|
||||
private $breadcrumbs = [];
|
||||
|
||||
/**
|
||||
* @var UserContext The user data associated to this scope
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* @var array<string, array<string, mixed>> The list of contexts associated to this scope
|
||||
*/
|
||||
private $contexts = [];
|
||||
|
||||
/**
|
||||
* @var TagsContext The list of tags associated to this scope
|
||||
*/
|
||||
private $tags;
|
||||
|
||||
/**
|
||||
* @var Context<mixed> A set of extra data associated to this scope
|
||||
*/
|
||||
private $extra;
|
||||
|
||||
/**
|
||||
* @var string[] List of fingerprints used to group events together in
|
||||
* Sentry
|
||||
*/
|
||||
private $fingerprint = [];
|
||||
|
||||
/**
|
||||
* @var Severity|null The severity to associate to the events captured in
|
||||
* this scope
|
||||
*/
|
||||
private $level;
|
||||
|
||||
/**
|
||||
* @var callable[] List of event processors
|
||||
*/
|
||||
private $eventProcessors = [];
|
||||
|
||||
/**
|
||||
* @var callable[] List of event processors
|
||||
*/
|
||||
private static $globalEventProcessors = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->user = new UserContext();
|
||||
$this->tags = new TagsContext();
|
||||
$this->extra = new Context();
|
||||
$this->contexts = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new tag in the tags context.
|
||||
*
|
||||
* @param string $key The key that uniquely identifies the tag
|
||||
* @param string $value The value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTag(string $key, string $value): self
|
||||
{
|
||||
$this->tags[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the given tags into the current tags context.
|
||||
*
|
||||
* @param array<string, string> $tags The tags to merge into the current context
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTags(array $tags): self
|
||||
{
|
||||
$this->tags->merge($tags);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets context data with the given name.
|
||||
*
|
||||
* @param string $name The name that uniquely identifies the context
|
||||
* @param array<string, mixed> $value The value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setContext(string $name, array $value): self
|
||||
{
|
||||
$this->contexts[$name] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the context from the scope.
|
||||
*
|
||||
* @param string $name The name that uniquely identifies the context
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeContext(string $name): self
|
||||
{
|
||||
unset($this->contexts[$name]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new information in the extra context.
|
||||
*
|
||||
* @param string $key The key that uniquely identifies the information
|
||||
* @param mixed $value The value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setExtra(string $key, $value): self
|
||||
{
|
||||
$this->extra[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the given data into the current extras context.
|
||||
*
|
||||
* @param array<string, mixed> $extras Data to merge into the current context
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setExtras(array $extras): self
|
||||
{
|
||||
$this->extra->merge($extras);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given data in the user context.
|
||||
*
|
||||
* @param array<string, mixed> $data The data
|
||||
* @param bool $merge If true, $data will be merged into user context instead of replacing it
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setUser(array $data, bool $merge = false): self
|
||||
{
|
||||
if ($merge) {
|
||||
$this->user->merge($data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@trigger_error('Replacing the data is deprecated since version 2.3 and will stop working from version 3.0. Set the second argument to `true` to merge the data instead.', E_USER_DEPRECATED);
|
||||
|
||||
$this->user->replaceData($data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of strings used to dictate the deduplication of this event.
|
||||
*
|
||||
* @param string[] $fingerprint The fingerprint values
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFingerprint(array $fingerprint): self
|
||||
{
|
||||
$this->fingerprint = $fingerprint;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the severity to apply to all events captured in this scope.
|
||||
*
|
||||
* @param Severity|null $level The severity
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setLevel(?Severity $level): self
|
||||
{
|
||||
$this->level = $level;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given breadcrumb to the scope.
|
||||
*
|
||||
* @param Breadcrumb $breadcrumb The breadcrumb to add
|
||||
* @param int $maxBreadcrumbs The maximum number of breadcrumbs to record
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addBreadcrumb(Breadcrumb $breadcrumb, int $maxBreadcrumbs = 100): self
|
||||
{
|
||||
$this->breadcrumbs[] = $breadcrumb;
|
||||
$this->breadcrumbs = \array_slice($this->breadcrumbs, -$maxBreadcrumbs);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all the breadcrumbs.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function clearBreadcrumbs(): self
|
||||
{
|
||||
$this->breadcrumbs = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new event processor that will be called after {@see Scope::applyToEvent}
|
||||
* finished its work.
|
||||
*
|
||||
* @param callable $eventProcessor The event processor
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addEventProcessor(callable $eventProcessor): self
|
||||
{
|
||||
$this->eventProcessors[] = $eventProcessor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new event processor that will be called after {@see Scope::applyToEvent}
|
||||
* finished its work.
|
||||
*
|
||||
* @param callable $eventProcessor The event processor
|
||||
*/
|
||||
public static function addGlobalEventProcessor(callable $eventProcessor): void
|
||||
{
|
||||
self::$globalEventProcessors[] = $eventProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the scope and resets any data it contains.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function clear(): self
|
||||
{
|
||||
$this->tags->clear();
|
||||
$this->extra->clear();
|
||||
$this->user->clear();
|
||||
|
||||
$this->level = null;
|
||||
$this->fingerprint = [];
|
||||
$this->breadcrumbs = [];
|
||||
$this->contexts = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the current context and fingerprint to the event. If the event has
|
||||
* already some breadcrumbs on it, the ones from this scope won't get merged.
|
||||
*
|
||||
* @param Event $event The event object that will be enriched with scope data
|
||||
* @param array<string, mixed> $payload The raw payload of the event that will be propagated to the event processors
|
||||
*/
|
||||
public function applyToEvent(Event $event, array $payload): ?Event
|
||||
{
|
||||
if (empty($event->getFingerprint())) {
|
||||
$event->setFingerprint($this->fingerprint);
|
||||
}
|
||||
|
||||
if (empty($event->getBreadcrumbs())) {
|
||||
$event->setBreadcrumb($this->breadcrumbs);
|
||||
}
|
||||
|
||||
if (null !== $this->level) {
|
||||
$event->setLevel($this->level);
|
||||
}
|
||||
|
||||
$event->getTagsContext()->merge($this->tags->toArray());
|
||||
$event->getExtraContext()->merge($this->extra->toArray());
|
||||
$event->getUserContext()->merge($this->user->toArray());
|
||||
|
||||
foreach (array_merge($this->contexts, $event->getContexts()) as $name => $data) {
|
||||
$event->setContext($name, $data);
|
||||
}
|
||||
|
||||
foreach (array_merge(self::$globalEventProcessors, $this->eventProcessors) as $processor) {
|
||||
$event = $processor($event, $payload);
|
||||
|
||||
if (null === $event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$event instanceof Event) {
|
||||
throw new \InvalidArgumentException(sprintf('The event processor must return null or an instance of the %s class', Event::class));
|
||||
}
|
||||
}
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
$this->user = clone $this->user;
|
||||
$this->tags = clone $this->tags;
|
||||
$this->extra = clone $this->extra;
|
||||
}
|
||||
}
|
||||
23
vendor/sentry/sentry/src/Transport/ClosableTransportInterface.php
vendored
Normal file
23
vendor/sentry/sentry/src/Transport/ClosableTransportInterface.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Transport;
|
||||
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
|
||||
/**
|
||||
* All classes implementing this interface will support sending events on-demand.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
interface ClosableTransportInterface
|
||||
{
|
||||
/**
|
||||
* Waits until all pending requests have been sent or the timeout expires.
|
||||
*
|
||||
* @param int|null $timeout Maximum time in seconds before the sending
|
||||
* operation is interrupted
|
||||
*/
|
||||
public function close(?int $timeout = null): PromiseInterface;
|
||||
}
|
||||
65
vendor/sentry/sentry/src/Transport/DefaultTransportFactory.php
vendored
Normal file
65
vendor/sentry/sentry/src/Transport/DefaultTransportFactory.php
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Transport;
|
||||
|
||||
use Http\Message\MessageFactory as MessageFactoryInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Sentry\HttpClient\HttpClientFactoryInterface;
|
||||
use Sentry\Options;
|
||||
|
||||
/**
|
||||
* This class is the default implementation of the {@see TransportFactoryInterface}
|
||||
* interface.
|
||||
*/
|
||||
final class DefaultTransportFactory implements TransportFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @var MessageFactoryInterface The PSR-7 message factory
|
||||
*/
|
||||
private $messageFactory;
|
||||
|
||||
/**
|
||||
* @var HttpClientFactoryInterface The factory to create the HTTP client
|
||||
*/
|
||||
private $httpClientFactory;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface|null A PSR-3 logger
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param MessageFactoryInterface $messageFactory The PSR-7 message factory
|
||||
* @param HttpClientFactoryInterface $httpClientFactory The HTTP client factory
|
||||
* @param LoggerInterface|null $logger A PSR-3 logger
|
||||
*/
|
||||
public function __construct(MessageFactoryInterface $messageFactory, HttpClientFactoryInterface $httpClientFactory, ?LoggerInterface $logger = null)
|
||||
{
|
||||
$this->messageFactory = $messageFactory;
|
||||
$this->httpClientFactory = $httpClientFactory;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function create(Options $options): TransportInterface
|
||||
{
|
||||
if (null === $options->getDsn(false)) {
|
||||
return new NullTransport();
|
||||
}
|
||||
|
||||
return new HttpTransport(
|
||||
$options,
|
||||
$this->httpClientFactory->create($options),
|
||||
$this->messageFactory,
|
||||
true,
|
||||
false,
|
||||
$this->logger
|
||||
);
|
||||
}
|
||||
}
|
||||
198
vendor/sentry/sentry/src/Transport/HttpTransport.php
vendored
Normal file
198
vendor/sentry/sentry/src/Transport/HttpTransport.php
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Transport;
|
||||
|
||||
use GuzzleHttp\Promise\EachPromise;
|
||||
use GuzzleHttp\Promise\FulfilledPromise;
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
use Http\Client\HttpAsyncClient as HttpAsyncClientInterface;
|
||||
use Http\Message\RequestFactory as RequestFactoryInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Sentry\Dsn;
|
||||
use Sentry\Event;
|
||||
use Sentry\Options;
|
||||
use Sentry\Util\JSON;
|
||||
|
||||
/**
|
||||
* This transport sends the events using a syncronous HTTP client that will
|
||||
* delay sending of the requests until the shutdown of the application.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class HttpTransport implements TransportInterface, ClosableTransportInterface
|
||||
{
|
||||
/**
|
||||
* @var Options The Sentry client options
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @var HttpAsyncClientInterface The HTTP client
|
||||
*/
|
||||
private $httpClient;
|
||||
|
||||
/**
|
||||
* @var RequestFactoryInterface The PSR-7 request factory
|
||||
*/
|
||||
private $requestFactory;
|
||||
|
||||
/**
|
||||
* @var array<array<mixed>> The list of pending requests
|
||||
*
|
||||
* @psalm-var array<array{\Psr\Http\Message\RequestInterface, Event}>
|
||||
*/
|
||||
private $pendingRequests = [];
|
||||
|
||||
/**
|
||||
* @var bool Flag indicating whether the sending of the events should be
|
||||
* delayed until the shutdown of the application
|
||||
*/
|
||||
private $delaySendingUntilShutdown = false;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface A PSR-3 logger
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Options $options The Sentry client configuration
|
||||
* @param HttpAsyncClientInterface $httpClient The HTTP client
|
||||
* @param RequestFactoryInterface $requestFactory The PSR-7 request factory
|
||||
* @param bool $delaySendingUntilShutdown This flag controls whether to delay
|
||||
* sending of the events until the shutdown
|
||||
* of the application
|
||||
* @param bool $triggerDeprecation Flag controlling whether to throw
|
||||
* a deprecation if the transport is
|
||||
* used relying on the deprecated behavior
|
||||
* of delaying the sending of the events
|
||||
* until the shutdown of the application
|
||||
* @param LoggerInterface|null $logger An instance of a PSR-3 logger
|
||||
*/
|
||||
public function __construct(
|
||||
Options $options,
|
||||
HttpAsyncClientInterface $httpClient,
|
||||
RequestFactoryInterface $requestFactory,
|
||||
bool $delaySendingUntilShutdown = true,
|
||||
bool $triggerDeprecation = true,
|
||||
?LoggerInterface $logger = null
|
||||
) {
|
||||
if ($delaySendingUntilShutdown && $triggerDeprecation) {
|
||||
@trigger_error(sprintf('Delaying the sending of the events using the "%s" class is deprecated since version 2.2 and will not work in 3.0.', __CLASS__), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->options = $options;
|
||||
$this->httpClient = $httpClient;
|
||||
$this->requestFactory = $requestFactory;
|
||||
$this->delaySendingUntilShutdown = $delaySendingUntilShutdown;
|
||||
$this->logger = $logger ?? new NullLogger();
|
||||
|
||||
// By calling the cleanupPendingRequests function from a shutdown function
|
||||
// registered inside another shutdown function we can be confident that it
|
||||
// will be executed last
|
||||
register_shutdown_function('register_shutdown_function', \Closure::fromCallable([$this, 'cleanupPendingRequests']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor. Ensures that all pending requests ends before destroying this
|
||||
* object instance.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->cleanupPendingRequests();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function send(Event $event): ?string
|
||||
{
|
||||
$dsn = $this->options->getDsn(false);
|
||||
|
||||
if (!$dsn instanceof Dsn) {
|
||||
throw new \RuntimeException(sprintf('The DSN option must be set to use the "%s" transport.', self::class));
|
||||
}
|
||||
|
||||
$request = $this->requestFactory->createRequest(
|
||||
'POST',
|
||||
$dsn->getStoreApiEndpointUrl(),
|
||||
['Content-Type' => 'application/json'],
|
||||
JSON::encode($event->toArray())
|
||||
);
|
||||
|
||||
if ($this->delaySendingUntilShutdown) {
|
||||
$this->pendingRequests[] = [$request, $event];
|
||||
} else {
|
||||
try {
|
||||
$this->httpClient->sendAsyncRequest($request)->wait();
|
||||
} catch (\Throwable $exception) {
|
||||
$this->logger->error(
|
||||
sprintf('Failed to send the event to Sentry. Reason: "%s".', $exception->getMessage()),
|
||||
[
|
||||
'exception' => $exception,
|
||||
'event' => $event,
|
||||
]
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return (string) $event->getId(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function close(?int $timeout = null): PromiseInterface
|
||||
{
|
||||
$this->cleanupPendingRequests();
|
||||
|
||||
return new FulfilledPromise(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the pending requests. Any error that occurs will be ignored.
|
||||
*
|
||||
* @deprecated since version 2.2.3, to be removed in 3.0. Even though this
|
||||
* method is `private` we cannot delete it because it's used
|
||||
* in some old versions of the `sentry-laravel` package using
|
||||
* tricky code involving reflection and Closure binding
|
||||
*/
|
||||
private function cleanupPendingRequests(): void
|
||||
{
|
||||
$requestGenerator = function (): \Generator {
|
||||
foreach ($this->pendingRequests as $key => $data) {
|
||||
yield $key => $this->httpClient->sendAsyncRequest($data[0]);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
$eachPromise = new EachPromise($requestGenerator(), [
|
||||
'concurrency' => 30,
|
||||
'rejected' => function (\Throwable $exception, int $requestIndex): void {
|
||||
$this->logger->error(
|
||||
sprintf('Failed to send the event to Sentry. Reason: "%s".', $exception->getMessage()),
|
||||
[
|
||||
'exception' => $exception,
|
||||
'event' => $this->pendingRequests[$requestIndex][1],
|
||||
]
|
||||
);
|
||||
},
|
||||
]);
|
||||
|
||||
$eachPromise->promise()->wait();
|
||||
} catch (\Throwable $exception) {
|
||||
$this->logger->error(
|
||||
sprintf('Failed to send the event to Sentry. Reason: "%s".', $exception->getMessage()),
|
||||
['exception' => $exception]
|
||||
);
|
||||
}
|
||||
|
||||
$this->pendingRequests = [];
|
||||
}
|
||||
}
|
||||
25
vendor/sentry/sentry/src/Transport/NullTransport.php
vendored
Normal file
25
vendor/sentry/sentry/src/Transport/NullTransport.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Transport;
|
||||
|
||||
use Sentry\Event;
|
||||
|
||||
/**
|
||||
* This transport fakes the sending of events by just ignoring them.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*
|
||||
* @final since 2.3
|
||||
*/
|
||||
class NullTransport implements TransportInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function send(Event $event): ?string
|
||||
{
|
||||
return (string) $event->getId(false);
|
||||
}
|
||||
}
|
||||
51
vendor/sentry/sentry/src/Transport/SpoolTransport.php
vendored
Normal file
51
vendor/sentry/sentry/src/Transport/SpoolTransport.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Transport;
|
||||
|
||||
use Sentry\Event;
|
||||
use Sentry\Spool\SpoolInterface;
|
||||
|
||||
/**
|
||||
* This transport stores the events in a queue to send them later.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class SpoolTransport implements TransportInterface
|
||||
{
|
||||
/**
|
||||
* @var SpoolInterface The spool instance
|
||||
*/
|
||||
private $spool;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param SpoolInterface $spool The spool instance
|
||||
*/
|
||||
public function __construct(SpoolInterface $spool)
|
||||
{
|
||||
$this->spool = $spool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the spool.
|
||||
*/
|
||||
public function getSpool(): SpoolInterface
|
||||
{
|
||||
return $this->spool;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function send(Event $event): ?string
|
||||
{
|
||||
if ($this->spool->queueEvent($event)) {
|
||||
return (string) $event->getId(false);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
21
vendor/sentry/sentry/src/Transport/TransportFactoryInterface.php
vendored
Normal file
21
vendor/sentry/sentry/src/Transport/TransportFactoryInterface.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Transport;
|
||||
|
||||
use Sentry\Options;
|
||||
|
||||
/**
|
||||
* This interface defines a contract for all classes willing to create instances
|
||||
* of the transport to use with the Sentry client.
|
||||
*/
|
||||
interface TransportFactoryInterface
|
||||
{
|
||||
/**
|
||||
* Creates a new instance of a transport that will be used to send events.
|
||||
*
|
||||
* @param Options $options The options of the Sentry client
|
||||
*/
|
||||
public function create(Options $options): TransportInterface;
|
||||
}
|
||||
25
vendor/sentry/sentry/src/Transport/TransportInterface.php
vendored
Normal file
25
vendor/sentry/sentry/src/Transport/TransportInterface.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Transport;
|
||||
|
||||
use Sentry\Event;
|
||||
|
||||
/**
|
||||
* This interface must be implemented by all classes willing to provide a way
|
||||
* of sending events to a Sentry server.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
interface TransportInterface
|
||||
{
|
||||
/**
|
||||
* Sends the given event.
|
||||
*
|
||||
* @param Event $event The event
|
||||
*
|
||||
* @return string|null Returns the ID of the event or `null` if it failed to be sent
|
||||
*/
|
||||
public function send(Event $event): ?string;
|
||||
}
|
||||
142
vendor/sentry/sentry/src/Util/JSON.php
vendored
Normal file
142
vendor/sentry/sentry/src/Util/JSON.php
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Util;
|
||||
|
||||
use Sentry\Exception\JsonException;
|
||||
|
||||
/**
|
||||
* This class provides some utility methods to encode/decode JSON data.
|
||||
*
|
||||
* @author Stefano Arlandini <sarlandini@alice.it>
|
||||
*/
|
||||
final class JSON
|
||||
{
|
||||
/**
|
||||
* Encodes the given data into JSON.
|
||||
*
|
||||
* @param mixed $data The data to encode
|
||||
* @param int $options Bitmask consisting of JSON_* constants
|
||||
* @param int $maxDepth The maximum depth allowed for serializing $data
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws JsonException If the encoding failed
|
||||
*/
|
||||
public static function encode($data, int $options = 0, int $maxDepth = 512)
|
||||
{
|
||||
$options |= JSON_UNESCAPED_UNICODE;
|
||||
|
||||
if (\PHP_VERSION_ID >= 70200) {
|
||||
/** @psalm-suppress UndefinedConstant */
|
||||
$options |= JSON_INVALID_UTF8_SUBSTITUTE;
|
||||
}
|
||||
|
||||
$encodedData = json_encode($data, $options);
|
||||
|
||||
// This should never happen on PHP >= 7.2 as the substitution of invalid
|
||||
// UTF-8 characters is done internally. On lower versions instead, we
|
||||
// try to sanitize the data ourselves before retrying encoding. If it
|
||||
// fails again we throw an exception as usual.
|
||||
if (JSON_ERROR_UTF8 === json_last_error()) {
|
||||
$encodedData = json_encode(self::sanitizeData($data, $maxDepth - 1), $options);
|
||||
}
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new JsonException(sprintf('Could not encode value into JSON format. Error was: "%s".', json_last_error_msg()));
|
||||
}
|
||||
|
||||
return $encodedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the given data from JSON.
|
||||
*
|
||||
* @param string $data The data to decode
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws JsonException If the decoding failed
|
||||
*/
|
||||
public static function decode(string $data)
|
||||
{
|
||||
$decodedData = json_decode($data, true);
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new JsonException(sprintf('Could not decode value from JSON format. Error was: "%s".', json_last_error_msg()));
|
||||
}
|
||||
|
||||
return $decodedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs sanity checks on data that shall be encoded to JSON.
|
||||
*
|
||||
* @param mixed $data The data to sanitize
|
||||
* @param int $maxDepth The maximum depth to walk through `$data`
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws JsonException If the value of $maxDepth is less than 0
|
||||
*/
|
||||
private static function sanitizeData($data, int $maxDepth)
|
||||
{
|
||||
if ($maxDepth < 0) {
|
||||
throw new JsonException('Reached the maximum depth limit while sanitizing the data.');
|
||||
}
|
||||
|
||||
if (\is_string($data)) {
|
||||
return self::convertStringToUtf8($data);
|
||||
} elseif (\is_array($data) || \is_object($data)) {
|
||||
$output = [];
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
if (\is_string($key)) {
|
||||
$key = self::convertStringToUtf8($key);
|
||||
}
|
||||
|
||||
if (\is_string($value)) {
|
||||
$value = self::convertStringToUtf8($value);
|
||||
} elseif (\is_array($value) || \is_object($value)) {
|
||||
// This check is here because the `Event::toArray()` method
|
||||
// is broken and doesn't return all child items as scalars
|
||||
// or objects/arrays, so the sanitification would fail (e.g.
|
||||
// on breadcrumb objects which do not expose public properties
|
||||
// to iterate on)
|
||||
if (\is_object($value) && method_exists($value, 'toArray')) {
|
||||
$value = $value->toArray();
|
||||
}
|
||||
|
||||
$value = self::sanitizeData($value, $maxDepth - 1);
|
||||
}
|
||||
|
||||
$output[$key] = $value;
|
||||
}
|
||||
|
||||
return \is_array($data) ? $output : (object) $output;
|
||||
} else {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string to UTF-8 to avoid errors during its encoding to
|
||||
* the JSON format.
|
||||
*
|
||||
* @param string $value The text to convert to UTF-8
|
||||
*/
|
||||
private static function convertStringToUtf8(string $value): string
|
||||
{
|
||||
$previousSubstituteCharacter = mb_substitute_character();
|
||||
$encoding = mb_detect_encoding($value, mb_detect_order(), true);
|
||||
|
||||
mb_substitute_character(0xfffd);
|
||||
|
||||
$value = mb_convert_encoding($value, 'UTF-8', $encoding ?: 'UTF-8');
|
||||
|
||||
mb_substitute_character($previousSubstituteCharacter);
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
37
vendor/sentry/sentry/src/Util/PHPVersion.php
vendored
Normal file
37
vendor/sentry/sentry/src/Util/PHPVersion.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry\Util;
|
||||
|
||||
/**
|
||||
* This class is an helper utility to parse the version of PHP and convert it
|
||||
* to a normalized form.
|
||||
*
|
||||
* @internal since version 2.4
|
||||
*/
|
||||
final class PHPVersion
|
||||
{
|
||||
private const VERSION_PARSING_REGEX = '/^(?<base>\d\.\d\.\d{1,2})(?<extra>-(beta|rc)-?(\d+)?(-dev)?)?/i';
|
||||
|
||||
/**
|
||||
* Parses the given string representing a PHP version and returns it in a
|
||||
* normalized form.
|
||||
*
|
||||
* @param string $version The string to parse
|
||||
*/
|
||||
public static function parseVersion(string $version = PHP_VERSION): string
|
||||
{
|
||||
if (!preg_match(self::VERSION_PARSING_REGEX, $version, $matches)) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
$version = $matches['base'];
|
||||
|
||||
if (isset($matches['extra'])) {
|
||||
$version .= $matches['extra'];
|
||||
}
|
||||
|
||||
return $version;
|
||||
}
|
||||
}
|
||||
90
vendor/sentry/sentry/src/functions.php
vendored
Normal file
90
vendor/sentry/sentry/src/functions.php
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sentry;
|
||||
|
||||
/**
|
||||
* Creates a new Client and Hub which will be set as current.
|
||||
*
|
||||
* @param array<string, mixed> $options The client options
|
||||
*/
|
||||
function init(array $options = []): void
|
||||
{
|
||||
$client = ClientBuilder::create($options)->getClient();
|
||||
|
||||
SentrySdk::init()->bindClient($client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures a message event and sends it to Sentry.
|
||||
*
|
||||
* @param string $message The message
|
||||
* @param Severity $level The severity level of the message
|
||||
*/
|
||||
function captureMessage(string $message, ?Severity $level = null): ?string
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->captureMessage($message, $level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures an exception event and sends it to Sentry.
|
||||
*
|
||||
* @param \Throwable $exception The exception
|
||||
*/
|
||||
function captureException(\Throwable $exception): ?string
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->captureException($exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures a new event using the provided data.
|
||||
*
|
||||
* @param array<string, mixed> $payload The data of the event being captured
|
||||
*/
|
||||
function captureEvent(array $payload): ?string
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->captureEvent($payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the most recent error (obtained with {@link error_get_last}).
|
||||
*/
|
||||
function captureLastError(): ?string
|
||||
{
|
||||
return SentrySdk::getCurrentHub()->captureLastError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Records a new breadcrumb which will be attached to future events. They
|
||||
* will be added to subsequent events to provide more context on user's
|
||||
* actions prior to an error or crash.
|
||||
*
|
||||
* @param Breadcrumb $breadcrumb The breadcrumb to record
|
||||
*/
|
||||
function addBreadcrumb(Breadcrumb $breadcrumb): void
|
||||
{
|
||||
SentrySdk::getCurrentHub()->addBreadcrumb($breadcrumb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the given callback passing to it the current scope so that any
|
||||
* operation can be run within its context.
|
||||
*
|
||||
* @param callable $callback The callback to be executed
|
||||
*/
|
||||
function configureScope(callable $callback): void
|
||||
{
|
||||
SentrySdk::getCurrentHub()->configureScope($callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new scope with and executes the given operation within. The scope
|
||||
* is automatically removed once the operation finishes or throws.
|
||||
*
|
||||
* @param callable $callback The callback to be executed
|
||||
*/
|
||||
function withScope(callable $callback): void
|
||||
{
|
||||
SentrySdk::getCurrentHub()->withScope($callback);
|
||||
}
|
||||
Reference in New Issue
Block a user