Coder Social home page Coder Social logo

silverstripe-raygun's Introduction

Raygun integration for Silverstripe

This is a simple module that binds Raygun to the error & exception handler of Silverstripe.

Requirements

  • PHP ^8.1
  • Raygun4PHP ^2
  • Silverstripe Framework ^5

Support for Silverstripe 3 can be found in version ^1. Support for Silverstripe 4 can be found in versions ^2 and ^3.

Installation

composer require silverstripe/raygun

Configuration

Add the following to your .env file:

SS_RAYGUN_APP_KEY="dwhouq3845y98uiof=="

If you want to track JavaScript errors in CMS, you can activate LeftAndMainExtension in your project YAML configs:

---
Name: raygunning-left-and-main
---
SilverStripe\Admin\LeftAndMain:
  extensions:
    - SilverStripe\Raygun\LeftAndMainExtension

Set Log Level

You can define the error reporting level in your YAML config:

SilverStripe\Core\Injector\Injector:
  SilverStripe\Raygun\RaygunHandler:
    constructor:
      client: '%$Raygun4php\RaygunClient'
      level: 'error'

User tracking

By default, no user data will be sent to Raygun at all. You can choose to track logged-in members by setting some yml configuration:

---
After: raygun
---
Raygun4php\RaygunClient:
  disable_user_tracking: false

SilverStripe\Raygun\RaygunHandler:
  user_main_id_field: 'ID' #default: 'Email'. This is the "Identifier" in the Raygun app.
  user_include_firstname: true #default: false
  user_include_fullname: true #default: false
  user_include_email: true #default: false

Multiple Raygun API Keys (app keys)

You may have more than one Raygun integration, each of which could use custom API keys, different from the default one (set by SS_RAYGUN_APP_KEY). To do so you'll need to configure each one of them separately. Here are some examples:

# Here's an example of the LeftAndMainExtension using a custom raygun
# API Key, set through a custom environment variable (SS_CUSTOM_RAYGUN_APP_KEY)

---
Name: custom-raygun-leftnmain-extension
---
SilverStripe\Core\Injector\Injector:
  SilverStripe\Raygun\LeftAndMainExtension.custom:
    class: SilverStripe\Raygun\LeftAndMainExtension
    properties:
      # You'll have to set the SS_CUSTOM_RAYGUN_APP_KEY environment var
      CustomRaygunAppKey: '`SS_CUSTOM_RAYGUN_APP_KEY`'

---
Name: raygunning-left-and-main
After: custom-raygun-leftnmain-extension
---
SilverStripe\Admin\LeftAndMain:
  extensions:
    - SilverStripe\Raygun\LeftAndMainExtension.custom
# Here's an example of a custom Raygun handler for Monolog
# which uses API Key provided by a custom RaygunClientFactory

---
Name: custom-monolog-raygun-handler
---
SilverStripe\Core\Injector\Injector:
  SilverStripe\Raygun\RaygunClientFactory.custom:
    class: SilverStripe\Raygun\RaygunClientFactory
    properties:
      # You'll have to set the SS_CUSTOM_RAYGUN_APP_KEY environment var
      CustomRaygunAppKey: '`SS_CUSTOM_RAYGUN_APP_KEY`'

  Raygun4php\RaygunClient.custom:
    factory: '%$SilverStripe\Raygun\RaygunClientFactory.custom'

  SilverStripe\Raygun\RaygunHandler.custom:
    class: SilverStripe\Raygun\RaygunHandler
    constructor:
      client: '%$Raygun4php\RaygunClient.custom'
      level: 'debug'

  Psr\Log\LoggerInterface:
    calls:
      - [ pushHandler, [ '%$SilverStripe\Raygun\RaygunHandler.custom'] ]

Disable handler

The RaygunHandler is enabled by default when the SS_RAYGUN_APP_KEY environment variable is set. There may be some situations where you need that variable to be set but you don't want the handler enabled by default (e.g. you may not want the handler enabled in dev or test environments except when triggering some test exception via a BuildTask).

---
Only:
  environment: 'dev'
---
SilverStripe\Raygun\RaygunHandler:
  enabled: false

Then in your BuildTask you can enable that handler as required.

use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\BuildTask;
use SilverStripe\Raygun\RaygunHandler;

class TriggerTestExtensionTask extends BuildTask
{
    protected $title = 'Trigger Test Exception';

    protected $description = 'Throws an exception. Useful for checking raygun integration is working as expected.';

    /**
     * Throw a test exception that is directed through raygun.
     *
     * @param HTTPRequest $request
     */
    public function run($request)
    {
        $env = Director::get_environment_type();
        Config::modify()->set(RaygunHandler::class, 'enabled', true);
        throw new \Exception("Test exception thrown from '$env' environment.");
    }
}

Proxy

