Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

winston-aws-cloudwatch

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

winston-aws-cloudwatch - npm Package Compare versions

Comparing version 2.0.0 to 3.0.0

186

lib/cloudwatch-client.js

@@ -1,31 +0,7 @@

'use strict';
const _debug = require('debug')
const AWS = require('aws-sdk')
const CloudWatchEventFormatter = require('./cloudwatch-event-formatter')
Object.defineProperty(exports, "__esModule", {
value: true
});
const debug = _debug('winston-aws-cloudwatch:CloudWatchClient')
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
var _debug2 = require('debug');
var _debug3 = _interopRequireDefault(_debug2);
var _awsSdk = require('aws-sdk');
var _awsSdk2 = _interopRequireDefault(_awsSdk);
var _cloudwatchEventFormatter = require('./cloudwatch-event-formatter');
var _cloudwatchEventFormatter2 = _interopRequireDefault(_cloudwatchEventFormatter);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const debug = (0, _debug3.default)('winston-aws-cloudwatch:CloudWatchClient');
const DEFAULT_OPTIONS = {

@@ -38,41 +14,46 @@ awsConfig: null,

submissionRetryCount: 1
};
}
class CloudWatchClient {
constructor(logGroupName, logStreamName, options) {
debug('constructor', { logGroupName, logStreamName, options });
this._logGroupName = logGroupName;
this._logStreamName = logStreamName;
this._options = (0, _assign2.default)({}, DEFAULT_OPTIONS, options);
this._formatter = new _cloudwatchEventFormatter2.default(this._options);
this._sequenceToken = null;
this._client = new _awsSdk2.default.CloudWatchLogs(this._options.awsConfig);
this._initializing = null;
constructor (logGroupName, logStreamName, options) {
debug('constructor', { logGroupName, logStreamName, options })
this._logGroupName = logGroupName
this._logStreamName = logStreamName
this._options = Object.assign({}, DEFAULT_OPTIONS, options)
this._formatter = new CloudWatchEventFormatter(this._options)
this._sequenceToken = null
this._client = new AWS.CloudWatchLogs(this._options.awsConfig)
this._initializing = null
}
submit(batch) {
debug('submit', { batch });
return this._initialize().then(() => this._doSubmit(batch, 0));
submit (batch) {
debug('submit', { batch })
return this._initialize().then(() => this._doSubmit(batch, 0))
}
_initialize() {
_initialize () {
if (this._initializing == null) {
this._initializing = this._maybeCreateLogGroup().then(() => this._maybeCreateLogStream());
this._initializing = this._maybeCreateLogGroup().then(() =>
this._maybeCreateLogStream()
)
}
return this._initializing;
return this._initializing
}
_maybeCreateLogGroup() {
_maybeCreateLogGroup () {
if (!this._options.createLogGroup) {
return _promise2.default.resolve();
return Promise.resolve()
}
const params = {
logGroupName: this._logGroupName
};
return this._client.createLogGroup(params).promise().catch(err => this._allowResourceAlreadyExistsException(err));
}
return this._client
.createLogGroup(params)
.promise()
.catch(err => this._allowResourceAlreadyExistsException(err))
}
_maybeCreateLogStream() {
_maybeCreateLogStream () {
if (!this._options.createLogStream) {
return _promise2.default.resolve();
return Promise.resolve()
}

@@ -82,38 +63,49 @@ const params = {

logStreamName: this._logStreamName
};
return this._client.createLogStream(params).promise().catch(err => this._allowResourceAlreadyExistsException(err));
}
return this._client
.createLogStream(params)
.promise()
.catch(err => this._allowResourceAlreadyExistsException(err))
}
_allowResourceAlreadyExistsException(err) {
return err.code === 'ResourceAlreadyExistsException' ? _promise2.default.resolve() : _promise2.default.reject(err);
_allowResourceAlreadyExistsException (err) {
return err.code === 'ResourceAlreadyExistsException'
? Promise.resolve()
: Promise.reject(err)
}
_doSubmit(batch, retryCount) {
return this._maybeUpdateSequenceToken().then(() => this._putLogEventsAndStoreSequenceToken(batch)).catch(err => this._handlePutError(err, batch, retryCount));
_doSubmit (batch, retryCount) {
return this._maybeUpdateSequenceToken()
.then(() => this._putLogEventsAndStoreSequenceToken(batch))
.catch(err => this._handlePutError(err, batch, retryCount))
}
_maybeUpdateSequenceToken() {
return this._sequenceToken != null ? _promise2.default.resolve() : this._fetchAndStoreSequenceToken();
_maybeUpdateSequenceToken () {
return this._sequenceToken != null
? Promise.resolve()
: this._fetchAndStoreSequenceToken()
}
_handlePutError(err, batch, retryCount) {
_handlePutError (err, batch, retryCount) {
if (err.code !== 'InvalidSequenceTokenException') {
return _promise2.default.reject(err);
return Promise.reject(err)
}
if (retryCount >= this._options.submissionRetryCount) {
const error = new Error('Invalid sequence token, will retry');
error.code = 'InvalidSequenceTokenException';
return _promise2.default.reject(error);
const error = new Error('Invalid sequence token, will retry')
error.code = 'InvalidSequenceTokenException'
return Promise.reject(error)
}
this._sequenceToken = null;
return this._doSubmit(batch, retryCount + 1);
this._sequenceToken = null
return this._doSubmit(batch, retryCount + 1)
}
_putLogEventsAndStoreSequenceToken(batch) {
return this._putLogEvents(batch).then(({ nextSequenceToken }) => this._storeSequenceToken(nextSequenceToken));
_putLogEventsAndStoreSequenceToken (batch) {
return this._putLogEvents(batch).then(({ nextSequenceToken }) =>
this._storeSequenceToken(nextSequenceToken)
)
}
_putLogEvents(batch) {
const sequenceToken = this._sequenceToken;
debug('putLogEvents', { batch, sequenceToken });
_putLogEvents (batch) {
const sequenceToken = this._sequenceToken
debug('putLogEvents', { batch, sequenceToken })
const params = {

@@ -124,19 +116,21 @@ logGroupName: this._logGroupName,

sequenceToken
};
return this._client.putLogEvents(params).promise();
}
return this._client.putLogEvents(params).promise()
}
_fetchAndStoreSequenceToken() {
debug('fetchSequenceToken');
return this._findLogStream().then(({ uploadSequenceToken }) => this._storeSequenceToken(uploadSequenceToken));
_fetchAndStoreSequenceToken () {
debug('fetchSequenceToken')
return this._findLogStream().then(({ uploadSequenceToken }) =>
this._storeSequenceToken(uploadSequenceToken)
)
}
_storeSequenceToken(sequenceToken) {
debug('storeSequenceToken', { sequenceToken });
this._sequenceToken = sequenceToken;
return sequenceToken;
_storeSequenceToken (sequenceToken) {
debug('storeSequenceToken', { sequenceToken })
this._sequenceToken = sequenceToken
return sequenceToken
}
_findLogStream(nextToken) {
debug('findLogStream', { nextToken });
_findLogStream (nextToken) {
debug('findLogStream', { nextToken })
const params = {

@@ -146,15 +140,21 @@ logGroupName: this._logGroupName,

nextToken
};
return this._client.describeLogStreams(params).promise().then(({ logStreams, nextToken }) => {
const match = logStreams.find(({ logStreamName }) => logStreamName === this._logStreamName);
if (match) {
return match;
}
if (nextToken == null) {
throw new Error('Log stream not found');
}
return this._findLogStream(nextToken);
});
}
return this._client
.describeLogStreams(params)
.promise()
.then(({ logStreams, nextToken }) => {
const match = logStreams.find(
({ logStreamName }) => logStreamName === this._logStreamName
)
if (match) {
return match
}
if (nextToken == null) {
throw new Error('Log stream not found')
}
return this._findLogStream(nextToken)
})
}
}
exports.default = CloudWatchClient;
module.exports = CloudWatchClient

@@ -1,38 +0,27 @@

'use strict';
const isEmpty = require('lodash.isempty')
Object.defineProperty(exports, "__esModule", {
value: true
});
var _stringify = require('babel-runtime/core-js/json/stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _lodash = require('lodash.isempty');
var _lodash2 = _interopRequireDefault(_lodash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
class CloudWatchEventFormatter {
constructor({ formatLog, formatLogItem } = {}) {
constructor ({ formatLog, formatLogItem } = {}) {
if (typeof formatLog === 'function') {
this.formatLog = formatLog;
this.formatLog = formatLog
} else if (typeof formatLogItem === 'function') {
this.formatLogItem = formatLogItem;
this.formatLogItem = formatLogItem
}
}
formatLogItem(item) {
formatLogItem (item) {
return {
message: this.formatLog(item),
timestamp: item.date
};
}
}
formatLog(item) {
const meta = (0, _lodash2.default)(item.meta) ? '' : ' ' + (0, _stringify2.default)(item.meta, null, 2);
return `[${item.level.toUpperCase()}] ${item.message}${meta}`;
formatLog (item) {
const meta = isEmpty(item.meta)
? ''
: ' ' + JSON.stringify(item.meta, null, 2)
return `[${item.level.toUpperCase()}] ${item.message}${meta}`
}
}
exports.default = CloudWatchEventFormatter;
module.exports = CloudWatchEventFormatter

@@ -1,37 +0,29 @@

'use strict';
const Transport = require('winston-transport')
const CloudWatchClient = require('./cloudwatch-client')
const LogItem = require('./log-item')
const Relay = require('./relay')
Object.defineProperty(exports, "__esModule", {
value: true
});
var _winston = require('winston');
var _cloudwatchClient = require('./cloudwatch-client');
var _cloudwatchClient2 = _interopRequireDefault(_cloudwatchClient);
var _logItem = require('./log-item');
var _logItem2 = _interopRequireDefault(_logItem);
var _relay = require('./relay');
var _relay2 = _interopRequireDefault(_relay);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
class CloudWatchTransport extends _winston.Transport {
constructor(options) {
super(options);
const client = new _cloudwatchClient2.default(options.logGroupName, options.logStreamName, options);
this._relay = new _relay2.default(client, options);
this._relay.on('error', err => this.emit('error', err));
this._relay.start();
class CloudWatchTransport extends Transport {
constructor (options) {
super(options)
const client = new CloudWatchClient(
options.logGroupName,
options.logStreamName,
options
)
this._relay = new Relay(client, options)
this._relay.on('error', err => this.emit('error', err))
this._relay.start()
}
log(level, msg, meta, callback) {
this._relay.submit(new _logItem2.default(+new Date(), level, msg, meta, callback));
log (info, callback) {
const level = info.level
const msg = info.message
const meta = Object.assign({}, info)
delete meta.level
delete meta.message
this._relay.submit(new LogItem(+new Date(), level, msg, meta, callback))
}
}
exports.default = CloudWatchTransport;
module.exports = CloudWatchTransport

@@ -1,35 +0,31 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
class LogItem {
constructor(date, level, message, meta, callback) {
this._date = date;
this._level = level;
this._message = message;
this._meta = meta;
this._callback = callback;
constructor (date, level, message, meta, callback) {
this._date = date
this._level = level
this._message = message
this._meta = meta
this._callback = callback
}
get date() {
return this._date;
get date () {
return this._date
}
get level() {
return this._level;
get level () {
return this._level
}
get message() {
return this._message;
get message () {
return this._message
}
get meta() {
return this._meta;
get meta () {
return this._meta
}
get callback() {
return this._callback;
get callback () {
return this._callback
}
}
exports.default = LogItem;
module.exports = LogItem

@@ -1,39 +0,30 @@

'use strict';
const _debug = require('debug')
Object.defineProperty(exports, "__esModule", {
value: true
});
const debug = _debug('winston-aws-cloudwatch:Queue')
var _debug2 = require('debug');
var _debug3 = _interopRequireDefault(_debug2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const debug = (0, _debug3.default)('winston-aws-cloudwatch:Queue');
class Queue {
constructor() {
this._contents = [];
constructor () {
this._contents = []
}
get size() {
return this._contents.length;
get size () {
return this._contents.length
}
push(item) {
debug('push', { item });
this._contents.push(item);
push (item) {
debug('push', { item })
this._contents.push(item)
}
head(num) {
debug('head', { num });
return this._contents.slice(0, num);
head (num) {
debug('head', { num })
return this._contents.slice(0, num)
}
remove(num) {
debug('remove', { num });
this._contents.splice(0, num);
remove (num) {
debug('remove', { num })
this._contents.splice(0, num)
}
}
exports.default = Queue;
module.exports = Queue

@@ -1,100 +0,79 @@

'use strict';
const _debug = require('debug')
const Bottleneck = require('bottleneck')
const Queue = require('./queue')
const { EventEmitter } = require('events')
Object.defineProperty(exports, "__esModule", {
value: true
});
const debug = _debug('winston-aws-cloudwatch:Relay')
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
var _debug2 = require('debug');
var _debug3 = _interopRequireDefault(_debug2);
var _bottleneck = require('bottleneck');
var _bottleneck2 = _interopRequireDefault(_bottleneck);
var _queue = require('./queue');
var _queue2 = _interopRequireDefault(_queue);
var _events = require('events');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const debug = (0, _debug3.default)('winston-aws-cloudwatch:Relay');
const DEFAULT_OPTIONS = {
submissionInterval: 2000,
batchSize: 20
};
}
class Relay extends _events.EventEmitter {
constructor(client, options) {
super();
debug('constructor', { client, options });
this._client = client;
this._options = (0, _assign2.default)({}, DEFAULT_OPTIONS, options);
this._limiter = null;
this._queue = null;
class Relay extends EventEmitter {
constructor (client, options) {
super()
debug('constructor', { client, options })
this._client = client
this._options = Object.assign({}, DEFAULT_OPTIONS, options)
this._limiter = null
this._queue = null
}
start() {
debug('start');
start () {
debug('start')
if (this._queue) {
throw new Error('Already started');
throw new Error('Already started')
}
this._limiter = new _bottleneck2.default(1, this._options.submissionInterval, 1);
this._queue = new _queue2.default();
this._limiter = new Bottleneck(1, this._options.submissionInterval, 1)
this._queue = new Queue()
// Initial call to postpone first submission
this._limiter.schedule(() => _promise2.default.resolve());
this._limiter.schedule(() => Promise.resolve())
}
submit(item) {
this._queue.push(item);
this._scheduleSubmission();
submit (item) {
this._queue.push(item)
this._scheduleSubmission()
}
_scheduleSubmission() {
debug('scheduleSubmission');
this._limiter.schedule(() => this._submit());
_scheduleSubmission () {
debug('scheduleSubmission')
this._limiter.schedule(() => this._submit())
}
_submit() {
_submit () {
if (this._queue.size === 0) {
debug('submit: queue empty');
return _promise2.default.resolve();
debug('submit: queue empty')
return Promise.resolve()
}
const batch = this._queue.head(this._options.batchSize);
debug(`submit: submitting ${batch.length} item(s)`);
return this._client.submit(batch).then(() => this._onSubmitted(batch), err => this._onError(err, batch)).then(() => this._scheduleSubmission());
const batch = this._queue.head(this._options.batchSize)
debug(`submit: submitting ${batch.length} item(s)`)
return this._client
.submit(batch)
.then(() => this._onSubmitted(batch), err => this._onError(err, batch))
.then(() => this._scheduleSubmission())
}
_onSubmitted(batch) {
debug('onSubmitted', { batch });
this._queue.remove(batch.length);
_onSubmitted (batch) {
debug('onSubmitted', { batch })
this._queue.remove(batch.length)
for (let i = 0; i < batch.length; ++i) {
const item = batch[i];
item.callback(null, true);
const item = batch[i]
item.callback(null, true)
}
}
_onError(err, batch) {
debug('onError', { error: err });
_onError (err, batch) {
debug('onError', { error: err })
if (err.code === 'DataAlreadyAcceptedException') {
// Assume the request got replayed and remove the batch
this._queue.remove(batch.length);
this._queue.remove(batch.length)
} else if (err.code === 'InvalidSequenceTokenException') {
// Keep retrying
} else {
this.emit('error', err);
this.emit('error', err)
}
}
}
exports.default = Relay;
module.exports = Relay
{
"name": "winston-aws-cloudwatch",
"version": "2.0.0",
"version": "3.0.0",
"description": "A Winston transport for Amazon CloudWatch.",

@@ -18,50 +18,45 @@ "keywords": [

"engines": {
"node": ">=6",
"yarn": "*"
"node": ">=8",
"yarn": ">=1.6.0"
},
"peerDependencies": {
"winston": "^2.3.1"
"winston": "^3.0.0"
},
"dependencies": {
"aws-sdk": "^2.58.0",
"babel-runtime": "^6.23.0",
"bottleneck": "^1.15.1",
"aws-sdk": "^2.293.0",
"bottleneck": "^1.16.0",
"debug": "^3.1.0",
"lodash.isempty": "^4.2.1"
"lodash.isempty": "^4.2.1",
"winston-transport": "^4.2.0"
},
"devDependencies": {
"babel-cli": "^6.24.1",
"babel-core": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.5.1",
"chai": "^4.0.2",
"chai-as-promised": "^7.0.0",
"coveralls": "^3.0.0",
"delay": "^2.0.0",
"mocha": "^4.0.1",
"mocha-junit-reporter": "^1.13.0",
"nyc": "^11.0.3",
"coveralls": "^3.0.2",
"delay": "^3.0.0",
"husky": "^0.14.3",
"lint-staged": "^7.2.2",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.18.0",
"nyc": "^12.0.2",
"prettier-standard": "^8.0.1",
"rimraf": "^2.6.1",
"sinon": "^4.1.2",
"sinon-chai": "^2.10.0",
"standard": "^10.0.2"
"sinon": "^6.1.5",
"sinon-chai": "^3.2.0",
"standard": "^10.0.0"
},
"main": "index.js",
"main": "lib/index.js",
"files": [
"lib/",
"index.js"
"lib/"
],
"scripts": {
"prepublishOnly": "yarn run build",
"clean": "rimraf lib",
"build": "yarn run clean && babel src --out-dir lib",
"test": "yarn run test:lint && yarn run test:cover",
"test:lint": "standard",
"test:unit": "mocha --require babel-core/register test/lib/setup.js test/**/*.spec.js",
"test:lint": "standard '{lib,test}/**/*.js'",
"test:unit": "mocha 'test/lib/setup.js' 'test/**/*.spec.js'",
"test:cover": "nyc yarn run test:unit",
"test:ci": "yarn run test:ci:cover && yarn run test:ci:report",
"test:ci:unit": "mocha --reporter mocha-junit-reporter --require babel-core/register test/lib/setup.js test/**/*.spec.js",
"test:ci:cover": "nyc yarn run test:ci:unit",
"test:ci": "yarn run test:lint && yarn run test:ci:cover && yarn run test:ci:report",
"test:ci:cover": "nyc mocha --reporter mocha-junit-reporter 'test/lib/setup.js' 'test/**/*.spec.js'",
"test:ci:report": "nyc report --reporter text-lcov | coveralls",
"dev": "babel src --out-dir lib --watch"
"format": "prettier-standard '{lib,test}/**/*.js'",
"precommit": "lint-staged"
},

@@ -82,3 +77,9 @@ "repository": "timdp/winston-aws-cloudwatch",

]
},
"lint-staged": {
"*.js": [
"prettier-standard",
"git add"
]
}
}
# winston-aws-cloudwatch
[![npm](https://img.shields.io/npm/v/winston-aws-cloudwatch.svg)](https://www.npmjs.com/package/winston-aws-cloudwatch) [![Dependencies](https://img.shields.io/david/timdp/winston-aws-cloudwatch.svg)](https://david-dm.org/timdp/winston-aws-cloudwatch) [![Build Status](https://img.shields.io/circleci/project/github/timdp/winston-aws-cloudwatch/master.svg?label=build)](https://circleci.com/gh/timdp/winston-aws-cloudwatch) [![Coverage Status](https://img.shields.io/coveralls/timdp/winston-aws-cloudwatch/master.svg)](https://coveralls.io/r/timdp/winston-aws-cloudwatch) [![JavaScript Standard Style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
[![npm](https://img.shields.io/npm/v/winston-aws-cloudwatch.svg)](https://www.npmjs.com/package/winston-aws-cloudwatch) [![Dependencies](https://img.shields.io/david/timdp/winston-aws-cloudwatch.svg)](https://david-dm.org/timdp/winston-aws-cloudwatch) [![Build Status](https://img.shields.io/circleci/project/github/timdp/winston-aws-cloudwatch/master.svg?label=build)](https://circleci.com/gh/timdp/winston-aws-cloudwatch) [![Coverage Status](https://img.shields.io/coveralls/timdp/winston-aws-cloudwatch/master.svg)](https://coveralls.io/r/timdp/winston-aws-cloudwatch) [![JavaScript Standard Style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](https://standardjs.com/)

@@ -11,20 +11,24 @@ A [Winston](https://www.npmjs.com/package/winston) transport for

```js
var CloudWatchTransport = require('winston-aws-cloudwatch')
const winston = require('winston')
const CloudWatchTransport = require('winston-aws-cloudwatch')
winston.add(CloudWatchTransport, {
logGroupName: '...', // REQUIRED
logStreamName: '...', // REQUIRED
createLogGroup: true,
createLogStream: true,
submissionInterval: 2000,
submissionRetryCount: 1,
batchSize: 20,
awsConfig: {
accessKeyId: '...',
secretAccessKey: '...',
region: '...'
},
formatLog: function (item) {
return item.level + ': ' + item.message + ' ' + JSON.stringify(item.meta)
}
const logger = winston.createLogger({
transports: [
new CloudWatchTransport({
logGroupName: '...', // REQUIRED
logStreamName: '...', // REQUIRED
createLogGroup: true,
createLogStream: true,
submissionInterval: 2000,
submissionRetryCount: 1,
batchSize: 20,
awsConfig: {
accessKeyId: '...',
secretAccessKey: '...',
region: '...'
},
formatLog: item =>
`${item.level}: ${item.message} ${JSON.stringify(item.meta)}`
})
]
})

@@ -37,3 +41,3 @@ ```

emit an `error` event. It is recommended that you
[subscribe to this event](https://www.npmjs.com/package/winston#events-and-callbacks-in-winston)
[subscribe to this event](https://www.npmjs.com/package/winston#awaiting-logs-to-be-written-in-winston)
to avoid crashes.

@@ -40,0 +44,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc