GithubHelp home page GithubHelp logo

airbrake-grails's Introduction

Airbrake Plugin for Grails

This is the notifier plugin for integrating grails apps with Airbrake.

When an uncaught exception occurs, Airbrake will POST the relevant data to the Airbrake server specified in your environment.

Installation & Configuration

Add the following to your BuildConfig.groovy

compile ":airbrake:0.9.4"

Once the plugin is installed, you need to provide your Api Key in Config.groovy file:

grails.plugins.airbrake.apiKey = 'YOUR_API_KEY'

Usage

Once you have installed and configured the plugin there is nothing else to do. Uncaught exceptions will be logged by log4j and those errors will be reported to Airbrake. However, the plugin also exposes a few other ways to send errors to airbrake.

Logging Errors with Exceptions

Manually logging messages at the error level and including an Exception triggers an error notification to airbrake:

class SomeController
	def someAction() {
		try {
			somethingThatThrowsAnException()
		} catch(e) {
			log.error('An error occured', e)
		}
	}

(See the section below on configuring the plugin to including errors without exceptions.)

AirbakeService

The plugin also exposes an airbrakeService which can be dependency injected into your Grails classes. The service allows you to send error notifications directly to Airbrake without logging anything to log4j. It has a notify method that takes a Throwable parameter and an optional Map of arguemnts. The next example shows both in use:

class SomeController
	def airbrakeService
	
	def someAction() {
		try {
			somethingThatThrowsAnException()
		} catch(e) {
			airbrakeService.notify(e, [errorMessage: 'An error occurred'])
		}
	}

	def anotherAction() {
		if (somethingWentWrong()) {
			airbrakeService.notify(null, [errorMessage: 'Something went wrong'])
		}
	}

Advanced Configuration

The Api Key is the minimum requirement to report errors to Airbrake. However, the plugin supports several other configuration options. The full list of configuration options is:

grails.plugins.airbrake.apiKey
grails.plugins.airbrake.enabled
grails.plugins.airbrake.env
grails.plugins.airbrake.includeEventsWithoutExceptions
grails.plugins.airbrake.paramsFilteredKeys
grails.plugins.airbrake.sessionFilteredKeys
grails.plugins.airbrake.cgiDataFilteredKeys
grails.plugins.airbrake.host
grails.plugins.airbrake.port
grails.plugins.airbrake.secure
grails.plugins.airbrake.async
grails.plugins.airbrake.asyncThreadPoolSize
grails.plugins.airbrake.stackTraceFilterer
grails.plugins.airbrake.excludes

Enabling/Disabling Notifications

By default all errors are sent to Airbrake. However, you can disable error notifications (essentially disabling the plugin) by setting grails.plugins.airbrake.enabled = false. For example to disable error notificaitons in development and test environments you might have the following in Config.groovy:

grails.plugins.airbrake.apiKey = 'YOUR_API_KEY'
environments {
	development {
		grails.plugins.airbrake.enabled = false
	}
	test {
		grails.plugins.airbrake.enabled = false
	}

Disabling Notifications by Exception Type

For example, to disable notifications caused by IllegalArgumentException and IllegalStateException, configure

grails.plugins.airbrake.excludes = ['java.lang.IllegalArgumentException', 'java.lang.IllegalStateException']

each entry in the list will be converted to a Pattern and matched against the exception class name, so the following would also exclude these two exceptions:

grails.plugins.airbrake.excludes = ['java.lang.Illegal.*Exception']

Runtime Enabling/Disabling

If you wish to enable/disable notifications at runtime you have a couple of options

  • Call the service method airbrakeService.setEnabled(boolean enabled)
  • Invoke the setEnabled action of AirbrakeTestController. This action expects a single parameter either enabled=true or enabled=false

Setting the Environment

By default, the environment name used in Airbrake will match that of the current Grails environment. To change this default, set the env property:

grails.plugins.airbrake.env = grails.util.Environment.current.name[0..0] // Airbrake env name changed from default value of Development/Test/Production to D/T/P

Including all events logged at the Error level

By default only uncaught errors or errors logged with an exception are reported to Airbrake. It is often convenient to loosen that restriction so that all messages logged at the Error level are reported to Airbrake. This often most useful in src/java or src/groovy classes that can more easily have a log4j logger than get accees to the dependency injected airbrakeService.

With the following line in Config.groovy:

grails.plugins.airbrake.includeEventsWithoutExceptions = true

then logged errors get reported to Airbrake:

@Log4j
class SomeGroovyClass {
	def doSomething() {
		if (somethingWentWrong()) {
			log.error('Something went wrong')
		}
	}
}

Note: It might be reasonable to have this setting true by default but for backwards compatibility with previous versions of te plugin the default is false.

Filtering Parameters sent to Airbrake

To prevent certain parameters from being sent to Airbrake you can configure a list of parameter names to filter out. The configuration settings paramsFilteredKeys, sessionFilteredKeys and cgiFilteredKeys filter the params, session and cgi data sent to Airbrake. For example to prevent any web request parameter named 'password' from being included in the notification to Airbrake you would use the following configuration:

grails.plugins.airbrake.paramsFilteredKeys = ['password']

Each configuration option also supports regular expression matching on the keys. For example the following configuration would prevent all session data from being sent to Airbrake:

grails.plugins.airbrake.sessionFilteredKeys = ['.*']

Custom Airbrake Host, Port and Scheme

If you are running the Airbrake server locally (or a clone thereof, e.g. Errbit), you will need to customise the server URL, port, scheme, etc. For example to change the server host and port, add the following configuration parameters:

grails.plugins.airbrake.host = 'errbit.example.org'
grails.plugins.airbrake.port = 8080

Adding Custom Data to Error Notifications

Supplying User Data

Airbrake allows certain User data to be supplied with the notice. To set the current users data to be included in all notifications use the airbrakeService.addNoticeContext method to set a map of userData. The supported keys are id, name, email and username

airbrakeService.addNoticeContext(id: '1234', name: 'Bugs Bunny', email: '[email protected]', username: 'bugs')

In most web apps the simplest way to provide this context is in a Grails filter. For example if you are using SpringSecurity add the following AirbrakeFilter.groovy in grails-app/conf

class AirbrakeFilters {
    def airbrakeService
    def springSecurityService

    def filters = {
        all(uri: '/**') {
            before = {
                def user = springSecurityService.currentUser
                if (user) {
                   airbrakeService.addNoticeContext(user: [id: user.id, name: user.name, email: user.email, username: user.username ])
                }
            }
        }
    }
}

Synchronous/Asynchronous notifications

By default, notifications are sent to Airbrake asynchronously using a thread-pool of size 5. To change the size of this thread pool set the following config parameter:

// double the size of the pool
grails.plugins.airbrake.asyncThreadPoolSize = 10

To have the notifications sent synchronously, set the async parameter to false:

// send notifications synchronously
grails.plugins.airbrake.async = false

Custom Asynchronous Handler

To send the notifications asynchronously using a custom handler, use the async configuration option. This configuration takes a closure with two parameters the Notice to send and the grailsApplication. The asynchronous handler should simply call airbrakeService.sendNotice(notice) to deliver the notification.

This plugin does not introduce a default choice for processing notices asynchronously. You should choose a method that suits your application. You could just create a new thread or use a scheduler/queuing plugin such as Quartz or Jesque

For example if you are using the Quartz plugin you can send notifications asynchronously using the following setting in Config.groovy

grails.plugins.airbrake.async = { notice, grailsApplication ->
    AirbrakeNotifyJob.triggerNow(notice: notice)
}

and the AirbrakeNotifyJob is defined in grails-app\jobs something like this:

class AirbrakeNotifyJob {
    def airbrakeService

    def execute(JobExecutionContext context) {
        Notice notice = context.mergedJobDataMap.notice
        if (notice) {
            airbrakeService.sendNotice(notice)
        }
    }
}

Stack Trace Filtering

By default all stack traces are filtered using an instance of org.codehaus.groovy.grails.exceptions.DefaultStackTraceFilterer to remove common Grails and java packages. To provide custom stack trace filtering simple configure an instance of a class that implements the interface org.codehaus.groovy.grails.exceptions.StackTraceFilterer in Config.groovy

grails.plugins.airbrake.stackTraceFilterer = new MyCustomStackTraceFilterer()

Compatibility

This plugin is compatible with Grails version 2.0 or greater. A backport to Grails 1.3 is available on the [grails-1.3 branch] (https://github.com/cavneb/airbrake-grails/tree/grails-1.3).

Release Notes

  • 0.7 - 2012/09/21
    • Added support for filtering parameters, session and cgiData. #2
  • 0.7.1 - 2012/09/21
    • Change supported Grails version to 2.0.0. #3
  • 0.7.2 - 2012/09/24
    • Added User Agent, Hostname and user data to notifications
  • 0.8 - 2012/10/16
    • Simpler configuration (Breaking change)
    • Default notification environment to current Grails environment. #9
    • Support for notifying caught exceptions. #15
    • Support for notifying all messages logged at the error level (with or without exceptions)
    • Simpler api for providing user data
    • Full class names in stacktrace. #11
  • 0.8.1 - 2012/10/19
    • Better error message for uncaught exceptions. #18
  • 0.9.0 - 2012/10/29
    • Support for sending notifications to Airbrake asynchronously
    • Added method to AirbrakeService set notification context information that will be used for any reported errors
    • Simpler api to provide User Data. No need to implement UserDataService instead just set the context. (Breaking Change)
    • All request headers now included when reporting an error.
  • 0.9.1 - 2012/11/30
    • Notifications sent to Airbrake asynchronously by default using a thread pool of configurable size #20
    • By default stack traces are filtered #19
    • New configuration option to support custom stack trace filtering
    • New configuration options for filtering params, session and cgi data independently
  • 0.9.2 - 2013/1/19
    • Support for Grails 2.2 and Groovy 2.0 #27
  • 0.9.3 - 2013/05/10
    • New feature to enable/disable notification send while the plugin is running #31
    • New configuration option to filter exceptions by name or pattern #34
    • Bug fix. Don't send notifications synchronously by default #26
    • Bug fix. Handle empty backtrace more gracefully for Errbit #33
    • Thanks to @domurtag for all the fixes
  • 0.9.4 - 2013/06/25
    • Bug fix. AirbrakeNotifier.notify no longer throws under any circumstance.

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Kudos

The origin version of this plugin was written by Phuong LeCong (https://github.com/plecong/grails-airbrake). Since then it has undergone significant refactoring and updates inspired by the Ruby Airbrake gem (https://github.com/airbrake/airbrake)

airbrake-grails's People

Contributors

donalmurtagh avatar jonspalmer avatar kaufda avatar spoonman avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

airbrake-grails's Issues

notifications sent synchronously by default

According to the docs

By default, notifications are sent to Airbrake asynchronously using a thread-pool of size 5.

However, my testing indicates that they are sent synchronously by default. You can verify this by creating a test project with a valid API key. Generate and error from this test project with a breakpoint set in the following method of AirbrakeNotifier

void sendNotice(Notice notice) {
    if (configuration.async) {
        configuration.async(notice, grailsApplication)
    } else {
        sendToAirbrake(notice)
    }
}

You'll see that by default the sendToAirbrake branch is executed which sends notices synchronously. The root cause of the problem is in Configuration where async is initialized

    private configureDefaultAsyncClosure(Map options) {
        def async = (options.async != null) ? options.async : true
        if (!(async instanceof Closure)) {

            ////////////////////////////////////////////////////////////////////////////////////////
            /////////////// problem is here async is falsey
            //////////////////////////////////////////////////////////////////////////////////////// 
            if (async == true ) {
                log.info "configureDefaultAsyncClosure create default async handler with threadPool"
                def threadPoolSize = options.asyncThreadPoolSize ?: 5
                threadPool = Executors.newFixedThreadPool(threadPoolSize)
                options.async = { notice, grailsApplication ->
                    log.debug "submitting notice to threadPool"
                    Runnable sendToAirbrake = {
                        grailsApplication.mainContext.airbrakeNotifier.sendToAirbrake(notice)
                    } as Runnable
                    threadPool.submit(sendToAirbrake)
                }
            } else {
                options.async = null
            }
        }
    }

If you add the config param

grails.plugins.airbrake.async = true

Then notifications are sent asynchronously, so maybe the docs just need to be changed to say that the default is synchronous, though IMO asynchronous would be a better default (which implies there's currently a bug).

Make plugin more resilient to server unavailability

It's possible that the client cannot contact the server, for example:

  • in the case of a locally running server, the URL, port, etc. may have been incorrectly configured
  • if using the public Airbrake server, it could be unavailable

If the server is unavailable, the plugin will try to send the notice to the server each time an error occurs and if the notices are being sent synchronously this will block the request in which the error occurs.

It seems the following might improve the plugin's tolerance to unavailability of the server:

  • at startup check if the server is contactable and if not, disable notice sending
  • provide a URL that allows notice sending to be enabled/disabled without restarting the application. Obviously this URL would need to be protected so that only admins can access it, but providing this protection would be the responsibility of whatever security mechanism the application is using.

I will submit a pull request if you think this proposal is worthwhile?

logging error without exception doesn't work with Errbit

I configured

grails.plugins.airbrake.includeEventsWithoutExceptions = true

and tested

log.error 'something went wrong'

in an application that logs to Errbit, rather than Airbrake. Errbit responds with a HTTP 500 to the data that is sent. My suspicion is that Errbit doesn't like an empty backtrace element:

<backtrace/>

but I think if I change it to

<backtrace></backtrace>

it might work. I guess you don't use Errbit, so I can submit a pull request for this if you wish?

Grails 1.3.X

I would like to use this plugin in a Grails 1.3.7 app. I can't use the current release because AirbrakeGrailsPlugin.groovy declares

def grailsVersion = "2.0.0 > *"

If I were to fork the plugin, and change this to

def grailsVersion = "1.3.7 > *"

are you aware of any reason why the plugin wouldn't work, or to put the question another way, are you actually using any Grails 2.X specific features?

Exclude exceptions of certain types

What?

Add a configuration param that can be used to skip notice-sending for certain types of exceptions. For example, imagine I don't want to send a notice for all exceptions of type IllegalArgumentException or IllegalStateException

This could be configured using a list of exception class names:

grails.plugins.airbrake.excludes = ['java.lang.IllegalArgumentException', 'java.lang.IllegalStateException']

or alternatively, one or more exception class name patterns:

grails.plugins.airbrake.excludes = ['java.lang.Illegal.*Exception']

I considered a list of exception classes instead of a list of exception class names, but decided against the former approach because it would require the exception to be on the classpath at compile-time.

Why?

In my application I have a global error handler configured in UrlMappings.groovy

"500"(controller: "errors", action: "serverError")

which does the following (among other things)

class ErrorsController {
  def serverError = {
    log.error 'unhandled exception', request.exception
  }
}

However, this causes the exception to be logged twice in Errbit

  1. Once with the exceptions actual type and place of origin
  2. Once with an exception type of GrailsWrappedRuntimeException. The origin of this second occurrence is the log.error statement in the global error handler

So in my case I want to use this config param to exclude these duplicates:

grails.plugins.airbrake.excludes = ['org.codehaus.groovy.grails.web.errors.GrailsWrappedRuntimeException']

I can imagine there might be other cases where this feature might be useful, e.g. a 3rd party library is throwing an exception that you don't care about (and can't change the code to prevent it).

Unable to compile v0.9.1

The latest version cannot compile. Here are my results when attempting to compile via the console:

$ grails compile
| Environment set to development....
| Error Exception occurred trigger event [SetClasspath]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Environment set to development.....
| Error Exception occurred trigger event [StatusUpdate]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [StatusUpdate]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [StatusUpdate]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [PluginInstalled]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [StatusUpdate]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [StatusUpdate]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [StatusUpdate]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [PluginInstalled]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [StatusUpdate]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [StatusUpdate]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [StatusUpdate]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [PluginInstalled]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [StatusUpdate]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [StatusUpdate]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)
| Error Exception occurred trigger event [StatusError]: No such property: logScriptTiming for class: grails.util.BuildSettings (Use --stacktrace to see the full trace)

It seems as well that the latest commit which fixes the private/public conflict bug has not been pushed to the Grails plugin repo.

I would fix the issue but I am not sure about the logScriptTiming issue. Please help.

Eric

errors not recorded in airbrake

I've tried using v.0.7.2 of this plugin and the head of the git repository, but no matter which version I use, the errors do not appear when I login to the airbrake website.

I've uploaded the sample application I've created to test this plugin, so you can reproduce the problem. If you run this application, then click on the link on the homepage to generate an error, then login to my airbrake account:

https://kaufda.airbrake.io/projects/82838/errors

email: [email protected]
password: playboy,83

you'll see that no errors are recorded

Truncate messages that would exceed Airbrake's limit

Airbrake has a 64kb limit on the size of notices. Any notice that exceeds this limit is rejected. This typically happens when a exception message is very large. In my opinion, it's more useful to store a truncated error, rather than omit it from Airbrake completely.

I've implemented this locally for the Grails 2.X version of the plugin, by replacing the airbrakeNotifier Spring bean with my own implementation:

@InheritConstructors
class MessageTruncatingAirbrakeNotifier extends AirbrakeNotifier {

    @PackageScope
    static final MAX_MESSAGE_LENGTH = 50000

    @PackageScope
    static final TRUNCATED_MESSAGE_SUFFIX = "...(truncated)"

    MessageTruncatingAirbrakeNotifier(Configuration configuration) {
        super(configuration)
    }

    @Override
    Notice buildNotice(Map options) {

        Notice notice = super.buildNotice(options)

        if (notice.errorMessage.size() > MAX_MESSAGE_LENGTH) {
            notice.errorMessage = notice.errorMessage.take(MAX_MESSAGE_LENGTH) + TRUNCATED_MESSAGE_SUFFIX
        }

        notice
    }
}

It would be useful if this behaviour was added to the plugin, e.g. if a grails.plugins.airbrake.maxErrorMessageChars config param is defined, then any messages that exceed this size are truncated. If this parameter is not defined, there is no truncation.

If you're willing in principle to accept such a contribution and release a new version of the plugin, I'll submit the above as a PR, along with some specs.

Docs inconsistent with latest release

The information in the docs is not consistent with v. 0.7.2. The docs propose using the configuration below:

def isProd = Environment.current == Environment.PRODUCTION

log4j = {
  // Example of changing the log pattern for the default console appender:
  appenders {
    def airbrakeAppender = new grails.plugins.airbrake.AirbrakeAppender (
      name: 'airbrake',
      api_key: 'API_KEY',
      filtered_keys: ['password'],
      env: ((Environment.current == Environment.PRODUCTION) ? 'production' : 'development'),
      enabled: true
    )
  }

  root {
    debug 'stdout', 'airbrake' // This can be added to any log level, not only 'debug'
  }
}

But the AirbrakeAppender class does not have an "enabled" property. Also in the config above, the "isProd" variable is never used.

Furthermore, the docs refer to a test controller that is available at:

http://localhost:8080/airbrakeTest/throwException

This is not present in release 0.7.2, but is present in the head of the git repository, so perhaps you need to release this as a new version?

Incomplete Docs

It would be really helpful if you could document the purpose of each non-obvious property of AirbrakeAppender, e.g.

  • filtered_keys
  • env
  • supplementer
  • secured
  • varFilter
  • etc.

Error in docs

Currently it says:

By default, notifications are sent to Airbrake synchronously

It should read:

By default, notifications are sent to Airbrake asynchronously

send errors asynchronously

Sending the errors synchronously really slows down an app (as the docs acknowledge). I'm not sure I completely understand the asynchronous solution proposed in the docs (which involves Quartz), but it seems a lot more complex than necessary.

Why not just add the following to AirbrakeNotifier

Thread.start {
  // code that submits XML notice to Airbrake (over HTTP)
}

If sending each notice in a separate thread is considered too laissez faire, we could use ExecutorService to create a thread-pool instead,

environment

If the appender is configured as per the example in the docs

        def isProd = Environment.current == Environment.PRODUCTION

        def airbrakeAppender = new grails.plugins.airbrake.AirbrakeAppender(
                name: 'airbrake',
                api_key: '19467cfa091f0eb6e51c6350647bf213',
                filtered_keys: ['password'],
                env: (isProd ? 'production' : 'development'))

then when the app is running in the dev environment, the errors are logged in airbrake in the production environment. I tried using the configuration below instead:

        def airbrakeAppender = new grails.plugins.airbrake.AirbrakeAppender(
                name: 'airbrake',
                api_key: '19467cfa091f0eb6e51c6350647bf213',
                filtered_keys: ['password'],
                env: grails.util.Environment.current.name)

and it seems to resolve this problem. Perhaps it would make sense to use the above as the default value for the env property of AirbrakeAppender?

errors not appearing in airbrake

I followed the instructions for integrating v. 0.7.2, but ran into a compilation error because the class MockUserSupplementer could not be found. I eventually discovered that this class is not included in the latest version (0.7.2) of the plugin available in the Grails repo, so I downloaded the .zip from GitHub and used that instead. This resolved the compilation error, but when I run the application and throw an exception, I don't see anything recorded in Airbrake.

My log4j config currently looks like this:

log4j = {
  // Example of changing the log pattern for the default console appender:
  appenders {
    def airbrakeAppender = new grails.plugins.airbrake.AirbrakeAppender (
      name: 'airbrake',
      api_key: '19467cfa091f0eb6e51c6350647bf213',
      filtered_keys: ['password'],
      env: ((Environment.current == Environment.PRODUCTION) ? 'production' : 'development'),    
      enabled: true
    )
    airbrakeAppender.addSupplementer(new MockUserSupplementer())
  }

  root {
    debug 'stdout', 'airbrake' // This can be added to any log level, not only 'debug'
  }
}

The API key above is the key of the single-user test project I've setup. In case you want to login to Airbrake to check why this isn't working, the details are:

email: [email protected]
password: playboy,83

This is just a test account I'm using to evaluate Airbrake, so I don't mind publishing this info in a public forum :)

support sending caught exceptions to Airbrake

Currently, the only errors that are sent to Airbrake are unhandled exceptions. However, it would be very useful to also be able to send handled errors.

One possible way to support this would be for all calls to a Logger at the ERROR level (or above) to also send an error, e.g.

try {
  // some code that throws an exception

} catch (ex) {

  // because ex is logged at the error level, the error is sent to Airbrake
  log.error "Something bad happened", ex
}

So the idea is that in the code above ex is treated identically to an uncaught ex. A property could be added to AirbrakeAppender to indicate whether handled exceptions should also be logged, e.g.

    def airbrakeAppender = new grails.plugins.airbrake.AirbrakeAppender (
      name: 'airbrake',
      api_key: 'API_KEY',
      filtered_keys: ['password'],
      notify_handled_exceptions: org.apache.log4j.Level.ERROR
    )

The config above indicates that exceptions logged at the ERROR level and above should be sent to Airbrake. If this parameter is omitted, only uncaught exceptions are sent, to preserve compatability with previous plugin versions.

grails 2.2 upgrade and private Map getCgiData(webRequest)

I am getting the following compilation exception after upgrading to grails 2.2

| Error Compilation error: startup failed:
/Users/john/.grails/2.2.0/projects/fotonotes/plugins/airbrake-0.9.1/src/groovy/grails/plugins/airbrake/Notice.groovy: 281: Mixing private and public/protected methods of the same name causes multimethods to be disabled and is forbidden to avoid surprising behaviour. Renaming the private methods will solve the problem.
 @ line 281, column 5.
       private Map getCgiData(webRequest) {
       ^

unhandled exception message

The recent contribution that resolved this issue appears to have introduced a regression with the way unhandled exceptions are recorded. Previously, an action such as:

    def throwException() {
        throw new Exception("Power Cut")
    }

would cause an error to be logged in Airbrake with the message

Power Cut

However, the Airbrake message that's now used for an exception such as the above is:

Exception occurred when processing request: [GET] /ttt/test/throwException Power Cut. Stacktrace follows:

My own opinion is that the exception message (alone) is a more readable and appropriate message to use for each Airbrake error, and in the interest of backward compatibility, we should restore the previous behaviour.

Plugin does't send the actual exception class to airbrake

Wonderful plugin. It sends a lot of good information to airbrake, but I am missing the actual exception that was thrown. It looks like the title is the exception message, and the Backtrace is the full stacktrace except for the final exception. Some configuration I am missing?

filter stacktraces

Before the stacktrace is converted to XML, remove all the Groovy/Grails noise from it with

Throwable filtered = new DefaultStackTraceFilterer().filter(unfilteredThrowable)

make environment configuration more flexible

I would like to set Notice.env to the hostname (I realise that the host is already available in Notice.hostname, but this field is not displayed on Errbit's error list screen, whereas the environment is).

AFAIK, the only reliable way to get the hostname is from the request object, e.g.

RequestContextHolder.requestAttributes?.currentRequest?.getHeader('X-Forwarded-Host')

However, if I configure

grails.plugins.airbrake.env = RequestContextHolder.requestAttributes?.currentRequest?.getHeader('X-Forwarded-Host')

this won't work, because there is no request object when this configuration is read. Instead, I would like to be able to do this

grails.plugins.airbrake.env = { RequestAttributes webRequest ->
    webRequest?.currentRequest?.getHeader('X-Forwarded-Host')
}

@cavneb if you've no objection to this (and are willing to release a new version that includes this change), could you let me know, and I'll send a pull-request with the relevant code changes?

I'll make this change such that it's backwards compatible, i.e. the environment will be resolved by passing the current request into the closure above only if a closure is assigned to grails.plugins.airbrake.env.

script for airbrake deploy notification

Hi,
Is it possible to write a groovy/grails script which notifies the airbrake about a new deployed (GIT)Version? So this script can be executed manually or by an CIServer like Hudson/Jenkins.

THX.

Should we provide information for nested exceptions?

Currently airbrake plugin provides information only about top-most exception. I think that we can make it better and provide information about all nested exceptions.

For example, consider hierarchy:

MyConnectionException("foo")
    +---IOException("bar")
        +---SocketException("baz")

I think that we can extend plugin so it reports:

  • errorMessage - 3 messages joined with a newline: foo\nbar\nbaz
  • errorClass - top-most exception class: MyConnectionException
  • backtrace - whole backtrace of 3 exceptions from top-most to bottom-lowest

What do you think? I think it's reasonable and I can provide implementation along with tests.

stacktrace format

By default the backtrace tab in airbrake shows the stacktrace in the following format

AirbrakeTestController.groovy:8:in `throwException'
PageFragmentCachingFilter.java:195:in `doFilter'
AbstractFilter.java:63:in `doFilter'
ThreadPoolExecutor.java:886:in `runTask'
ThreadPoolExecutor.java:908:in `run'
Thread.java:680:in `run'

Is it possible to show the fully-qualified class name instead? If so, IMO, this should be the default.

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.