If you need to forward outgoing requests through a proxy (such as for sites hosted in CWP), you can set the proxy host and optional port via yaml config:

SilverStripe\Core\Injector\Injector:
  Raygun4php\RaygunClient:
    constructor:
      proxyHost: '`SS_OUTBOUND_PROXY`'
      proxyPort: '`SS_OUTBOUND_PROXY_PORT`'

Filtering

Raygun will send the following data:

  • $_POST
  • $_SERVER
  • $_GET (included in URL also)

By default we filter out some sensitive Silverstripe details which appear in the $_SERVER variable. These include:

  • SS_DATABASE_USERNAME
  • SS_DEFAULT_ADMIN_USERNAME
  • SS_RAYGUN_APP_KEY
  • Cookie information (through Cookie and HTTP_COOKIE)
  • Basic auth information (through PHP_AUTH_PW)
  • HTTP authorisation information (through Authorization and HTTP_AUTHORIZATION)
  • Anything containing PASSWORD, KEY, SECRET or TOKEN (case insensitive)

You will likely want to filter out other sensitive data such as credit cards, passwords etc. You can do this in your mysite/_config.php file. These rules are applied to $_SERVER, $_POST and $_GET data. All key comparisons are case insensitive.

Example implementation in mysite/_config.php:

<?php

$client = Injector::inst()->get(Raygun4php\RaygunClient::class);
$client->setFilterParams(array_merge($client->getFilterParams(), [
    'php_auth_pw' => true,
    '/password/i' => true,
	'Email' => function($key, $val) {
        return substr($val, 0, 5) . '...';
    }
]));

More information about accepted filtering formats is available in the Raygun4php documentation.

silverstripe-raygun's People

Contributors

adrexia avatar benmanu avatar chillu avatar chrispenny avatar dnsl48 avatar emteknetnz avatar guysartorelli avatar halkyon avatar ichaber avatar madmatt avatar mateusz avatar micmania1 avatar patbolo avatar robbieaverill avatar satrun77 avatar sumitramanga avatar timkung avatar wilr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

silverstripe-raygun's Issues

Documentation is not clear that Raygun error handling replaces default error handling

Logger configuration in _config/config.yml overrides the default LoggerInterface framework configuration, adding a "Handler", resulting in default logging handler no longer working.

SilverStripe\Core\Injector\Injector:
  Psr\Log\LoggerInterface:
    calls:
      - [ pushHandler, [ '%$SilverStripe\Raygun\RaygunHandler' ]]

Silverstripe Framework by default does not add any handlers to this interface which results in Monolog sending it to php://stderr by default.

https://github.com/silverstripe/silverstripe-framework/blob/4/_config/logging.yml#L19-L25

  # Default implementation for use as a standard logger. Up to developers to attach their own
  # handlers
  Psr\Log\LoggerInterface:
    type: singleton
    class: Monolog\Logger
    constructor:
      - "error-log"

https://github.com/Seldaek/monolog/blob/1.27.1/src/Monolog/Logger.php#L292-L296

    public function addRecord($level, $message, array $context = array())
    {
        if (!$this->handlers) {
            $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG));
        }

With this Raygun module adding a handler to the LoggerInterface, this default is no longer used resulting in logs no longer being sent to php://stderr.

This may be by design of this module, however it is not clear in the README.md that this replaces the default logger with Raygun logging (meaning all logging to php://sterr will stop unless specifically added as a StreamHandler to LoggerInterface).

v4: TypeError: RaygunHandler::writeError(): Argument #1 ($record) must be of type Monolog\LogRecord, array given

if ($exception instanceof Throwable) {
    $this->writeException(
        $record,
        $formatted['tags'],
        $formatted['custom_data'],
        $formatted['timestamp']
    );
} elseif (isset($context['file']) && isset($context['line'])) {
    $this->writeError(
        $formatted,
        $formatted['tags'],
        $formatted['custom_data'],
        $formatted['timestamp']
    );
}

The section calling writeError() with $formatted (I think) needs to be updated to pass $record instead.

SS4 tag

Master seems configured for SS4, but we don't have an offical tag!

Can someone please tag maybe a 2.0.0-rc ?

"Filter sensitive data" needs to be more paranoid

Any env var with "token", "secret", "key", or "password" should be filtered out. Status quo it's likely to push a bunch of secrets stored in env vars for 3rd party services.

Losing an env var that isn't actually secret is benign and easily corrected on a per-site basis, sending data that we didn't want to is by far the biggest risk.

Regular log messages break

With the Raygun module installed, it looks like this:

Injector::inst()->get(LoggerInterface::class)->info('Log test for ssp/core');

Causes this error:

Uncaught Exception InvalidArgumentException: “Invalid record given.” at /var/www/meridia1/releases/004e7725df19f851bc4fc1cbbcfee1ef339785a2/vendor/graze/monolog-extensions/src/Graze/Monolog/Handler/RaygunHandler.php line 66 {“exception”:“[object] (InvalidArgumentException(code: 0): Invalid record given. at /var/www/meridia1/releases/004e7725df19f851bc4fc1cbbcfee1ef339785a2/vendor/graze/monolog-extensions/src/Graze/Monolog/Handler/RaygunHandler.php:66)“} []

silverstripe/silverstripe-framework#8241 would make this issue go away, but that's not merged yet and will never be in SilverStripe 4.0 - 4.3.

Exclusion of sensitive data

I have a problem. The main Raygun's documentation contains one magic sentence. "Note that when any filters are defined, the Raygun error will no longer contain the raw HTTP data, since there's no effective way to filter it.". In this situation, I wonder how I can encrypt selected sensitive data and transfer the necessary data from rawData? For each registered error I need to know what request flew to my api. However, encryption makes me not able to see it. Is there any way to do this?

Adding tags

Please excuse my ignorance if I missed something obvious, but is it possible to add tags to the Raygun logging? I'm wanting to pass certain values such as SS_ENVIRONMENT_TYPE. Thanks.

Add JS integration

Add support for Raygun's JavaScript tracking, for either front-end code, or the admin.

My (biased) perspective is that we should do this as a https://github.com/sminnee/silverstripe-tagmanager plugin, so that we don't get a bunch of modules each providing their own middleware for modifying the outputted HTML. The status quo, for e.g. google analytics insertion is a bit of a mess in this regard. Keen to get thoughts on that, though.

  • A simple interface for defining a snippet, and a middleware for updating the resulting HTML
  • An admin UI for selecting & configuring which snippets should be active. This is less relevant for raygun than, say, google analytics or crasyegg, but putting CMS admins in control of potential feature bloat isn't necessarily a bad thing.

On my to-do list:

  • Support for adding the same kinds of snippets to the admin if you want
  • Potentially the choice between yml snippets and UI-configured ones, if you don't want to put front-end Raygun insertion in the CMS administrator's hands.

FEATURE: Env-specific logging

Currently, the module isn't picky about what it reports or from where. The former is resolved by @chillu's filter example, the latter would be good to allow dev's to optionally enable Raygun logging on a per environment basis.

Yes it's easy to apply ad-hoc project-specific config, but it's messy in mysite/_config.php, so the ability apply something like this in project config would be better:

RaygunLogWriter:
  environment:
    - test
    - live

This would obviously ensure that Raygun logged only in test and live environments. Something like the following in the module's own _config.php (Off the top of my head)

$userDefinedEnvs = Config::inst()->get('RaygunLogWriter', 'environments');
$enableOnLive = Director::isLive() && in_array('live', $userDefinedEnvs);
$enableOnTest = Director::isTest() && in_array('test', $userDefinedEnvs);
$enableOnDev = Director::isDev() && in_array('dev', $userDefinedEnvs);

if(!empty($raygunAPIKey)) {
    // Enable on specific environments
    if(!$enableOnLive || !$enableOnTest || !$enableOnDev) {
        return;
    }
    ....
}

Update for Raygun PHP SDK v2 when it is released

The PHP SDK is preparing for its v2 release, which includes some breaking changes (notably MindscapeHQ/raygun4php#117 re: client instantiation).

Just a placeholder for now, but when it's tagged it'd be a good idea to update this module to either allow both versions to be installed, or release a new minor version with an updated upstream dependency.

Mistake in the documentation

The documentation contains this description:

SilverStripe\Core\Injector\Injector:
  SilverStripe\Raygun\RaygunHandler:
    constructor:
      level: 'error'

However, this will break the application because the level is a second param in the constructor not the first. The following change is necessary to make it work:

SilverStripe\Core\Injector\Injector:
  SilverStripe\Raygun\RaygunHandler:
    constructor:
      client: '%$Raygun4php\RaygunClient'
      level: 'error'

Configuring RaygunClient from _config.php doesn't actually do anything

Here's my flow:

  • Read the readme
  • Add the example code for filtering sensitive data to my app/_config.php file
  • Add throw new Exception('foo') to PageController::init()
  • Open my website

Firstly I get an exception, because we aren't providing the client with the app key:

ERROR [Emergency]: Uncaught ArgumentCountError: Too few arguments to function Raygun4php\RaygunClient::__construct(), 0 passed and at least 1 expected

I change the injector call so that it does, then fire it again and it seems to work because it shows up in Raygun.

If I debug RaygunClientFactory::create() and look at $this->client->getFilterParams() however none of my custom filtering is applied. This is because RaygunClientFactory doesn't track singletons, so the filtering logic in _config.php is useless.

We need to track and return the configured client as a singleton (and update the docs).

I think the last part here is wrong - investigating how it actually works now to confirm.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.