Skip to content

Commit

Permalink
NEW: Release 4.0:
Browse files Browse the repository at this point in the history
- Fixes #6 (Documents Sentry's "release" feature)
- Fixes #66 (Additional default tags)
- Fixes #68 (Upgrade to Sentry 3.x)
- Fixes #69 (INFO mis-reported as "ERROR")
- Added more examples to `usage.md`
- Added custom stacktrace feature & YML config
- Bumped composer PHP versions to include all versions of 7.x and 8.x
- Minor syntax formatting
- Ensure all tags+extras appear as per Sentry's format: lower-case with '.' separator
- Removed refs to Silverstripe 3 from README & moved config instructions into usage.md
- Added meta-data about the app in which the module is installed as a tag
- Fixed incorrectly-named scope key
- Adds guard around setting an empty context
- Removed redundant Exception subclass
- Simplified logic flow
  • Loading branch information
dcentrica committed Jul 16, 2021
1 parent 06df067 commit 64e573d
Show file tree
Hide file tree
Showing 13 changed files with 470 additions and 382 deletions.
6 changes: 5 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ matrix:
- php: 7.4
env:
- DB=MYSQL
- php: 8.0
env:
- DB=MYSQL

services:
- mysql
Expand All @@ -37,5 +40,6 @@ script:
- vendor/bin/phpunit --testsuite sentry

