bugsnag / bugsnag-ruby

BugSnag error monitoring & reporting software for rails, sinatra, rack and ruby
https://docs.bugsnag.com/platforms/ruby
MIT License
245 stars 173 forks source link

Library not usable on aws lambda (w/o docker) #726

Open gburgett opened 2 years ago

gburgett commented 2 years ago

Hello,

I am trying to use Bugsnag to diagnose issues with my AWS Lambda Function which runs ruby code. I use the Serverless framework to deploy my function, which runs on a cron timer every 15 minutes.

Unfortunately when I include this library, the function fails to run. Here is the relevant log line from CloudWatch logs:

{
    "errorMessage": "cannot load such file -- bugsnag",
    "errorType": "Init<LoadError>",
    "stackTrace": [
        "/var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'",
        "/var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'",
        "/var/task/src/squawker/bugsnag.rb:3:in `<top (required)>'",
        "/var/task/src/squawker.rb:5:in `require_relative'",
        "/var/task/src/squawker.rb:5:in `<top (required)>'",
        "/var/task/src/handlers/squawker/cron.rb:3:in `require_relative'",
        "/var/task/src/handlers/squawker/cron.rb:3:in `<top (required)>'",
        "/var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'",
        "/var/lang/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'"
    ]
}

I believe this is because the bugsnag gem depends on concurrent-ruby, which includes native C code that must be compiled. The AWS Lambda Runtime does not handle native code by default, it must be packaged into a docker file.

Does the Bugsnag gem require concurrent-ruby as a runtime dependency? If that dependency could be eliminated, the gem could be used by default in an AWS lambda context. In the meantime, I will pursue the workaround of building a Docker container on top of the AWS base image for Lambda.

For reference, here are the relevant parts of my serverless.yml file

service: wcc-squawker

frameworkVersion: '3'

provider:
  name: aws
  region: us-east-1
  runtime: ruby2.7
  memorySize: 256
  timeout: 10
  environment:
    stage: ${sls:stage}
    region: ${self:provider.region}
    service: ${self:service}
    tableName: ${self:custom.tableName}
    BUGSNAG_API_KEY: xxxxxx
    LOG_LEVEL: debug

  logRetentionInDays: 30
  tags:
    Application: ${self:service}
    Stage: ${sls:stage}
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - dynamodb:GetItem
            - dynamodb:BatchGetItem
            - dynamodb:PutItem
            - dynamodb:UpdateItem
            - dynamodb:BatchWriteItem
            - dynamodb:Query
            - dynamodb:Scan
          Resource:
            - !GetAtt Table.Arn
        - Effect: Allow
          Resource: "*"
          Action:
            - ses:SendEmail
            - ses:SendRawEmail
            - logs:CreateLogGroup
            - logs:CreateLogStream
            - logs:PutLogEvents

functions:
  cron:
    handler: src/handlers/squawker/cron.run
    events:
      - schedule: rate(15 minutes)

resources:
  Resources:
    Table:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: ${self:custom.tableName}
        Tags:
          - Key: Application
            Value: ${self:service}
          - Key: Stage
            Value: ${sls:stage}
        BillingMode: PAY_PER_REQUEST
        AttributeDefinitions:
          - AttributeName: index_name
            AttributeType: S
          - AttributeName: search
            AttributeType: S
        KeySchema:
          - AttributeName: index_name
            KeyType: HASH
          - AttributeName: search
            KeyType: RANGE
        TimeToLiveSpecification:
          Enabled: true
          AttributeName: 'expires_at'

plugins:
  - serverless-ruby-layer
  - serverless-export-env
  - serverless-plugin-aws-alerts
custom:
  tableName: ${self:service}-${sls:stage}
  rubyLayer:
    include_functions:
      - cron
  alerts:
    stages:
      - production
    topics:
      alarm:
        topic: ${self:service}-${sls:stage}-alerts-alarm
        notifications:
          - protocol: email
            endpoint: gburgett@xxx.org
    alarms:
      - functionErrors
      - functionThrottles
luke-belton commented 2 years ago

Hi @gburgett - concurrent-ruby is currently a runtime dependency. We do have an item on our backlog already to look at official support for AWS Lambdas with Ruby in the future - I'll make sure we keep this thread updated on that 👍