Skip to content

Commit 98a3c3c

Browse files
author
kkuzmin
authored
Report error status if invocation fails (#44)
* Report error status if invocation fails * Change package version
1 parent 24e6e28 commit 98a3c3c

File tree

3 files changed

+80
-28
lines changed

3 files changed

+80
-28
lines changed

al_aws_collector.js

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* Base class for AWS Lambda based collectors.
66
*
7-
* Last message ID: AWSC0010
7+
* Last message ID: AWSC0011
88
* @end
99
* -----------------------------------------------------------------------------
1010
*/
@@ -120,31 +120,46 @@ class AlAwsCollector {
120120
done(error) {
121121
let context = this._invokeContext;
122122
if (error) {
123-
// The lambda context tires to stringify errors, so we should check if they can be stringified before we pass them to the context
123+
// The lambda context tries to stringify errors,
124+
// so we should check if they can be stringified before we pass them to the context
125+
let errorString;
124126
try{
125-
const stringifiedError = JSON.stringify(error);
126-
return context.fail(error);
127+
errorString = JSON.stringify(error);
127128
}
128129
catch (stringifyError){
129130
// Can't stringify the whole error, so lets try and get some useful info from it
130-
let errorString;
131-
132-
if (error.toJSON){
133-
errorString = error.toJSON();
134-
} else if (error.message){
135-
errorString = error.message;
136-
} else {
137-
// when all else fails, stringify it the gross way with inspect
138-
errorString = util.inspect(error);
139-
}
140-
141-
return context.fail(errorString);
131+
errorString = error.toJSON ? error.toJSON() :
132+
error.message ? error.message :
133+
// when all else fails, stringify it the gross way with inspect
134+
util.inspect(error);
142135
}
136+
const status = this.prepareErrorStatus(errorString);
137+
this.sendStatus(status, (sendError) => {
138+
console.warn('AWSC0011 Collector status send failed', sendError);
139+
context.fail(errorString);
140+
});
143141
} else {
144142
return context.succeed();
145143
}
146144
}
147145

146+
prepareErrorStatus(errorString, streamName = 'error', collectionType) {
147+
let cType = collectionType ? collectionType : this._ingestType;
148+
return {
149+
stream_name: streamName,
150+
status_type: 'error',
151+
stream_type: 'collector',
152+
message_type: 'collector_status',
153+
host_uuid: this._collectorId,
154+
data: [
155+
{error: errorString}
156+
],
157+
agent_type: this._collectorType,
158+
collection_type: cType,
159+
timestamp: moment().unix()
160+
};
161+
}
162+
148163
getProperties() {
149164
return {
150165
awsAccountId : m_alAws.arnToAccId(this._arn),
@@ -353,6 +368,28 @@ class AlAwsCollector {
353368
});
354369
}
355370

371+
sendStatus(status, callback) {
372+
let collector = this;
373+
374+
if(!status){
375+
return callback(null);
376+
} else {
377+
zlib.deflate(JSON.stringify([status]), function(compressionErr, compressed) {
378+
if (compressionErr) {
379+
return callback(compressionErr);
380+
} else {
381+
collector._ingestc.sendAgentstatus(compressed)
382+
.then(resp => {
383+
return callback(null, resp);
384+
})
385+
.catch(exception => {
386+
return callback(exception);
387+
});
388+
}
389+
});
390+
}
391+
}
392+
356393
send(data, compress = true, callback) {
357394
var collector = this;
358395

@@ -416,7 +453,7 @@ class AlAwsCollector {
416453
collector._formatFun(event, context, asyncCallback);
417454
},
418455
function(formattedData, compress, asyncCallback) {
419-
if(arguments.length === 2 && typeof compress === "function"){
456+
if(arguments.length === 2 && typeof compress === 'function'){
420457
asyncCallback = compress;
421458
compress = true;
422459
}
@@ -427,7 +464,7 @@ class AlAwsCollector {
427464
}
428465

429466
processLog(messages, formatFun, hostmetaElems, callback) {
430-
if(arguments.length === 3 && typeof hostmetaElems === "function"){
467+
if(arguments.length === 3 && typeof hostmetaElems === 'function'){
431468
callback = hostmetaElems;
432469
hostmetaElems = this._defaultHostmetaElems();
433470
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@alertlogic/al-aws-collector-js",
3-
"version": "2.0.7",
3+
"version": "2.0.8",
44
"license": "MIT",
55
"description": "Alert Logic AWS Collector Common Library",
66
"repository": {
@@ -33,7 +33,7 @@
3333
"sinon": "^7.5.0"
3434
},
3535
"dependencies": {
36-
"@alertlogic/al-collector-js": "1.4.3",
36+
"@alertlogic/al-collector-js": "1.4.4",
3737
"cfn-response": "1.0.1",
3838
"async": "3.0.1",
3939
"moment": "2.24.0",

test/al_aws_collector_test.js

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@ describe('al_aws_collector tests', function() {
399399
var ingestCSecmsgsStub;
400400
var ingestCVpcFlowStub;
401401
var ingestCLogmsgsStub;
402+
var ingestCAgentstatusStub;
403+
402404
beforeEach(function() {
403405
ingestCSecmsgsStub = sinon.stub(m_alCollector.IngestC.prototype, 'sendSecmsgs').callsFake(
404406
function fakeFn(data, callback) {
@@ -420,12 +422,20 @@ describe('al_aws_collector tests', function() {
420422
resolve(null);
421423
});
422424
});
425+
426+
ingestCAgentstatusStub = sinon.stub(m_alCollector.IngestC.prototype, 'sendAgentstatus').callsFake(
427+
function fakeFn(data, callback) {
428+
return new Promise (function(resolve, reject) {
429+
resolve(null);
430+
});
431+
});
423432
});
424433

425434
afterEach(function() {
426435
ingestCSecmsgsStub.restore();
427436
ingestCVpcFlowStub.restore();
428437
ingestCLogmsgsStub.restore();
438+
ingestCAgentstatusStub.restore();
429439
});
430440

431441
it('dont send if data is falsey', function(done) {
@@ -625,13 +635,17 @@ describe('al_aws_collector tests', function() {
625635
assert.ok(doneResult);
626636
});
627637

628-
it('returns errors that can be stringified in their raw state', () => {
638+
it('returns errors that can be stringified in their raw state', (done) => {
629639
const stringifialbleError = {
630640
foo: "bar"
631641
};
632642
const testContext = {
633643
succeed: () => true,
634-
fail: (error) => error
644+
fail: (error) => {
645+
assert.equal(error, JSON.stringify(stringifialbleError));
646+
done();
647+
}
648+
635649
};
636650

637651
collector = new AlAwsCollector(
@@ -642,16 +656,19 @@ describe('al_aws_collector tests', function() {
642656
colMock.AIMS_TEST_CREDS
643657
);
644658

645-
const doneResult = collector.done(stringifialbleError);
646-
assert.ok(doneResult === stringifialbleError);
659+
collector.done(stringifialbleError);
647660
});
648661

649662
it('returns errors that cannot be JSON stringified as a string', () => {
650663
const circRefError = {};
651664
circRefError.foo = circRefError;
652665
const testContext = {
653666
succeed: () => true,
654-
fail: (error) => error
667+
fail: (error) => {
668+
assert.notEqual(error, circRefError);
669+
assert.ok(typeof error === 'string');
670+
assert.equal(error, '{ foo: [Circular] }');
671+
}
655672
};
656673

657674
collector = new AlAwsCollector(
@@ -662,9 +679,7 @@ describe('al_aws_collector tests', function() {
662679
colMock.AIMS_TEST_CREDS
663680
);
664681

665-
const doneResult = collector.done(circRefError);
666-
assert.ok(doneResult !== circRefError);
667-
assert.ok(typeof doneResult === 'string');
682+
collector.done(circRefError);
668683
});
669684
});
670685

0 commit comments

Comments
 (0)