Skip to content

Commit

Permalink
Initial release
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexandr Murashkin authored and Alexandr Murashkin committed May 16, 2017
1 parent 1fc7636 commit 68dc7e6
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 1 deletion.
1 change: 1 addition & 0 deletions .coveralls.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
repo_token: DJGAL2yp0e1J24hc7m5Mlot2zKP0Y9vh4
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
coverage/
12 changes: 12 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root: true

env:
node: true
es6: true
mocha: true

extends:
"eslint:recommended"

ecmaFeatures:
generators: true
8 changes: 8 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
test/
coverage/
.editorconfig
.eslintignore
.eslintrc
.gitignore
.npmignore
.travis.yml
44 changes: 43 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,44 @@
# serverless-plugin-tracing
Enables AWS X-Ray tracing for Serverless

[![npm version](https://badge.fury.io/js/serverless-plugin-tracing.svg)](https://badge.fury.io/js/serverless-plugin-tracing)
[![CircleCI](https://circleci.com/gh/AlexanderMS/serverless-plugin-tracing.svg?style=shield)](https://circleci.com/gh/AlexanderMS/serverless-plugin-tracing)
[![Coverage Status](https://coveralls.io/repos/github/AlexanderMS/serverless-plugin-tracing/badge.svg)](https://coveralls.io/github/AlexanderMS/serverless-plugin-tracing)

Enables AWS X-Ray (https://aws.amazon.com/xray/) for entire Serverless stack or individual functions.

Note: this plugin is currently **Beta**.

`npm install --save-dev serverless-plugin-tracing`

Example:

```yml
service: my-great-service

provider:
name: aws
stage: test
tracing: true # enable tracing
iamRoleStatements:
- Effect: "Allow" # xray permissions (required)
Action:
- "xray:PutTraceSegments"
- "xray:PutTelemetryRecords"
Resource:
- "*"

plugins:
- serverless-plugin-tracing

functions:
mainFunction: # inherits tracing settings from "provider"
handler: src/app/index.handler
healthcheck:
tracing: false # overrides provider settings (opt out)
```
Output after `serverless deploy`:
```
Serverless: Tracing ENABLED for function "my-great-service-test-mainFunction"
Serverless: Tracing DISABLED for function "my-great-service-test-healthcheck"
```
32 changes: 32 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';

module.exports = class TracingConfigPlugin {
constructor(serverless) {
this.serverless = serverless;
this.aws = serverless.getProvider('aws');
this.hooks = {
'after:deploy:deploy': this.processTracing.bind(this)
};
}

processTracing() {
const service = this.serverless.service;
const providerLevelTracingEnabled = (service.provider.tracing === true);
Object.keys(service.functions).forEach(functionName => {
this.toggleTracing(`${service.service}-${service.provider.stage}-${functionName}`,
(service.functions[functionName].tracing === true)
|| (providerLevelTracingEnabled && service.functions[functionName].tracing !== false)
);
});
}

toggleTracing(functionName, isEnabled) {
this.serverless.cli.log(`Tracing ${isEnabled ? 'ENABLED' : 'DISABLED'} for function "${functionName}"`);
this.aws.request('Lambda', 'updateFunctionConfiguration', {
FunctionName: functionName,
TracingConfig: {
Mode: isEnabled === true ? 'Active' : 'PassThrough'
}
});
}
};
46 changes: 46 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "serverless-plugin-tracing",
"version": "1.0.0",
"description": "Enables AWS X-Ray for entire Serverless stack or individual functions",
"main": "index.js",
"engines": {
"node": ">=4.0"
},
"directories": {
"test": "test"
},
"scripts": {
"coverage": "nyc report --reporter=lcov",
"coveralls-coverage": "nyc report --reporter=text-lcov | coveralls",
"lint": "eslint .",
"test": "nyc --all mocha --recursive ./test",
"posttest": "eslint ."
},
"keywords": [
"serverless",
"aws",
"tracing",
"trace",
"xray",
"x-ray"
],
"repository": {
"type": "git",
"url": "git+https://github.com/AlexanderMS/serverless-plugin-tracing.git"
},
"author": "Alex Murashkin",
"license": "MIT",
"bugs": {
"url": "https://github.com/AlexanderMS/serverless-plugin-tracing/issues"
},
"homepage": "https://github.com/AlexanderMS/serverless-plugin-tracing#readme",
"dependencies": {},
"devDependencies": {
"chai": "^3.5.0",
"coveralls": "^2.13.0",
"eslint": "^3.18.0",
"mocha": "^3.2.0",
"nyc": "^10.2.0",
"sinon": "^2.1.0"
}
}
164 changes: 164 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
'use strict';

const
sinon = require('sinon'),
assert = require('chai').assert,
Plugin = require('../index');

describe('serverless-plugin-tracing', function() {
let sandbox, logSpy, requestSpy, serverlessBaseInstance;
beforeEach(function() {
sandbox = sinon.sandbox.create();
logSpy = sandbox.spy();
requestSpy = sandbox.spy();
serverlessBaseInstance = {
service: {
service: 'myService',
functions: {
},
provider: {
stage: 'test'
}
},
cli: {
log: logSpy
},
getProvider: () => ({
request: requestSpy
})
};
});

function runPlugin(params) {
const serverlessInstance = Object.assign({}, serverlessBaseInstance);
serverlessInstance.service.provider = Object.assign({},
serverlessInstance.service.provider,
params.provider);

serverlessInstance.service.functions = params.functions;
const plugin = new Plugin(serverlessInstance);
plugin.hooks['after:deploy:deploy'].call(plugin);
return plugin;
}

afterEach(function() {
sandbox.verifyAndRestore();
});

it('enables tracing when function.tracing=true', function() {
runPlugin({
functions: {
healthcheck: {
},
mainFunction: {
tracing: true
}
},
provider: {
}
});

assert.deepEqual(logSpy.getCall(0).args[0], 'Tracing DISABLED for function "myService-test-healthcheck"');
assert.deepEqual(logSpy.getCall(1).args[0], 'Tracing ENABLED for function "myService-test-mainFunction"');
assert.deepEqual(requestSpy.getCall(0).args, [
'Lambda',
'updateFunctionConfiguration',
{
FunctionName: 'myService-test-healthcheck',
TracingConfig: {
Mode: 'PassThrough'
}
}
]);

assert.deepEqual(requestSpy.getCall(1).args, [
'Lambda',
'updateFunctionConfiguration',
{
FunctionName: 'myService-test-mainFunction',
TracingConfig: {
Mode: 'Active'
}
}
]);
});

it('enables tracing when provider.tracing=true', function() {
runPlugin({
functions: {
healthcheck: {
},
mainFunction: {
tracing: true
}
},
provider: {
tracing: true
}
});

assert.deepEqual(logSpy.getCall(0).args[0], 'Tracing ENABLED for function "myService-test-healthcheck"');
assert.deepEqual(logSpy.getCall(1).args[0], 'Tracing ENABLED for function "myService-test-mainFunction"');
assert.deepEqual(requestSpy.getCall(0).args, [
'Lambda',
'updateFunctionConfiguration',
{
FunctionName: 'myService-test-healthcheck',
TracingConfig: {
Mode: 'Active'
}
}
]);

assert.deepEqual(requestSpy.getCall(1).args, [
'Lambda',
'updateFunctionConfiguration',
{
FunctionName: 'myService-test-mainFunction',
TracingConfig: {
Mode: 'Active'
}
}
]);
});

it('does not enable tracing when provider.tracing=true but function.tracing=false', function() {
runPlugin({
functions: {
healthcheck: {
tracing: false
},
mainFunction: {
tracing: true
}
},
provider: {
tracing: true
}
});

assert.deepEqual(logSpy.getCall(0).args[0], 'Tracing DISABLED for function "myService-test-healthcheck"');
assert.deepEqual(logSpy.getCall(1).args[0], 'Tracing ENABLED for function "myService-test-mainFunction"');
assert.deepEqual(requestSpy.getCall(0).args, [
'Lambda',
'updateFunctionConfiguration',
{
FunctionName: 'myService-test-healthcheck',
TracingConfig: {
Mode: 'PassThrough'
}
}
]);

assert.deepEqual(requestSpy.getCall(1).args, [
'Lambda',
'updateFunctionConfiguration',
{
FunctionName: 'myService-test-mainFunction',
TracingConfig: {
Mode: 'Active'
}
}
]);
});
});

0 comments on commit 68dc7e6

Please sign in to comment.