From 4bd8b593b94b01859b04023dc9d17f2830c197a9 Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Thu, 21 Feb 2019 14:52:31 +0100 Subject: [PATCH 1/3] Add AWS x-ray support for Lambda --- docs/providers/aws/guide/functions.md | 32 ++ docs/providers/aws/guide/serverless.yml.md | 5 +- .../aws/package/compile/functions/index.js | 35 +++ .../package/compile/functions/index.test.js | 282 ++++++++++++++++++ 4 files changed, 353 insertions(+), 1 deletion(-) diff --git a/docs/providers/aws/guide/functions.md b/docs/providers/aws/guide/functions.md index 9a3ae2266..2351063aa 100644 --- a/docs/providers/aws/guide/functions.md +++ b/docs/providers/aws/guide/functions.md @@ -28,6 +28,8 @@ provider: memorySize: 512 # optional, in MB, default is 1024 timeout: 10 # optional, in seconds, default is 6 versionFunctions: false # optional, default is true + tracingConfig: # optional, enables tracing for all functions (can be 'Active' or 'PassThrough') + mode: Active functions: hello: @@ -38,6 +40,8 @@ functions: memorySize: 512 # optional, in MB, default is 1024 timeout: 10 # optional, in seconds, default is 6 reservedConcurrency: 5 # optional, reserved concurrency limit for this function. By default, AWS uses account concurrency limit + tracingConfig: # optional, overwrite, can be 'Active' or 'PassThrough' + mode: PassThrough ``` The `handler` property points to the file and module containing the code you want to run in your function. @@ -430,3 +434,31 @@ functions: ### Secrets using environment variables and KMS When storing secrets in environment variables, AWS [strongly suggests](http://docs.aws.amazon.com/lambda/latest/dg/env_variables.html#env-storing-sensitive-data) encrypting sensitive information. AWS provides a [tutorial](http://docs.aws.amazon.com/lambda/latest/dg/tutorial-env_console.html) on using KMS for this purpose. + +## AWS X-Ray Tracing + +You can enable [AWS X-Ray Tracing](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html) on your Lambda functions through the optional `tracingConfig` config variable in conjucntion with the `mode` property: + +```yml +service: myService + +provider: + name: aws + runtime: nodejs8.10 + tracingConfig: + mode: Active +``` + +You can also set this variable on a per-function basis. This will override the provider level setting if present: + +```yml +functions: + hello: + handler: handler.hello + tracingConfig: + mode: Active + goodbye: + handler: handler.goodbye + tracingConfig: + mode: PassThrough +``` diff --git a/docs/providers/aws/guide/serverless.yml.md b/docs/providers/aws/guide/serverless.yml.md index 1a44a8e0e..4465c58a8 100644 --- a/docs/providers/aws/guide/serverless.yml.md +++ b/docs/providers/aws/guide/serverless.yml.md @@ -59,7 +59,6 @@ provider: '/users/create': xxxxxxxxxx apiKeySourceType: HEADER # Source of API key for usage plan. HEADER or AUTHORIZER. minimumCompressionSize: 1024 # Compress response when larger than specified size in bytes (must be between 0 and 10485760) - usagePlan: # Optional usage plan configuration quota: limit: 5000 @@ -118,6 +117,8 @@ provider: tags: # Optional service wide function tags foo: bar baz: qux + tracingConfig: + mode: Active # optional, can be 'Active' or 'PassThrough' package: # Optional deployment packaging configuration include: # Specify the directories and files which should be included in the deployment package @@ -164,6 +165,8 @@ functions: individually: true # Enables individual packaging for specific function. If true you must provide package for each function. Defaults to false layers: # An optional list Lambda Layers to use - arn:aws:lambda:region:XXXXXX:layer:LayerName:Y # Layer Version ARN + tracingConfig: + mode: Active # optional, can be 'Active' or 'PassThrough' (overwrites the one defined on the provider level) events: # The Events that trigger this Function - http: # This creates an API Gateway HTTP endpoint which can be used to trigger this function. Learn more in "events/apigateway" path: users/create # Path for this endpoint diff --git a/lib/plugins/aws/package/compile/functions/index.js b/lib/plugins/aws/package/compile/functions/index.js index 8a130d1c9..b2f83ed92 100644 --- a/lib/plugins/aws/package/compile/functions/index.js +++ b/lib/plugins/aws/package/compile/functions/index.js @@ -242,6 +242,41 @@ class AwsCompileFunctions { } } + const tracingConfig = functionObject.tracingConfig + || this.serverless.service.provider.tracingConfig; + + if (tracingConfig) { + if (tracingConfig.mode && typeof tracingConfig.mode === 'string') { + const iamRoleLambdaExecution = this.serverless.service.provider + .compiledCloudFormationTemplate.Resources.IamRoleLambdaExecution; + + newFunction.Properties.TracingConfig = { + Mode: tracingConfig.mode, + }; + + const stmt = { + Effect: 'Allow', + Action: [ + 'xray:PutTraceSegments', + 'xray:PutTelemetryRecords', + ], + Resource: ['*'], + }; + + // update the PolicyDocument statements (if default policy is used) + if (iamRoleLambdaExecution) { + iamRoleLambdaExecution.Properties.Policies[0].PolicyDocument.Statement = _.unionWith( + iamRoleLambdaExecution.Properties.Policies[0].PolicyDocument.Statement, + [stmt], + _.isEqual + ); + } + } else { + const errorMessage = 'tracingConfig must provide a "mode" property as a string'; + throw new this.serverless.classes.Error(errorMessage); + } + } + if (functionObject.environment || this.serverless.service.provider.environment) { newFunction.Properties.Environment = {}; newFunction.Properties.Environment.Variables = Object.assign( diff --git a/lib/plugins/aws/package/compile/functions/index.test.js b/lib/plugins/aws/package/compile/functions/index.test.js index 389204db1..662710695 100644 --- a/lib/plugins/aws/package/compile/functions/index.test.js +++ b/lib/plugins/aws/package/compile/functions/index.test.js @@ -1286,6 +1286,288 @@ describe('AwsCompileFunctions', () => { }); }); + describe('when using tracingConfig config', () => { + let s3Folder; + let s3FileName; + + beforeEach(() => { + s3Folder = awsCompileFunctions.serverless.service.package.artifactDirectoryName; + s3FileName = awsCompileFunctions.serverless.service.package.artifact + .split(path.sep).pop(); + }); + + it('should throw an error if "mode" config parameter is not provided', () => { + awsCompileFunctions.serverless.service.functions = { + func: { + handler: 'func.function.handler', + name: 'new-service-dev-func', + tracingConfig: 'Active', + }, + }; + + return expect(awsCompileFunctions.compileFunctions()) + .to.be.rejectedWith('property as a string'); + }); + + it('should throw an error if "mode" config paramter is not a string', () => { + awsCompileFunctions.serverless.service.functions = { + func: { + handler: 'func.function.handler', + name: 'new-service-dev-func', + tracingConfig: { + mode: 123, + }, + }, + }; + + return expect(awsCompileFunctions.compileFunctions()) + .to.be.rejectedWith('property as a string'); + }); + + it('should use a the provider wide tracingConfig config if provided', () => { + Object.assign(awsCompileFunctions.serverless.service.provider, { + tracingConfig: { + mode: 'Active', + }, + }); + + awsCompileFunctions.serverless.service.functions = { + func: { + handler: 'func.function.handler', + name: 'new-service-dev-func', + }, + }; + + const compiledFunction = { + Type: 'AWS::Lambda::Function', + DependsOn: [ + 'FuncLogGroup', + 'IamRoleLambdaExecution', + ], + Properties: { + Code: { + S3Key: `${s3Folder}/${s3FileName}`, + S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, + }, + FunctionName: 'new-service-dev-func', + Handler: 'func.function.handler', + MemorySize: 1024, + Role: { 'Fn::GetAtt': ['IamRoleLambdaExecution', 'Arn'] }, + Runtime: 'nodejs4.3', + Timeout: 6, + TracingConfig: { + Mode: 'Active', + }, + }, + }; + + return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { + const compiledCfTemplate = awsCompileFunctions.serverless.service.provider + .compiledCloudFormationTemplate; + const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + expect(functionResource).to.deep.equal(compiledFunction); + }); + }); + + it('should prefer a function tracingConfig config over a provider config', () => { + Object.assign(awsCompileFunctions.serverless.service.provider, { + tracingConfig: { + mode: 'Active', + }, + }); + + awsCompileFunctions.serverless.service.functions = { + func1: { + handler: 'func1.function.handler', + name: 'new-service-dev-func1', + tracingConfig: { + mode: 'PassThrough', + }, + }, + func2: { + handler: 'func2.function.handler', + name: 'new-service-dev-func2', + }, + }; + + const compiledFunction1 = { + Type: 'AWS::Lambda::Function', + DependsOn: [ + 'Func1LogGroup', + 'IamRoleLambdaExecution', + ], + Properties: { + Code: { + S3Key: `${s3Folder}/${s3FileName}`, + S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, + }, + FunctionName: 'new-service-dev-func1', + Handler: 'func1.function.handler', + MemorySize: 1024, + Role: { 'Fn::GetAtt': ['IamRoleLambdaExecution', 'Arn'] }, + Runtime: 'nodejs4.3', + Timeout: 6, + TracingConfig: { + Mode: 'PassThrough', + }, + }, + }; + + const compiledFunction2 = { + Type: 'AWS::Lambda::Function', + DependsOn: [ + 'Func2LogGroup', + 'IamRoleLambdaExecution', + ], + Properties: { + Code: { + S3Key: `${s3Folder}/${s3FileName}`, + S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, + }, + FunctionName: 'new-service-dev-func2', + Handler: 'func2.function.handler', + MemorySize: 1024, + Role: { 'Fn::GetAtt': ['IamRoleLambdaExecution', 'Arn'] }, + Runtime: 'nodejs4.3', + Timeout: 6, + TracingConfig: { + Mode: 'Active', + }, + }, + }; + + return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { + const compiledCfTemplate = awsCompileFunctions.serverless.service.provider + .compiledCloudFormationTemplate; + + const function1Resource = compiledCfTemplate.Resources.Func1LambdaFunction; + const function2Resource = compiledCfTemplate.Resources.Func2LambdaFunction; + expect(function1Resource).to.deep.equal(compiledFunction1); + expect(function2Resource).to.deep.equal(compiledFunction2); + }); + }); + + describe('when IamRoleLambdaExecution is used', () => { + beforeEach(() => { + // pretend that the IamRoleLambdaExecution is used + awsCompileFunctions.serverless.service.provider + .compiledCloudFormationTemplate.Resources.IamRoleLambdaExecution = { + Properties: { + Policies: [ + { + PolicyDocument: { + Statement: [], + }, + }, + ], + }, + }; + }); + + it('should create necessary resources if a tracingConfig config is provided', () => { + awsCompileFunctions.serverless.service.functions = { + func: { + handler: 'func.function.handler', + name: 'new-service-dev-func', + tracingConfig: { + mode: 'Active', + }, + }, + }; + + const compiledFunction = { + Type: 'AWS::Lambda::Function', + DependsOn: [ + 'FuncLogGroup', + 'IamRoleLambdaExecution', + ], + Properties: { + Code: { + S3Key: `${s3Folder}/${s3FileName}`, + S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, + }, + FunctionName: 'new-service-dev-func', + Handler: 'func.function.handler', + MemorySize: 1024, + Role: { 'Fn::GetAtt': ['IamRoleLambdaExecution', 'Arn'] }, + Runtime: 'nodejs4.3', + Timeout: 6, + TracingConfig: { + Mode: 'Active', + }, + }, + }; + + const compiledXrayStatement = { + Effect: 'Allow', + Action: [ + 'xray:PutTraceSegments', + 'xray:PutTelemetryRecords', + ], + Resource: ['*'], + }; + + return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { + const compiledCfTemplate = awsCompileFunctions.serverless.service.provider + .compiledCloudFormationTemplate; + + const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + const xrayStatement = compiledCfTemplate.Resources + .IamRoleLambdaExecution.Properties.Policies[0].PolicyDocument.Statement[0]; + + expect(functionResource).to.deep.equal(compiledFunction); + expect(xrayStatement).to.deep.equal(compiledXrayStatement); + }); + }); + }); + + describe('when IamRoleLambdaExecution is not used', () => { + it('should create necessary resources if a tracingConfig config is provided', () => { + awsCompileFunctions.serverless.service.functions = { + func: { + handler: 'func.function.handler', + name: 'new-service-dev-func', + tracingConfig: { + mode: 'Active', + }, + }, + }; + + const compiledFunction = { + Type: 'AWS::Lambda::Function', + DependsOn: [ + 'FuncLogGroup', + 'IamRoleLambdaExecution', + ], + Properties: { + Code: { + S3Key: `${s3Folder}/${s3FileName}`, + S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, + }, + FunctionName: 'new-service-dev-func', + Handler: 'func.function.handler', + MemorySize: 1024, + Role: { 'Fn::GetAtt': ['IamRoleLambdaExecution', 'Arn'] }, + Runtime: 'nodejs4.3', + Timeout: 6, + TracingConfig: { + Mode: 'Active', + }, + }, + }; + + return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { + const compiledCfTemplate = awsCompileFunctions.serverless.service.provider + .compiledCloudFormationTemplate; + + const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + + expect(functionResource).to.deep.equal(compiledFunction); + }); + }); + }); + }); + it('should create a function resource with environment config', () => { const s3Folder = awsCompileFunctions.serverless.service.package.artifactDirectoryName; const s3FileName = awsCompileFunctions.serverless.service.package.artifact From a0b9951ac2a3fa016e57eb536ef8b07919984e02 Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Fri, 22 Feb 2019 13:08:46 +0100 Subject: [PATCH 2/3] Move from object syntax to simple string syntax --- docs/providers/aws/guide/functions.md | 17 +++----- docs/providers/aws/guide/serverless.yml.md | 6 +-- .../aws/package/compile/functions/index.js | 6 +-- .../package/compile/functions/index.test.js | 41 ++++--------------- 4 files changed, 19 insertions(+), 51 deletions(-) diff --git a/docs/providers/aws/guide/functions.md b/docs/providers/aws/guide/functions.md index 2351063aa..ab452624a 100644 --- a/docs/providers/aws/guide/functions.md +++ b/docs/providers/aws/guide/functions.md @@ -28,8 +28,7 @@ provider: memorySize: 512 # optional, in MB, default is 1024 timeout: 10 # optional, in seconds, default is 6 versionFunctions: false # optional, default is true - tracingConfig: # optional, enables tracing for all functions (can be 'Active' or 'PassThrough') - mode: Active + tracingConfig: Active # optional, enables tracing for all functions (can be 'Active' or 'PassThrough') functions: hello: @@ -40,8 +39,7 @@ functions: memorySize: 512 # optional, in MB, default is 1024 timeout: 10 # optional, in seconds, default is 6 reservedConcurrency: 5 # optional, reserved concurrency limit for this function. By default, AWS uses account concurrency limit - tracingConfig: # optional, overwrite, can be 'Active' or 'PassThrough' - mode: PassThrough + tracingConfig: PassThrough # optional, overwrite, can be 'Active' or 'PassThrough' ``` The `handler` property points to the file and module containing the code you want to run in your function. @@ -437,7 +435,7 @@ When storing secrets in environment variables, AWS [strongly suggests](http://do ## AWS X-Ray Tracing -You can enable [AWS X-Ray Tracing](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html) on your Lambda functions through the optional `tracingConfig` config variable in conjucntion with the `mode` property: +You can enable [AWS X-Ray Tracing](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html) on your Lambda functions through the optional `tracingConfig` config variable: ```yml service: myService @@ -445,8 +443,7 @@ service: myService provider: name: aws runtime: nodejs8.10 - tracingConfig: - mode: Active + tracingConfig: Active ``` You can also set this variable on a per-function basis. This will override the provider level setting if present: @@ -455,10 +452,8 @@ You can also set this variable on a per-function basis. This will override the p functions: hello: handler: handler.hello - tracingConfig: - mode: Active + tracingConfig: Active goodbye: handler: handler.goodbye - tracingConfig: - mode: PassThrough + tracingConfig: PassThrough ``` diff --git a/docs/providers/aws/guide/serverless.yml.md b/docs/providers/aws/guide/serverless.yml.md index 4465c58a8..cec881588 100644 --- a/docs/providers/aws/guide/serverless.yml.md +++ b/docs/providers/aws/guide/serverless.yml.md @@ -117,8 +117,7 @@ provider: tags: # Optional service wide function tags foo: bar baz: qux - tracingConfig: - mode: Active # optional, can be 'Active' or 'PassThrough' + tracingConfig: Active # optional, can be 'Active' or 'PassThrough' package: # Optional deployment packaging configuration include: # Specify the directories and files which should be included in the deployment package @@ -165,8 +164,7 @@ functions: individually: true # Enables individual packaging for specific function. If true you must provide package for each function. Defaults to false layers: # An optional list Lambda Layers to use - arn:aws:lambda:region:XXXXXX:layer:LayerName:Y # Layer Version ARN - tracingConfig: - mode: Active # optional, can be 'Active' or 'PassThrough' (overwrites the one defined on the provider level) + tracingConfig: Active # optional, can be 'Active' or 'PassThrough' (overwrites the one defined on the provider level) events: # The Events that trigger this Function - http: # This creates an API Gateway HTTP endpoint which can be used to trigger this function. Learn more in "events/apigateway" path: users/create # Path for this endpoint diff --git a/lib/plugins/aws/package/compile/functions/index.js b/lib/plugins/aws/package/compile/functions/index.js index b2f83ed92..7d44ffdb8 100644 --- a/lib/plugins/aws/package/compile/functions/index.js +++ b/lib/plugins/aws/package/compile/functions/index.js @@ -246,12 +246,12 @@ class AwsCompileFunctions { || this.serverless.service.provider.tracingConfig; if (tracingConfig) { - if (tracingConfig.mode && typeof tracingConfig.mode === 'string') { + if (typeof tracingConfig === 'string') { const iamRoleLambdaExecution = this.serverless.service.provider .compiledCloudFormationTemplate.Resources.IamRoleLambdaExecution; newFunction.Properties.TracingConfig = { - Mode: tracingConfig.mode, + Mode: tracingConfig, }; const stmt = { @@ -272,7 +272,7 @@ class AwsCompileFunctions { ); } } else { - const errorMessage = 'tracingConfig must provide a "mode" property as a string'; + const errorMessage = 'tracingConfig requires the "mode" as a string'; throw new this.serverless.classes.Error(errorMessage); } } diff --git a/lib/plugins/aws/package/compile/functions/index.test.js b/lib/plugins/aws/package/compile/functions/index.test.js index 662710695..40d638f5d 100644 --- a/lib/plugins/aws/package/compile/functions/index.test.js +++ b/lib/plugins/aws/package/compile/functions/index.test.js @@ -1296,39 +1296,22 @@ describe('AwsCompileFunctions', () => { .split(path.sep).pop(); }); - it('should throw an error if "mode" config parameter is not provided', () => { + it('should throw an error if config paramter is not a string', () => { awsCompileFunctions.serverless.service.functions = { func: { handler: 'func.function.handler', name: 'new-service-dev-func', - tracingConfig: 'Active', + tracingConfig: 123, }, }; return expect(awsCompileFunctions.compileFunctions()) - .to.be.rejectedWith('property as a string'); - }); - - it('should throw an error if "mode" config paramter is not a string', () => { - awsCompileFunctions.serverless.service.functions = { - func: { - handler: 'func.function.handler', - name: 'new-service-dev-func', - tracingConfig: { - mode: 123, - }, - }, - }; - - return expect(awsCompileFunctions.compileFunctions()) - .to.be.rejectedWith('property as a string'); + .to.be.rejectedWith('as a string'); }); it('should use a the provider wide tracingConfig config if provided', () => { Object.assign(awsCompileFunctions.serverless.service.provider, { - tracingConfig: { - mode: 'Active', - }, + tracingConfig: 'Active', }); awsCompileFunctions.serverless.service.functions = { @@ -1371,18 +1354,14 @@ describe('AwsCompileFunctions', () => { it('should prefer a function tracingConfig config over a provider config', () => { Object.assign(awsCompileFunctions.serverless.service.provider, { - tracingConfig: { - mode: 'Active', - }, + tracingConfig: 'Active', }); awsCompileFunctions.serverless.service.functions = { func1: { handler: 'func1.function.handler', name: 'new-service-dev-func1', - tracingConfig: { - mode: 'PassThrough', - }, + tracingConfig: 'PassThrough', }, func2: { handler: 'func2.function.handler', @@ -1469,9 +1448,7 @@ describe('AwsCompileFunctions', () => { func: { handler: 'func.function.handler', name: 'new-service-dev-func', - tracingConfig: { - mode: 'Active', - }, + tracingConfig: 'Active', }, }; @@ -1527,9 +1504,7 @@ describe('AwsCompileFunctions', () => { func: { handler: 'func.function.handler', name: 'new-service-dev-func', - tracingConfig: { - mode: 'Active', - }, + tracingConfig: 'Active', }, }; From 72ce7d907ccf9a61fc134b87c63a392d4dfe45e6 Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Wed, 27 Feb 2019 13:40:39 +0100 Subject: [PATCH 3/3] Simplify tracing configuration --- docs/providers/aws/guide/functions.md | 14 ++++---- docs/providers/aws/guide/serverless.yml.md | 5 +-- .../aws/package/compile/functions/index.js | 19 +++++++---- .../package/compile/functions/index.test.js | 32 +++++++++++-------- 4 files changed, 42 insertions(+), 28 deletions(-) diff --git a/docs/providers/aws/guide/functions.md b/docs/providers/aws/guide/functions.md index ab452624a..ecdfe09ed 100644 --- a/docs/providers/aws/guide/functions.md +++ b/docs/providers/aws/guide/functions.md @@ -28,7 +28,8 @@ provider: memorySize: 512 # optional, in MB, default is 1024 timeout: 10 # optional, in seconds, default is 6 versionFunctions: false # optional, default is true - tracingConfig: Active # optional, enables tracing for all functions (can be 'Active' or 'PassThrough') + tracing: + lambda: true # optional, enables tracing for all functions (can be true (true equals 'Active') 'Active' or 'PassThrough') functions: hello: @@ -39,7 +40,7 @@ functions: memorySize: 512 # optional, in MB, default is 1024 timeout: 10 # optional, in seconds, default is 6 reservedConcurrency: 5 # optional, reserved concurrency limit for this function. By default, AWS uses account concurrency limit - tracingConfig: PassThrough # optional, overwrite, can be 'Active' or 'PassThrough' + tracing: PassThrough # optional, overwrite, can be 'Active' or 'PassThrough' ``` The `handler` property points to the file and module containing the code you want to run in your function. @@ -435,7 +436,7 @@ When storing secrets in environment variables, AWS [strongly suggests](http://do ## AWS X-Ray Tracing -You can enable [AWS X-Ray Tracing](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html) on your Lambda functions through the optional `tracingConfig` config variable: +You can enable [AWS X-Ray Tracing](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html) on your Lambda functions through the optional `tracing` config variable: ```yml service: myService @@ -443,7 +444,8 @@ service: myService provider: name: aws runtime: nodejs8.10 - tracingConfig: Active + tracing: + lambda: true ``` You can also set this variable on a per-function basis. This will override the provider level setting if present: @@ -452,8 +454,8 @@ You can also set this variable on a per-function basis. This will override the p functions: hello: handler: handler.hello - tracingConfig: Active + tracing: Active goodbye: handler: handler.goodbye - tracingConfig: PassThrough + tracing: PassThrough ``` diff --git a/docs/providers/aws/guide/serverless.yml.md b/docs/providers/aws/guide/serverless.yml.md index cec881588..7425200de 100644 --- a/docs/providers/aws/guide/serverless.yml.md +++ b/docs/providers/aws/guide/serverless.yml.md @@ -117,7 +117,8 @@ provider: tags: # Optional service wide function tags foo: bar baz: qux - tracingConfig: Active # optional, can be 'Active' or 'PassThrough' + tracing: + lambda: true # optional, can be true (true equals 'Active'), 'Active' or 'PassThrough' package: # Optional deployment packaging configuration include: # Specify the directories and files which should be included in the deployment package @@ -164,7 +165,7 @@ functions: individually: true # Enables individual packaging for specific function. If true you must provide package for each function. Defaults to false layers: # An optional list Lambda Layers to use - arn:aws:lambda:region:XXXXXX:layer:LayerName:Y # Layer Version ARN - tracingConfig: Active # optional, can be 'Active' or 'PassThrough' (overwrites the one defined on the provider level) + tracing: Active # optional, can be 'Active' or 'PassThrough' (overwrites the one defined on the provider level) events: # The Events that trigger this Function - http: # This creates an API Gateway HTTP endpoint which can be used to trigger this function. Learn more in "events/apigateway" path: users/create # Path for this endpoint diff --git a/lib/plugins/aws/package/compile/functions/index.js b/lib/plugins/aws/package/compile/functions/index.js index 7d44ffdb8..6eee5d75e 100644 --- a/lib/plugins/aws/package/compile/functions/index.js +++ b/lib/plugins/aws/package/compile/functions/index.js @@ -242,16 +242,23 @@ class AwsCompileFunctions { } } - const tracingConfig = functionObject.tracingConfig - || this.serverless.service.provider.tracingConfig; + const tracing = functionObject.tracing + || (this.serverless.service.provider.tracing + && this.serverless.service.provider.tracing.lambda); + + if (tracing) { + if (typeof tracing === 'boolean' || typeof tracing === 'string') { + let mode = tracing; + + if (typeof tracing === 'boolean') { + mode = 'Active'; + } - if (tracingConfig) { - if (typeof tracingConfig === 'string') { const iamRoleLambdaExecution = this.serverless.service.provider .compiledCloudFormationTemplate.Resources.IamRoleLambdaExecution; newFunction.Properties.TracingConfig = { - Mode: tracingConfig, + Mode: mode, }; const stmt = { @@ -272,7 +279,7 @@ class AwsCompileFunctions { ); } } else { - const errorMessage = 'tracingConfig requires the "mode" as a string'; + const errorMessage = 'tracing requires a boolean value or the "mode" provided as a string'; throw new this.serverless.classes.Error(errorMessage); } } diff --git a/lib/plugins/aws/package/compile/functions/index.test.js b/lib/plugins/aws/package/compile/functions/index.test.js index 40d638f5d..722285ba2 100644 --- a/lib/plugins/aws/package/compile/functions/index.test.js +++ b/lib/plugins/aws/package/compile/functions/index.test.js @@ -1286,7 +1286,7 @@ describe('AwsCompileFunctions', () => { }); }); - describe('when using tracingConfig config', () => { + describe('when using tracing config', () => { let s3Folder; let s3FileName; @@ -1301,7 +1301,7 @@ describe('AwsCompileFunctions', () => { func: { handler: 'func.function.handler', name: 'new-service-dev-func', - tracingConfig: 123, + tracing: 123, }, }; @@ -1309,9 +1309,11 @@ describe('AwsCompileFunctions', () => { .to.be.rejectedWith('as a string'); }); - it('should use a the provider wide tracingConfig config if provided', () => { + it('should use a the provider wide tracing config if provided', () => { Object.assign(awsCompileFunctions.serverless.service.provider, { - tracingConfig: 'Active', + tracing: { + lambda: true, + }, }); awsCompileFunctions.serverless.service.functions = { @@ -1352,16 +1354,18 @@ describe('AwsCompileFunctions', () => { }); }); - it('should prefer a function tracingConfig config over a provider config', () => { + it('should prefer a function tracing config over a provider config', () => { Object.assign(awsCompileFunctions.serverless.service.provider, { - tracingConfig: 'Active', + tracing: { + lambda: 'PassThrough', + }, }); awsCompileFunctions.serverless.service.functions = { func1: { handler: 'func1.function.handler', name: 'new-service-dev-func1', - tracingConfig: 'PassThrough', + tracing: 'Active', }, func2: { handler: 'func2.function.handler', @@ -1387,7 +1391,7 @@ describe('AwsCompileFunctions', () => { Runtime: 'nodejs4.3', Timeout: 6, TracingConfig: { - Mode: 'PassThrough', + Mode: 'Active', }, }, }; @@ -1410,7 +1414,7 @@ describe('AwsCompileFunctions', () => { Runtime: 'nodejs4.3', Timeout: 6, TracingConfig: { - Mode: 'Active', + Mode: 'PassThrough', }, }, }; @@ -1443,12 +1447,12 @@ describe('AwsCompileFunctions', () => { }; }); - it('should create necessary resources if a tracingConfig config is provided', () => { + it('should create necessary resources if a tracing config is provided', () => { awsCompileFunctions.serverless.service.functions = { func: { handler: 'func.function.handler', name: 'new-service-dev-func', - tracingConfig: 'Active', + tracing: 'Active', }, }; @@ -1499,12 +1503,12 @@ describe('AwsCompileFunctions', () => { }); describe('when IamRoleLambdaExecution is not used', () => { - it('should create necessary resources if a tracingConfig config is provided', () => { + it('should create necessary resources if a tracing config is provided', () => { awsCompileFunctions.serverless.service.functions = { func: { handler: 'func.function.handler', name: 'new-service-dev-func', - tracingConfig: 'Active', + tracing: 'PassThrough', }, }; @@ -1526,7 +1530,7 @@ describe('AwsCompileFunctions', () => { Runtime: 'nodejs4.3', Timeout: 6, TracingConfig: { - Mode: 'Active', + Mode: 'PassThrough', }, }, };