Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
version: 2.1

executors:
node:
docker:
- image: circleci/node:lts
working_directory: ~/repo

commands:
setup-js:
description: "Setup JS enviornment"
steps:
- run: npm install
check:
description: "Run test and code coverage"
steps:
- run: npm run check

jobs:
check:
executor: node
steps:
- checkout
- setup-js
- check
- save_cache:
key: build-cache-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
paths:
- "node_modules"

workflows:
build:
jobs:
- check:
filters:
tags:
only: /.*/
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# EditorConfig is awesome: https://EditorConfig.org

root = true

[*]
end_of_line = lf
insert_final_newline = true

[*.{js}]
charset = utf-8
indent_style = space
indent_size = 2

[{package.json,config.yml}]
indent_style = space
indent_size = 2
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
.nyc_output/
43 changes: 42 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,43 @@
# smartthings-zipkin-js
SmartThings JavaScript Zipkin packages

SmartThings JavaScript Zipkin package

## SQS Options

All SQS interactions are handled using the `sqs-producer` package, which minimizes the code required to enqueue new
messages. `sqs-producer` is an abstraction on top of the official AWS SQS lib and as all configuration options used to
create an SQS client instance should be valid. The only required configuration option is `queueUrl`.

[https://github.com/bbc/sqs-producer](https://github.com/bbc/sqs-producer)

## AWS AssumeRole

In accordance with best practices, this package allows for interactions with AWS services to operate under an assumed
role. By default the IAM credentials provided by the AWS instance will be used for all interactions. The presence of a
an `assumeRole` configuration block will result in an auth session using an assumed role which provides the ability to
leave the minimally required access permissions for a user and rely in IAM roles to grant appropriate access.

[https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/STS.html#assumeRole-property](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/STS.html#assumeRole-property)

## Error Handling

The default configuration will log errors to the console. If you would like to leverage a pre-existing logging solution,
simply provide a logger instance in your configuration. The `error` method of the logger will be called with any errors
encountered during execution.

## Configuration Options

```javascript
{
"onError": myLogger,
"assumeRole": {
"DurationSeconds": 3600,
"RoleArn": "arn:aws:iam::123456789012:role/demo",
"RoleSessionName": "Bob"
},
"sqs": {
"queueUrl": "https://sqs.eu-west-1.amazonaws.com/account-id/queue-name",
"region": "eu-west-1"
}
}
```
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./lib/LoggerFactory');
84 changes: 84 additions & 0 deletions lib/LoggerFactory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const AWS = require("aws-sdk");
const Producer = require("sqs-producer");
const {
jsonEncoder: { JSON_V2 }
} = require("zipkin");
const SQSLogger = require("./SQSLogger");

const encoder = { encode: span => `[${JSON_V2.encode(span)}]` };

const LoggerFactory = {
assumeRole(opts, cb) {
const sts = new AWS.STS();
sts.assumeRole(opts, (error, data) => {
if (error) {
cb(error);
} else {
const modEnv = process.env;

modEnv.AWS_ACCESS_KEY_ID = data.Credentials.AccessKeyId;
modEnv.AWS_SECRET_ACCESS_KEY = data.Credentials.SecretAccessKey;
modEnv.AWS_SESSION_TOKEN = data.Credentials.SessionToken;

cb(null, {
AWS_ACCESS_KEY_ID: data.Credentials.AccessKeyId,
AWS_SECRET_ACCESS_KEY: data.Credentials.SecretAccessKey,
AWS_SESSION_TOKEN: data.Credentials.SessionToken
});
}
});
},

createLogger(opts, cb) {
const sqsDefaults = {
region: "us-east-1"
};

const options = Object.assign({}, opts);
const sqsOpts = Object.assign({}, sqsDefaults, options.sqs || {});

const onError =
options.onError ||
function(err) {
const log = options.log || console;
log.error(err);
};

const loggerOpts = {
encoder,
onError
};

if (options.assumeRole) {
this.assumeRole(options.assumeRole, (error, creds) => {
if (error) {
cb(error);
} else {
const opts = Object.assign({}, sqsOpts, creds);
const producer = Producer.create(opts);
const logger = new SQSLogger(
Object.assign({}, loggerOpts, {
producer
})
);

cb(null, logger);
}
});
} else {
try {
const producer = Producer.create(sqsOpts);
const logger = new SQSLogger(
Object.assign({}, loggerOpts, {
producer
})
);
cb(null, logger);
} catch (error) {
cb(error);
}
}
}
};

module.exports = LoggerFactory;
26 changes: 26 additions & 0 deletions lib/SQSLogger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const uuidv1 = require("uuid/v1");

function SQSLogger(options) {
this.producer = options.producer;
this.onError = options.onError;
this.encoder = options.encoder;
}

SQSLogger.prototype.logSpan = function(span) {
try {
const payload = {
id: uuidv1(),
body: this.encoder.encode(span)
};

this.producer.send([payload], error => {
if (error) {
this.onError(error);
}
});
} catch (error) {
this.onError(error);
}
};

module.exports = SQSLogger;
Loading