serverless-sentry-lib
    TypeScript icon, indicating that this package has built-in type declarations

    2.4.0 • Public • Published

    ⚡️ Easy Sentry SDK Integration For AWS Lambda

    serverless npm license dependencies

    About

    This library simplifies integration of Sentry's @sentry/node library with AWS Lambda. The only supported platforms of this library are the Lambda Runtimes for Node.js 10 and 12. Python and Java support will require dedicated libraries. Pull requests are welcome!

    The serverless-sentry-plugin and serverless-sentry-lib libraries are not affiliated with either Functional Software Inc., Sentry, Serverless or Amazon Web Services but developed independently and in my spare time.

    Benefits

    • Easy to use. Promised 🤞
    • Integrates with Serverless Framework as well as the AWS Serverless Application Model for AWS Lambda (though no use of any framework is required).
    • Wraps your Node.js code with Sentry error capturing.
    • Forwards any errors returned by your AWS Lambda function to Sentry.
    • Warn if your code is about to hit the execution timeout limit.
    • Warn if your Lambda function is low on memory.
    • Reports unhandled promise rejections.
    • Catched and reports uncaught exceptions.
    • Serverless, Sentry and as well as this library are all Open Source. Yay! 🎉
    • TypeScript support

    Installation

    • Install the @sentry/node module:
      npm install --save @sentry/node
    • Install this module:
      npm install --save serverless-sentry-lib
    • Check out the examples below how to integrate it with your project by updating serverless.yml as well as your Lambda handler code.

    Although this library is written in TypeScript, the resulting library uses exclusively Node 10 features to ensure this code can run on AWS Lambda without any additional transpiling or further processing. We also do not use any 3rd party node module other than @sentry/node itself.

    This library can be used standalone or as part of the Serverless Sentry Plugin.

    Use as Standalone Library

    If you don't want to add another plugin to Serverless (or if you're not using the Serverless Framework), you can use this library standalone without additional dependencies (besides @sentry/node itself).

    If you're using the Serverless Framework, extend your serverless.yml to include additional environment variables. The only required environment variable is SENTRY_DSN to set the DSN url for your reporting. A full list of all available environment variables is available below.

    service: my-serverless-project
    provider:
      # ...
      environment:
        SENTRY_ENVIRONMENT: ${opt:stage, self:provider.stage} # recommended
        SENTRY_DSN: https://xxxx:yyyy@sentry.io/zzzz # URL provided by Sentry

    If you are using the AWS Serverless Application Model, set the environment variables in your template.yml:

    AWSTemplateFormatVersion: "2010-09-09"
    Transform: AWS::Serverless-2016-10-31
    Resources:
      SomeFunction:
        Type: AWS::Serverless::Function
        Properties:
          CodeUri: some-function/
          Handler: index.handler
          Runtime: nodejs12.x
          Environment:
            Variables:
              SENTRY_DSN: https://xxxx:yyyy@sentry.io/zzzz

    Environment Variables

    Capturing can be controlled through the following environment variables. You can set them manually in your serverless.yml (Serverless Framework) or template.yml (AWS SAM) or let them be configured automatically using the Serverless Sentry Plugin during deployment.

    Environment Variable Description
    SENTRY_DSN Sentry DSN Url
    SENTRY_ENVIRONMENT Environment (optional, e.g. "dev" or "prod")
    SENTRY_RELEASE Release number or version of your project (optional)
    SENTRY_AUTO_BREADCRUMBS Automatically create breadcrumbs (see Sentry SDK docs, default to true)
    SENTRY_FILTER_LOCAL Don't report errors from local environments (defaults to true)
    SENTRY_CAPTURE_ERRORS Enable capturing Lambda errors (defaults to true)
    SENTRY_CAPTURE_UNHANDLED Enable capturing unhandled Promise rejections (defaults to true)
    SENTRY_CAPTURE_UNCAUGHT Enable capturing uncaught exceptions (defaults to true)
    SENTRY_CAPTURE_MEMORY Enable monitoring memory usage (defaults to true)
    SENTRY_CAPTURE_TIMEOUTS Enable monitoring execution timeouts (defaults to true)
    SENTRY_SOURCEMAPS Enable Webpack sourcemaps support (defaults to false)

    In addition the library checks for the following optional variables and adds them as custom Sentry tags automatically:

    Environment Variable Sentry Tag Description
    SERVERLESS_SERVICE service_name Serveless service name
    SERVERLESS_STAGE stage Serverless stage
    SERVERLESS_ALIAS alias Serverless alias, see Serverless AWS Alias Plugin
    SERVERLESS_REGION region Serverless region name

    Use Together With the Serverless Sentry Plugin

    The Serverless Sentry Plugin allows simpler configuration of the library through the serverless.yml and will upload your source-maps automatically during deployment. This is the recommended way of using the serverless-sentry-lib library.

    Instead of manually setting environment variables, the plugin determines and sets them automatically. In the serverless.yml simply load the plugin and set the dsn configuration option as follows:

    service: my-serverless-project
    provider:
      # ...
    plugins: serverless-sentry
    custom:
      sentry:
        dsn: https://xxxx:yyyy@sentry.io/zzzz # URL provided by Sentry

    You can still manually set environment variables on a per-function level to overwrite the default ones. Please refer to the Serverless Sentry Plugin for full documentation of all available options.

    Updating Your Code

    For maximum flexibility this library is implemented as a wrapper around your original AWS Lambda handler code (your handler.js or similar function). The withSentry higher-order function adds error and exception handling, and takes care of configuring the Sentry client automatically.

    withSentry is pre-configured to reasonable defaults and doesn't need any configuration. If will automatically load and configure @sentry/node which needs to be installed as a peer dependency.

    Original Lambda Handler Code:

    exports.handler = async function (event, context) {
      console.log("EVENT: \n" + JSON.stringify(event, null, 2));
      return context.logStreamName;
    };

    New Lambda Handler Code Using withSentry For Sentry Reporting

    const withSentry = require("serverless-sentry-lib"); // This helper library
    
    exports.handler = withSentry(async function (event, context) {
      console.log("EVENT: \n" + JSON.stringify(event, null, 2));
      return context.logStreamName;
    });

    ES6 Module: Original Lambda Handler Code:

    export async function handler(event, context) {
      console.log("EVENT: \n" + JSON.stringify(event, null, 2));
      return context.logStreamName;
    }

    ES6 Module: New Lambda Handler Code Using withSentry For Sentry Reporting

    import withSentry from "serverless-sentry-lib"; // This helper library
    
    export const handler = withSentry(async (event, context) => {
      console.log("EVENT: \n" + JSON.stringify(event, null, 2));
      return context.logStreamName;
    });

    Once your Lambda handler code is wrapped in withSentry, it will be extended it with automatic error reporting. Whenever your Lambda handler sets an error response, the error is forwarded to Sentry with additional context information.

    Setting Custom Configuration Options

    As shown above you can use environment variables to control the Sentry integration. In some scenarios in which environment variables are not desired or in which custom logic needs to be executed, you can also pass in configuration options to withSentry directly:

    You can control how Sentry should be initialized by passing the following options:

    • sentryOptions - Additional options to set for the Sentry client, e.g. proxy settings.
    • scope - Custom scope settings.
    • filterLocal - don't report errors from local environments (defaults to true).
    • sourceMaps - Enable source maps (defaults to false) by loading the RewriteFrames Sentry integration.

    Or, alternatively, you can pass in a custom, already preconfigured Sentry object. Note that Sentry needs to be properly initialized in this case:

    • sentry - Use the given Sentry instance instead instead of importing it automatically.

    In addition you can set any of the following options to control what events should be captured:

    • flushTimeout - How long we should wait for Sentry data to be written when shutting down the Lambda or between invocations (defaults to 2000 milliseconds).
    • autoBreadcrumbs - Automatically create breadcrumbs (see Sentry SDK docs, defaults to true).
    • captureErrors - capture Lambda errors (defaults to true).
    • captureUnhandledRejections - capture unhandled Promise rejections (defaults to true).
    • captureUncaughtException - capture uncaught exceptions (defaults to true).
    • captureMemory - monitor memory usage (defaults to true).
    • captureTimeouts - monitor execution timeouts (defaults to true).

    Example

    import withSentry from "serverless-sentry-lib";
    
    // Wrap handler for automated error and exception logging
    const withSentryOptions = {
      sentryOptions: {
        /* Custom Sentry configuration options */
        httpProxy: "...",
        httpsProxy: "...",
      },
      scope: {
        tags: {
          /* additional tags to send to Sentry */
          Foo: "bar",
        },
      },
      captureErrors: false,
      captureUnhandledRejections: true,
      captureUncaughtException: true,
      captureMemory: true,
      captureTimeouts: true,
    };
    
    export const handler = withSentry(withSentryOptions, async (event, context) => {
      console.log("EVENT: \n" + JSON.stringify(event, null, 2));
      return context.logStreamName;
    });

    Accessing the Sentry Client for Capturing Custom Messages and Exceptions

    If you want to capture a message or exception from anywhere in your code, simply use the Sentry client as usual. It is a singleton instance and doesn't need to be configured again:

    CommonJS

    const Sentry = require("@sentry/node");
    Sentry.captureMessage("Hello from Lambda!", { level: "info" });

    ES6 Modules

    import * as Sentry from "@sentry/node";
    Sentry.captureMessage("Hello from Lambda!", { level: "info" });

    For further documentation on how to use it to capture your own messages refer to docs.getsentry.com.

    Capturing Unhandled Promise Rejections

    When enabled all Promise rejections that aren't handled by yourself will be reported to Sentry.

    Capturing Uncaught Exceptions

    Typically, if your Lambda code throws an unhandled exception somewhere in the code, the invocation is immediately aborted and the function exits with a "Process exited before completing request". The plugin captures these unhandled exceptions, forwards them to Sentry and then exits the Lambda with an error code.

    Local Development

    By default the library will only forward errors to Sentry when deployed on AWS Lambda, not during local development. If you want to change this behavior set the filterLocal option to false.

    Detecting Slow Running Code

    It's a good practice to specify the function timeout in serverless.yml to be at last twice as large as the expected maximum execution time. If you specify a timeout of 6 seconds (the default), this plugin will warn you if the function runs for 3 or more seconds. That means it's time to either review your code for possible performance improvements or increase the timeout value slightly.

    Low Memory Warnings

    The plugin will automatically generate a warning if the memory consumption of your Lambda function crosses 75% of the allocated memory limit. The plugin samples the amount of memory used by Node.js every 500 milliseconds (using process.memoryUsage()), independently of any garbage collection. As with all Node.js code, it is important to remember that JavaScript code runs single-threaded and the monitoring function will only be able to sample memory usage if your code is in a wait state, e.g. during database queries or when calling asynchronous functions with a callback.

    Only one low memory warning will be generated per function invocation. You might want to increase the memory limit step by step until your code runs without warnings.

    Turn Sentry Reporting On/Off

    Obviously Sentry reporting is only enabled if you wrap your code using withSentry as shown in the examples above. In addition, error reporting is only active if the SENTRY_DSN environment variable is set or if you explicitly pass { sentryOptions: { dsn } } as configuration options. This is an easy way to enable or disable reporting as a whole or for specific functions.

    In some cases it might be desirable to disable only error reporting itself but keep the advanced features such as timeout and low memory warnings in place. This can be achieved via setting the respective options in the environment variables or withSentry during initialization:

    const withSentry = require("serverless-sentry-lib");
    
    // Wrap handler but disable error capturing; all other options will remain the default
    module.exports.handler = withSentry({ captureErrors: false }, (event, context, callback) => {
      // your Lambda Functions Handler code goes here...
    });

    Version History

    2.4.0

    • Updated dependencies

    2.3.0

    • Override existing unhandledRejection and uncaughtException listeners when captureUnhandledRejections or captureUncaughtExceptions are enabled and invoke them after we handled them. At the same time we disable Sentry's default integrations for both to avoid duplicate reporting. This works around a custom listener registered by AWS Lambda internally that prevents proper automatic handling with Sentry. Thanks to ffxsam for reporting the original issue. By updating the execution order of the listeners we keep side effects to a minimum. Please report back if you encounter any weird or unexpected behavior!
    • Upgraded all dependencies, use Typescript 4.0

    2.2.0

    • Reset the scope on every Lambda start (if no custom Sentry client instance is used). This should avoid breadcrumbs and extras from previous runs "bleed" into subsequent Lambda invocations. Thanks to demsey2 for reporting the original issue.
    • Added a new flushTimeout option to control how long we want to wait for data being written to Sentry before the Lambda shuts down or between invocations.
    • Deprecated captureMemoryWarnings and captureTimeoutWarnings in favor of new options captureMemory and captureTimeouts which allow more customization. Thanks to keanolane for suggesting of custom timeouts. This only affects users invoking withSentry with custom options. If you're using serverless-sentry-plugin to set all options you won't have to change anything.
    • Fixed an issue with custom tags, extras and user traits not being set when passed as options to withSentry. Thanks to blelump for reporting and providing a pull request.

    2.1.0

    • Explicitly check environment variables IS_OFFLINE and IS_LOCAL for truthy strings (yes, on, true, t, or 1). Thanks to danilofuchs for suggesting.
    • Flush to Sentry when the Lambda function finishes but don't close Sentry yet as we might get called again. #23

    2.0.1

    • Fixed some type resolution issues in the generated TypeScript definition file

    2.0.0

    • Rewrite using TypeScript. The use of TypeScript in your project is fully optional, but if you do, we got you covered!
    • Added new default uncaught exception handler.
    • Dropped support for Node.js 6 and 8. The only supported versions are Node.js 10 and 12.
    • Upgrade from Sentry SDK raven to the Unified Node.js SDK @sentry/node.
    • Simplified integration using withSentry higher order function. Passing the Sentry instance is now optional.
    • Thank you @aheissenberger and @Vadorequest for their contributions to this release! 🤗

    Support

    That you for supporting me and my projects.

    Install

    npm i serverless-sentry-lib

    DownloadsWeekly Downloads

    6,379

    Version

    2.4.0

    License

    MIT

    Unpacked Size

    52.9 kB

    Total Files

    5

    Last publish

    Collaborators

    • arabold