├── functions ├── s3.js ├── kinesis.js ├── sqs.js ├── dynamodb.js ├── event-bridge.js ├── sns.js ├── service-c.js ├── timeout.js ├── error.js ├── service-b.js ├── utils.js └── service-a.js ├── architecture.png ├── .gitignore ├── package.json ├── .vscode └── launch.json ├── LICENSE └── serverless.yml /functions/s3.js: -------------------------------------------------------------------------------- 1 | exports.handler = async function(event) { 2 | }; -------------------------------------------------------------------------------- /functions/kinesis.js: -------------------------------------------------------------------------------- 1 | exports.handler = async function(event) { 2 | }; -------------------------------------------------------------------------------- /functions/sqs.js: -------------------------------------------------------------------------------- 1 | exports.handler = async function(event) { 2 | }; -------------------------------------------------------------------------------- /functions/dynamodb.js: -------------------------------------------------------------------------------- 1 | exports.handler = async function(event) { 2 | }; -------------------------------------------------------------------------------- /functions/event-bridge.js: -------------------------------------------------------------------------------- 1 | exports.handler = async function(event) { 2 | }; -------------------------------------------------------------------------------- /functions/sns.js: -------------------------------------------------------------------------------- 1 | module.exports.handler = async (event, context) => { 2 | } -------------------------------------------------------------------------------- /architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theburningmonk/lambda-x-ray-demo/HEAD/architecture.png -------------------------------------------------------------------------------- /functions/service-c.js: -------------------------------------------------------------------------------- 1 | module.exports.handler = async (event, context) => { 2 | return "foo" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # package directories 2 | node_modules 3 | jspm_packages 4 | 5 | # Serverless directories 6 | .serverless -------------------------------------------------------------------------------- /functions/timeout.js: -------------------------------------------------------------------------------- 1 | module.exports.handler = (event, context, callback) => { 2 | console.log(JSON.stringify(event)) 3 | console.log("this is going to timeout...") 4 | } -------------------------------------------------------------------------------- /functions/error.js: -------------------------------------------------------------------------------- 1 | module.exports.handler = async (event) => { 2 | console.log(JSON.stringify(event)) 3 | console.log("this is going to error...") 4 | 5 | throw new Error("boom") 6 | } -------------------------------------------------------------------------------- /functions/service-b.js: -------------------------------------------------------------------------------- 1 | module.exports.handler = async (event, context) => { 2 | return { 3 | statusCode: 200, 4 | body: JSON.stringify({ 5 | message: 'boo' 6 | }), 7 | } 8 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lambda-x-ray-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "aws-xray-sdk": "^1.1.1", 13 | "bluebird": "^3.5.0", 14 | "lodash": "^4.17.4" 15 | }, 16 | "devDependencies": { 17 | "aws-sdk": "^2.1206.0", 18 | "serverless": "^3.22.0", 19 | "serverless-iam-roles-per-function": "^3.2.0", 20 | "serverless-lumigo": "^1.14.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible Node.js debug attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "service-a", 11 | "program": "${workspaceRoot}/node_modules/.bin/sls", 12 | "args": [ 13 | "invoke", 14 | "local", 15 | "-f", 16 | "service-a" 17 | ], 18 | "cwd": "${workspaceRoot}" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /functions/utils.js: -------------------------------------------------------------------------------- 1 | const AWSXRay = require('aws-xray-sdk') 2 | const https = AWSXRay.captureHTTPs(require('https')) 3 | 4 | const request = (method, hostname, path) => { 5 | const options = { hostname, port: 443, path, method } 6 | 7 | const promise = new Promise((resolve, reject) => { 8 | const req = https.request(options, res => { 9 | console.log('statusCode:', res.statusCode) 10 | console.log('headers:', res.headers) 11 | 12 | res.on('data', buffer => resolve(buffer.toString('utf8'))) 13 | }) 14 | 15 | req.on('error', err => reject(err)) 16 | 17 | req.end() 18 | }) 19 | 20 | return promise 21 | } 22 | 23 | module.exports = { 24 | request 25 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Yan Cui 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /functions/service-a.js: -------------------------------------------------------------------------------- 1 | const AWSXRay = require('aws-xray-sdk') 2 | const AWS = AWSXRay.captureAWS(require('aws-sdk')) 3 | // const AWS = require('aws-sdk') 4 | const sns = new AWS.SNS() 5 | const sqs = new AWS.SQS() 6 | const s3 = new AWS.S3() 7 | const dynamodb = new AWS.DynamoDB.DocumentClient() 8 | const lambda = new AWS.Lambda() 9 | const kinesis = new AWS.Kinesis() 10 | const eventbridge = new AWS.EventBridge() 11 | 12 | const { 13 | BUCKET_NAME, 14 | TABLE_NAME, 15 | TOPIC_ARN, 16 | QUEUE_URL, 17 | FUNCTION_NAME, 18 | STREAM_NAME, 19 | BUS_NAME, 20 | } = process.env 21 | 22 | async function publishSNS() { 23 | await sns.publish({ 24 | TopicArn: TOPIC_ARN, 25 | Message: 'test' 26 | }).promise() 27 | } 28 | 29 | async function queueSQS() { 30 | await sqs.sendMessage({ 31 | QueueUrl: QUEUE_URL, 32 | MessageBody: 'test' 33 | }).promise() 34 | } 35 | 36 | async function callLambda() { 37 | await lambda.invoke({ 38 | FunctionName: FUNCTION_NAME, 39 | InvocationType: "RequestResponse", 40 | Payload: "" 41 | }).promise() 42 | } 43 | 44 | async function putS3(requestId) { 45 | await s3.putObject({ 46 | Body: 'test', 47 | Bucket: BUCKET_NAME, 48 | Key: `${requestId}.txt` 49 | }).promise() 50 | } 51 | 52 | async function putDynamoDB(requestId) { 53 | await dynamodb.put({ 54 | TableName: TABLE_NAME, 55 | Item: { 56 | id: requestId, 57 | } 58 | }).promise() 59 | } 60 | 61 | async function putKinesis(requestId) { 62 | await kinesis.putRecord({ 63 | StreamName: STREAM_NAME, 64 | Data: 'test', 65 | PartitionKey: requestId 66 | }).promise() 67 | } 68 | 69 | async function putEventBridge() { 70 | await eventbridge.putEvents({ 71 | Entries: [{ 72 | EventBusName: BUS_NAME, 73 | Source: 'xray-test', 74 | Detail: JSON.stringify({ message: 'test' }), 75 | DetailType: 'message' 76 | }] 77 | }).promise() 78 | } 79 | 80 | module.exports.handler = async (event, context) => { 81 | await Promise.all([ 82 | publishSNS(), 83 | queueSQS(), 84 | putS3(event.requestContext.requestId), 85 | putDynamoDB(event.requestContext.requestId), 86 | putKinesis(event.requestContext.requestId), 87 | callLambda(), 88 | putEventBridge(), 89 | ]) 90 | 91 | return { 92 | statusCode: 200, 93 | body: JSON.stringify({ 94 | message: 'done' 95 | }), 96 | } 97 | } -------------------------------------------------------------------------------- /serverless.yml: -------------------------------------------------------------------------------- 1 | service: lambda-x-ray-demo 2 | 3 | plugins: 4 | - serverless-iam-roles-per-function 5 | - serverless-lumigo 6 | 7 | custom: 8 | lumigo: 9 | token: ${ssm:/dev/lumigo-token} 10 | 11 | provider: 12 | name: aws 13 | runtime: nodejs14.x 14 | stage: dev 15 | region: us-east-1 16 | tracing: 17 | apiGateway: true 18 | lambda: true 19 | environment: 20 | stage: ${self:provider.stage} 21 | eventBridge: 22 | useCloudFormation: true 23 | 24 | functions: 25 | service-a: 26 | handler: functions/service-a.handler 27 | timeout: 10 28 | events: 29 | - http: 30 | path: /service-a 31 | method: get 32 | environment: 33 | BUCKET_NAME: !Ref S3Bucket 34 | TABLE_NAME: !Ref DynamoDB 35 | TOPIC_ARN: !Ref Topic 36 | QUEUE_URL: !Ref Queue 37 | FUNCTION_NAME: !Ref CallLambdaFunction 38 | STREAM_NAME: !Ref Kinesis 39 | BUS_NAME: !Ref EventBus 40 | iamRoleStatements: 41 | - Effect: Allow 42 | Action: dynamodb:PutItem 43 | Resource: !GetAtt DynamoDB.Arn 44 | - Effect: Allow 45 | Action: s3:PutObject* 46 | Resource: 47 | - !GetAtt S3Bucket.Arn 48 | - !Sub ${S3Bucket.Arn}/* 49 | - Effect: Allow 50 | Action: sns:Publish 51 | Resource: !Ref Topic 52 | - Effect: Allow 53 | Action: sqs:SendMessage 54 | Resource: !GetAtt Queue.Arn 55 | - Effect: Allow 56 | Action: lambda:InvokeFunction 57 | Resource: !GetAtt CallLambdaFunction.Arn 58 | - Effect: Allow 59 | Action: kinesis:PutRecord 60 | Resource: !GetAtt Kinesis.Arn 61 | - Effect: Allow 62 | Action: events:PutEvents 63 | Resource: !GetAtt EventBus.Arn 64 | - Effect: Allow 65 | Action: xray:Put* 66 | Resource: '*' 67 | 68 | service-b: 69 | handler: functions/service-b.handler 70 | events: 71 | - http: 72 | path: /service-b 73 | method: get 74 | 75 | call: 76 | handler: functions/service-c.handler 77 | 78 | timeout: 79 | handler: functions/timeout.handler 80 | timeout: 1 81 | events: 82 | - http: 83 | path: demo/timeout 84 | method: get 85 | 86 | error: 87 | handler: functions/error.handler 88 | events: 89 | - http: 90 | path: demo/error 91 | method: get 92 | 93 | sns: 94 | handler: functions/sns.handler 95 | events: 96 | - sns: 97 | topicName: test-topic 98 | arn: !Ref Topic 99 | 100 | sqs: 101 | handler: functions/sqs.handler 102 | events: 103 | - sqs: 104 | arn: !GetAtt Queue.Arn 105 | batchSize: 10 106 | 107 | s3: 108 | handler: functions/s3.handler 109 | events: 110 | - s3: 111 | existing: true 112 | event: s3:ObjectCreated:* 113 | bucket: !Ref S3Bucket 114 | 115 | kinesis: 116 | handler: functions/kinesis.handler 117 | events: 118 | - stream: 119 | type: kinesis 120 | arn: !GetAtt Kinesis.Arn 121 | 122 | dynamodb: 123 | handler: functions/dynamodb.handler 124 | events: 125 | - stream: 126 | type: dynamodb 127 | arn: !GetAtt DynamoDB.StreamArn 128 | 129 | eventbridge: 130 | handler: functions/event-bridge.handler 131 | events: 132 | - eventBridge: 133 | eventBus: !GetAtt EventBus.Name 134 | pattern: 135 | source: 136 | - xray-test 137 | 138 | # you can add CloudFormation resource templates here 139 | resources: 140 | Resources: 141 | S3Bucket: 142 | Type: AWS::S3::Bucket 143 | 144 | DynamoDB: 145 | Type: AWS::DynamoDB::Table 146 | Properties: 147 | BillingMode: PAY_PER_REQUEST 148 | AttributeDefinitions: 149 | - AttributeName: id 150 | AttributeType: S 151 | KeySchema: 152 | - AttributeName: id 153 | KeyType: HASH 154 | StreamSpecification: 155 | StreamViewType: NEW_AND_OLD_IMAGES 156 | 157 | Topic: 158 | Type: AWS::SNS::Topic 159 | Properties: 160 | TopicName: test-topic 161 | 162 | Queue: 163 | Type: AWS::SQS::Queue 164 | 165 | QueuePolicy: 166 | Type: AWS::SQS::QueuePolicy 167 | Properties: 168 | PolicyDocument: 169 | Statement: 170 | - Action: 171 | - SQS:SendMessage 172 | Effect: Allow 173 | Resource: !GetAtt Queue.Arn 174 | Principal: 175 | Service: sns.amazonaws.com 176 | Queues: 177 | - !Ref Queue 178 | 179 | Subscription: 180 | Type: AWS::SNS::Subscription 181 | Properties: 182 | Protocol: sqs 183 | Endpoint: !GetAtt Queue.Arn 184 | TopicArn: !Ref Topic 185 | 186 | Kinesis: 187 | Type: AWS::Kinesis::Stream 188 | Properties: 189 | ShardCount: 1 190 | 191 | EventBus: 192 | Type: AWS::Events::EventBus 193 | Properties: 194 | Name: xray-test 195 | --------------------------------------------------------------------------------