NAME
Log::Log4perl::Appender::Raven - Append log events to your Sentry account.
BUILD STATUS
WARNING(s)
This appender will send ALL the log events it receives to your Sentry DSN synchronously. If you generate a lot of logging, that can make your sentry account saturate quite quickly and your application come to a severe slowdown.
Using Log4perl appender's Threshold or Log::Log4perl::Filter in your log4perl config, and experimenting a little bit is Highly Recommended.
Remember sentry is designed to record errors, so hopefully your application will not generate too many of them.
You have been warned.
SYNOPSIS
Read the CONFIGURATION section, then use Log4perl just as usual.
If you are not familiar with Log::Log4perl, please check Log::Log4perl
In a nutshell, here's the minimul l4p config to output anything from ERROR to Sentry:
log4perl.rootLogger=DEBUG, Raven
log4perl.appender.Raven=Log::Log4perl::Appender::Raven
log4perl.appender.Raven.Threshold=ERROR
log4perl.appender.Raven.sentry_dsn="https://user:key@sentry-host.com/project_id"
log4perl.appender.Raven.layout=Log::Log4perl::Layout::PatternLayout
log4perl.appender.Raven.layout.ConversionPattern=%X{chunk} %d %F{1} %L> %m %n
CONFIGURATION
This is just another Log::Log4perl::Appender.
Simple Configuration
The only mandatory configuration key is *sentry_dsn* which is your sentry dsn string obtained from your sentry account. See http://www.getsentry.com/ and https://github.com/getsentry/sentry for more details.
Alternatively to setting this configuration key, you can set an environment variable SENTRY_DSN with the same setting. - Not recommended -
Example:
log4perl.rootLogger=ERROR, Raven
layout_class=Log::Log4perl::Layout::PatternLayout
layout_pattern=%X{chunk} %d %F{1} %L> %m %n
log4perl.appender.Raven=Log::Log4perl::Appender::Raven
log4perl.appender.Raven.sentry_dsn="http://user:key@host.com/project_id"
log4perl.appender.Raven.sentry_timeout=1
log4perl.appender.Raven.layout=${layout_class}
log4perl.appender.Raven.layout.ConversionPattern=${layout_pattern}
Configuring the culprit string
By default, this appender will calculate the Sentry culprit to be the fully qualified name of the function that called the log method, as Sentry recommends.
If you require more flexibility and precision in your culprit, you can configure it as a template. For instance:
log4perl.appender.Raven.sentry_culprit_template={$function}-{$line}
The default is '{$function}', as Sentry prescribes. But most people will probably be more happy with the added {$line} element, as it makes discriminating between culprits easier.
The template format follows Text::Template and the available variables and functions are as follow:
- function
-
The fully qualified name of the function that called the log method.
- line
-
The line at which the log method was called
- message
-
The Log4perl generated message. Keep in mind that this is the message AFTER it has been calculated by the layout pattern.
- sign($string, $offset, $length)
-
A function that calculates a small (4 chars) signature of the given string. $string, $offset and $length are optional.
This is useful for instance if some part of your code manage errors in a centralized way, or in other terms if the place at which you call '$log->error()' can output various messages. To help discriminating between culprit, you can for instance configure your culprit template:
log4perl.appender.Raven.sentry_culprit_template={$function}-{$line}-{sign($message, 30, 4)}
Note that in the example, we look at a part of the message after the 30th character, which helps skipping the common message parts defined by your message layout. Adjust this number (30) to make sure you pick a substring of your message in a meaningful area.
Timeout
The default timeout is 1 second. Feel free to bump it up. If sending an event timesout (or if the sentry host is down or doesn't exist), a plain Perl warning will be output.
Configuration with Static Tags
You have the option of predefining a set of tags that will be send to your Sentry installation with every event. Remember Sentry tags have a name and a value (they are not just 'labels').
Example:
...
log4perl.appender.Raven.tags.application=myproduct
log4perl.appender.Raven.tags.installation=live
...
Configure and use Dynamic Tagging
Dynamic tagging is performed using the Log4Perl MDC mechanism. See Log::Log4perl::MDC if you are not familiar with it.
Anywhere in your code.
...
Log::Log4perl::MDC->set('sentry_tags' , { subsystem => 'my_subsystem', ... });
$log->error("Something very wrong");
...
Or specify which key to capture in config:
...
log4perl.appender.Raven.mdc_tags=my_sentry_tags
...
Note that tags added this way will be added to the statically define ones, or override them in case of conflict.
Note: Tags are meant to categorize your Sentry events and will be displayed in the Sentry GUI like any other category.
Configure and use User Data
Sentry supports structured user data that can be added to your event. User data works a bit like the tags, except only three keys are supported:
id, username and email. See Sentry::Raven (capture_user) for a description of those keys.
In your code:
...
Log::Log4perl::MDC->set('sentry_user' , { id => '123' , email => 'jeteve@cpan.org', username => 'jeteve' });
$log->error("Something very wrong");
...
Or specify the MDC key to capture in Config:
...
log4perl.appender.Raven.mdc_user=my_sentry_user
...
Configure and use HTTP Request data.
Sentry support HTTP Request structured data that can be added to your event. HTTP Data work a bit like tags, except only a number of keys are supported:
url, method, data, query_string, cookies, headers, env
See Sentry::Raven (capture_request) or interface 'Http' in http://sentry.readthedocs.org/en/latest/developer/interfaces/index.html for a full description of those keys.
In your code:
...
Log::Log4perl::MDC->set('sentry_http' , { url => 'http://www.example.com' , method => 'GET' , ... });
$log->error("Something very wrong");
...
Or specify the MDC key to capture in Config:
...
log4perl.appender.Raven.mdc_http=my_sentry_http
...
Configure and use Dynamic Extra
Sentry allows you to specify any data (as a Single level HashRef) that will be stored with the Event.
It's very similar to dynamic tags, except its not tags.
Then anywere in your code:
...
Log::Log4perl::MDC->set('my_sentry_extra' , { session_id => ... , ... });
$log->error("Something very wrong");
...
Or specify MDC key to capture in config:
...
log4perl.appender.Raven.mdc_extra=my_sentry_extra
...
Configuration with a Static Context.
You can use lines like:
log4perl.appender.Raven.context.platform=myproduct
To define static Sentry::Raven context. The list of context keys supported is not very long, and most of them are defined dynamically when you use this package anyway.
See Sentry::Raven for more details.
USING Log::Any
This is tested to work with Log::Any just the same way it works when you use Log4perl directly.
CODE WITHOUT LOG4PERL
Warning: Experimental feature.
If your code, or some of its dependencies is not using Log4perl, you might want to consider infecting the __DIE__ pseudo signal with some amount of trickery to have die (and Carp::confess/croak) calls go through log4perl.
This appender makes that easy for you, and provides the 'infect_die' configuration property to do so:
...
log4perl.appender.Raven.infect_die=1
...
This is heavily inspired by https://metacpan.org/pod/Log::Log4perl::FAQ#My-program-already-uses-warn-and-die-.-How-can-I-switch-to-Log4perl
While this can be convenient to quickly implement this in a non-log4perl aware piece of software, you are strongly encourage not to use this feature and pepper your call with appropriate Log4perl calls.
SEE ALSO
Sentry::Raven , Log::Log4perl, Log::Any , Log::Any::Adapter::Log4perl
AUTHOR
Jerome Eteve jeteve@cpan.com