-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial PR - Create transport #1
Conversation
35bb93f
to
9736f0d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RLRabinowitz This looks good enough to use, but I reviewed it like 'new code', feel free to apply comments however you like
index.js
Outdated
var util = require('util'), | ||
winston = require('winston'), | ||
AWS = require('aws-sdk'), | ||
dynamodbIntegration = require('./lib/dynamodb-integration'), | ||
isEmpty = require('lodash.isempty'), | ||
assign = require('lodash.assign'), | ||
isError = require('lodash.iserror'), | ||
stringify = require('./lib/utils').stringify, | ||
debug = require('./lib/utils').debug, | ||
defaultFlushTimeoutMs = 10000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
put a const
in each line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!/^uncaughtException: /.test(info.message)) { | ||
// do not wait, just return right away | ||
return callback(null, true); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this one is confusing - maybe reverse the condition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since I'm not too sure on this code here (Specifically what the callback(null, true) means
. It seems that the callback is called immediately with these params on logger.info
, but is called again with other params when the batch is sent), I'll probably skip this...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
callbacks usually follow the pattern of func(error, result)
and in this case cb(null, true)
means everything worked. This is the 'happy flow' and will happen for EVERY log call except when the message includes uncaughtException
.
It's confusing because the 'normal' case is inside the if and short circuits this function.
If the error message does include uncaughtException
then we clear everything and submit the logs and get ready for a 'crash' exit of the process.
index.js
Outdated
WinstonDynamoDB.prototype.add = function(log) { | ||
debug('add log to queue', log); | ||
|
||
var self = this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use arrow functions and get rid of this shameful piece of javascript history
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, read online and didn't know about the whole this
scope thing that is different between function
s and arrow functions.
TIL
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
); | ||
}; | ||
|
||
WinstonDynamoDB.prototype.kthxbye = function(callback) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kthxbye
is unique to that transport right?
Doesn't winston have something more 'built-in' ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep it's unique to the transport
lib/dynamodb-integration.js
Outdated
@@ -0,0 +1,83 @@ | |||
var LIMITS = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prefer const
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jest.config.js
Outdated
@@ -0,0 +1,9 @@ | |||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this needed if there aren't any tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. This isn't need yet. I can remove it and add it later when necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const payload = { | ||
RequestItems: { | ||
[tableName]: eventsToSend.map(event => | ||
({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The streamName
will be the partition key and the timestamp
sort key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this PR, yes. I'll change the timestamp
to be a sequenceNumber
in a next PR, because of this issue
var entryIndex = 0; | ||
var bytes = 0; | ||
while (entryIndex < Math.min(logEvents.length, LIMITS.MAX_BATCH_ITEM_NUM)) { | ||
var ev = logEvents[entryIndex]; | ||
// unit tests pass null elements | ||
var evSize = ev ? Buffer.byteLength(ev.message, 'utf8') + BASE_EVENT_SIZE_BYTES : 0; | ||
if(evSize > LIMITS.MAX_EVENT_MSG_SIZE_BYTES) { | ||
evSize = LIMITS.MAX_EVENT_MSG_SIZE_BYTES; | ||
ev.message = ev.message.substring(0, evSize); | ||
const msgTooBigErr = new Error('Message Truncated because it exceeds the DynamoDB size limit'); | ||
msgTooBigErr.logEvent = ev; | ||
cb(msgTooBigErr); | ||
} | ||
if (bytes + evSize > LIMITS.MAX_BATCH_SIZE_BYTES) break; | ||
bytes += evSize; | ||
entryIndex++; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would put all this in a different function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ev.message = ev.message.substring(0, evSize); | ||
const msgTooBigErr = new Error('Message Truncated because it exceeds the DynamoDB size limit'); | ||
msgTooBigErr.logEvent = ev; | ||
cb(msgTooBigErr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this calls the callback but continues the run ? doesn't seem right, maybe missing a return
?
Also maybe instead we can split the large message to several smaller messages ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought about it, but since this is the existent logic in CW transport, I've decided not to touch this.
Also, the size limit for the truncation is bigger on DynamoDB (400KB) than in CW (256KB), so I wouldn't worry about it for our use case
I would also add a Dynamo DB Table definition file |
Add this to the missing README issue |
This PR creates the transport. It's very similar to the implementation of https://github.com/lazywithclass/winston-cloudwatch, with some adjustments for DynamoDB:
Index.js:
logGroupName
andretentionInDays
, which is CW specific, and addtableName
insteadutil.js:
WINSTON_CLOUDWATCH_DEBUG
toWINSTON_DYNAMODB_DEBUG
dynamodb-integration.js:
id
is thestreamName
,timestamp
is the timestamp of log addition,message
is the log message