branches:
only:
only:
- master
- 4.0
59 changes: 14 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,38 @@
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/phptek/silverstripe-sentry/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/phptek/silverstripe-sentry/?branch=master)
[![License](https://poser.pugx.org/phptek/sentry/license.svg)](https://github.com/phptek/silverstripe-sentry/blob/master/LICENSE.md)

[Sentry](https://sentry.io) is an error and exception aggregation service. It takes your application's errors, aggregates them alongside configurable context and stores them for later analysis and debugging.
[Sentry](https://sentry.io) is an error and exception aggregation service. It takes your application's errors, aggregates them alongside configurable context and stores them for later analysis and debugging.

Imagine this: You see errors and exceptions before your clients do. The error > report > debug > patch > deploy cycle is therefore the most efficient it can possibly be.

This module binds Sentry.io and hosted Sentry installations, to the Monlog error logger in SilverStripe. If you've used systems like
This module binds Sentry.io and hosted Sentry installations, to the Monlog error logger in SilverStripe. If you've used systems like
[RayGun](https://raygun.com), [Rollbar](https://rollbar.com), [AirBrake](https://airbrake.io/) and [BugSnag](https://www.bugsnag.com/) before, you'll know roughly what to expect.

## Requirements
### SilverStripe Framework v4

* PHP >=7.0
* SilverStripe ^4.0
* `phptek/sentry` version 3.x
* `phptek/sentry` version 4.x (use 1.x for Silverstripe 3)

#### Setup:
## Setup:

composer require phptek/sentry:^3
composer require phptek/sentry:^4

### SilverStripe Framework v3

* PHP 5.4+, <=7.4
* SilverStripe > v3.1, < 4
* `phptek/sentry` version 1.x

#### Setup:

composer require phptek/sentry:^1

Notes:
## Notes:

* Versions 2.x and 3.x should work with the same Silverstripe v4 setups. v3 simply uses a newer version of the Sentry PHP SDK, and has a leaner codebase.
* Versions 2.x, 3.x and 4.x should work with the same Silverstripe v4 setups. v3+ simply use newer versions of the Sentry PHP SDK and have additional bugfixes and features.
* Version 3.x `SentryClientAdaptor` has been renamed to `SentryAdaptor` and `SentryLogWriter` was renamed to `SentryLogger`, so your existing configuration(s) may need to be updated accordingly.

Configure your application or site with the Sentry DSN:

### SilverStripe Framework v4

#### General Config ####
## Config

You can set your DSN as a first-class environment variable or via your project's `.env` file:

SENTRY_DSN="http://deacdf9dfedb24ccdce1b90017b39dca:deacdf9dfedb24ccdce1b90017b39dca@sentry.mydomain.nz/44"

Or you can set it in YML config, where you gain a little more flexibility and control:

The following will get you errors reported in all environment modes: `dev`, `test` and `live`:
The following will get you errors reported in all environment modes: `dev`, `test` and `live`:

---
Name: my-project-config-sentry
Expand All @@ -62,9 +48,9 @@ The following will get you errors reported in all environment modes: `dev`, `tes
# Example DSN only. Obviously you'll need to setup your own Sentry "Project"
dsn: http://deacdf9dfedb24ccdce1b90017b39dca:deacdf9dfedb24ccdce1b90017b39dca@sentry.mydomain.nz/44

#### Conditional Config ####
### Conditional Config

The following will get you errors reported just in `test` and `live` but not `dev`:
The following will get you errors reported just in `test` and `live` but not `dev`:

---
Name: my-project-config-sentry
Expand Down Expand Up @@ -97,18 +83,11 @@ The following will get you errors reported just in `test` and `live` but not `de
dsn: null
---

#### Proxies ####

Should your app require outgoing traffic to be passed through a proxy, the following config will work:
Please review the [usage docs](docs/usage.md) for further configuration and customisation options.

# Proxy constants
http_proxy:
host: '`MY_OUTBOUND_PROXY`'
port: '`MY_OUTBOUND_PROXY_PORT`'

Notes:
Notes:

* In module version 3.x you can silence errors from `Injector` where "test" and "live" envs have `http_proxy` set, but "dev" environments don't. Just set `null` as the value. This applies to all YML config where some envs have a setting and others don't. For example:
* You can silence errors from `Injector` where "test" and "live" envs have `http_proxy` set, but "dev" environments don't. Just set `null` as the value. This applies to all YML config where some envs have a setting and others don't. For example:

```
...
Expand All @@ -129,16 +108,6 @@ Notes:
After:
- 'sentry-config'

#### Log Level ####

You can set the minimum log-level you're interested in, using the `log_level` config, the module default is to report anything more severe than a `WARNING`:

```
PhpTek\Sentry\Handler\SentryHandler:
# One of the permitted severities: DEBUG|INFO|WARNING|ERROR|FATAL
log_level: ERROR
```

### SilverStripe Framework v3

YML Config:
Expand Down
4 changes: 0 additions & 4 deletions _config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
Name: sentry-config
---

PhpTek\Sentry\Log\SentryLogger:
dependencies:
adaptor: '%$PhpTek\Sentry\Adaptor\SentryAdaptor'

SilverStripe\Core\Injector\Injector:
Psr\Log\LoggerInterface:
calls:
Expand Down
8 changes: 5 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
"silverstripe/sentry": "*"
},
"require": {
"php": "^5.4|<7.5",
"sentry/sdk": "^2",
"php": "^7.4.0|^8",
"sentry/sdk": "^3",
"composer/package-versions-deprecated": "^1.11",
"silverstripe/framework": "^4"
},
"require-dev": {
Expand All @@ -36,7 +37,8 @@
}
},
"config": {
"process-timeout": 900
"process-timeout": 900,
"optimize-autoloader": true
},
"extra": {
"installer-name": "sentry"
Expand Down
193 changes: 193 additions & 0 deletions docs/en/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# Usage

Once setup, everytime an `Exception` is thrown or PHP itself shuts down via `trigger_error()` etc or you "manually" trigger a log message to be sent to Sentry, all available data is automatically sent to your remote Sentry instance.

In addition to the module simply reporting all thrown `Exception`s, resulting in a stacktrace in Sentry itself, you can use Sentry as a simple logger with all the benefits of Sentry's tags and grouping. See the examples below.

## Environment

For "manual" error-reporting, you can augment your message with some context. If an environment is not specified,
the default is to use the return value of `Director::get_environment_type()`.

SilverStripe 4 uses `Monolog` and individual handlers for logging. Once you instantiate a `Logger` object, you have access to `Monolog`'s public API.

$config = ['env' => 'live'];
$logger = Injector::inst()->createWithArgs(Logger::class, ['error-log'])
->pushHandler(SentryHandler::create());

// Send an `ERROR` level message
$logger->error($message, $config);

// Send a `WARN` level message
$logger->warning($message, $config);

// Send an `INFO` level message
$logger->info($message, $config);

## Log Levels

You can set the minimum log-level you're interested in, using the `log_level` config, the module default is to report anything more severe than a `DEBUG`:

```
PhpTek\Sentry\Handler\SentryHandler:
# One of the permitted severities: DEBUG|INFO|WARNING|ERROR|FATAL
log_level: ERROR
```

Building on top of the "manual" logging examples above, you can configure these to send only errors of a specific severity:

```
$logger = Injector::inst()->createWithArgs(Logger::class, ['error-log'])
->pushHandler(SentryHandler::create('INFO')); // Send errors >= INFO
$logger->info('TEST: INFO'); // Sent
$logger->warning('TEST: WARN'); // Sent
$logger->error('TEST: ERROR'); // Sent
```

```
$logger = Injector::inst()->createWithArgs(Logger::class, ['error-log'])
->pushHandler(SentryHandler::create('WARNING')); // Send errors >= WARNING
$logger->info('TEST: INFO'); // Not sent
$logger->warning('TEST: WARN'); // Sent
$logger->error('TEST: ERROR'); // Sent
```

```
$logger = Injector::inst()->createWithArgs(Logger::class, ['error-log'])
->pushHandler(SentryHandler::create('ERROR')); // Send errors >= ERROR
$logger->info('TEST: INFO'); // Not sent
$logger->warning('TEST: WARN'); // Not sent
$logger->error('TEST: ERROR'); // Sent
```

Further; passing a severity in this way trumps any YML config you have set:

YML:
```
PhpTek\Sentry\Handler\SentryHandler:
log_level: 'ERROR'
```

PHP:
```
$logger = Injector::inst()->createWithArgs(Logger::class, ['error-log'])
->pushHandler(SentryHandler::create()); // Send errors >= ERROR
$logger->info('TEST: INFO'); // Not sent
$logger->warning('TEST: WARN'); // Not sent
$logger->error('TEST: ERROR'); // Sent
```

PHP:
```
$logger = Injector::inst()->createWithArgs(Logger::class, ['error-log'])
->pushHandler(SentryHandler::create('INFO)); // Send errors >= INFO (despite what's set in YML)
$logger->info('TEST: INFO'); // Sent
$logger->warning('TEST: WARN'); // Sent
$logger->error('TEST: ERROR'); // Sent
```

## Tags and Extras

Sentry allows for custom key-value pairs to be recorded against each message that it is sent.
These are known as "tags" and "extras" which allows for fine-grained grouping and filtering of messages via the Sentry UI.

Note: It makes no sense to send hugely varying data in a tag. If it's unlikely that a tag you
wish to send is ever going to be repeated, don't send it as a tag. Look at using the "Extras" feature (also described below)
instead.

$config = [
// Appears in Sentry's "Details" tab on RHS and in the lozenges, located at the top
'env' => 'live',
// Appears in Sentry's "Tags" tab as its own block and in the lozenges on the "Details" tab, located at the top
'tags' => [
'Unique-ID' => 44
],
// Appears in Sentry's "Details" tab under "Additional Data"
extra => [
'Moon-Phase' => 'Full',
'Tummy-Status' => 'Empty',
'Cats' => 'Are furry'
]
];
$logger = Injector::inst()->createWithArgs(Logger::class, ['error-log'])
->pushHandler(SentryHandler::create(null, true, $config));

// Send an `ERROR` level message
$logger->error($message);

// Send a `WARN` level message
$logger->warning($message);

// Send an `INFO` level message
$logger->info($message);

// Alternative syntax to send an `ERROR` level message
$logger->log('ERROR', 'Help, my curry is too hot. I only asked for mild.');

The module comes with some pre-defined **tags** and **extras** that are always shown in the "Tags" tab and in the tags "lozenges" at the top of the main "Details" tab within Sentry itself:

### Default Tags

* **app**: A string containing the project's name as defined in `composer.json`, branch-name and commit
* **phptek.sentry.version**: The version of the `phptek/sentry` package installed
* **request.method**: The HTTP method used for the request that generated the Sentry message
* **request.type**: The type of request e.g. "Ajax"
* **silverstripe.framework.version**: The version of `silverstripe/framework` package installed
* **php.sapi**: The PHP SAPI in use at the time the message was sent to Sentry

### Default Extras

* **php.peak.memory**: The amount of peak memory (in Mb) consumed at the time the message was sent

### Default User Data

* **Email**: The value of the current Silverstripe user's `Member::Email` field (If not scrubbed in Sentry's settings)
* **ID**: The value of the current Silverstripe user's `Member::ID` field
* **IPAddress**: The value of the originating IP address of the request at the time the message was sent to Sentry

## Stacktraces

By default, the module will render Sentry's own stacktraces into Sentry's UI. However, you can configure the module to skip recording Silverstripe's own debugging internals as well as those of the module:

```
PhpTek\Sentry\Adaptor\SentryAdaptor:
custom_stacktrace: true
```

Note that this feature should be considered experimental/incomplete. It is unable to fully render method/function calls when the module is set in this mode.

## Releases

You can configure the module to send release information back to Sentry itself. This allows you to configure a Sentry project with a VCS repository like Bitbucket for example, which prompts Sentry to display detailed metadata about the given release.

```
PhpTek\Sentry\Adaptor\SentryAdaptor:
opts:
release: 2.1.4
```

Project maintainers don't really want to be manually modifying the release, each time a new one is created or deployed, so consider making this a placeholder and replacing it during a CI step e.g.

```
...
- step:
script:
- export CURRENT_VERSION=$( git branch | grep '\*' )
- sed -i 's#release: 0.0.0#release: $CURRENT_VERSION#' app/_config/logging.yml
...
```
## Proxies

Should your app require outgoing traffic to be passed through a proxy, the following config will work:

# Proxy constants
PhpTek\Sentry\Adaptor\SentryAdaptor:
opts:
http_proxy:
host: '`MY_OUTBOUND_PROXY`'
port: '`MY_OUTBOUND_PROXY_PORT`'
Loading

0 comments on commit 64e573d

Please sign in to comment.