@ikonintegration/ikapi 3.0.18 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/package.json +2 -1
- package/src/API/IKResponse.js +2 -2
- package/src/BaseEvent/IKProcess.js +4 -0
- package/src/BaseEvent/IKTransaction.js +12 -9
- package/src/Database/DDB/IKDB.js +7 -1
- package/src/Database/DDB/IKDBQueryBatchWrite.js +5 -0
- package/src/Database/DDB/IKDBQueryDelete.js +5 -0
- package/src/Database/DDB/IKDBQueryGet.js +6 -0
- package/src/Database/DDB/IKDBQueryPut.js +5 -0
- package/src/Database/DDB/IKDBQueryScan.js +5 -0
- package/src/Database/DDB/IKDBQueryUpdate.js +5 -0
- package/src/Database/PSQL/IKDB.js +2 -0
- package/src/Database/Prototype/IKDB.js +3 -0
- package/src/IKEventProcessor.js +2 -2
- package/src/IKGlobals.js +3 -0
- package/src/Logger/IKLogger.js +4 -4
- package/src/Tracker/IKExecutionTracker.js +57 -0
package/README.md
CHANGED
|
@@ -50,7 +50,13 @@ export const handler = async (event, context) => {
|
|
|
50
50
|
sensitiveFilteringKeywords: [], //replaced default blacklist set
|
|
51
51
|
},
|
|
52
52
|
//Queue
|
|
53
|
-
publisher: { region: 'SNS-REGION' }
|
|
53
|
+
publisher: { region: 'SNS-REGION' },
|
|
54
|
+
//Resources tracker
|
|
55
|
+
resourcesTracker: { //by default, it will auto track (lambda, ecs, ddb)
|
|
56
|
+
busName: 'busName',
|
|
57
|
+
region: 'region',
|
|
58
|
+
appName: 'appName',
|
|
59
|
+
}
|
|
54
60
|
};)).handleEvent(event, context));
|
|
55
61
|
}
|
|
56
62
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ikonintegration/ikapi",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "main.js",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"@aws-sdk/credential-provider-node": "^3.72.0",
|
|
18
18
|
"@aws-sdk/node-http-handler": "^3.58.0",
|
|
19
19
|
"@aws-sdk/util-dynamodb": "^3.72.0",
|
|
20
|
+
"@ikonintegration/mod-resources-tracker-client": "0.0.1",
|
|
20
21
|
"abind": "^1.0.5",
|
|
21
22
|
"bluebird": "^3.7.2",
|
|
22
23
|
"email-templates": "^8.0.8",
|
package/src/API/IKResponse.js
CHANGED
|
@@ -22,7 +22,7 @@ export default class IKResponse {
|
|
|
22
22
|
getBody() { return this._body; }
|
|
23
23
|
appendIntoBody(key, value) { this._body[key] = value; }
|
|
24
24
|
appendHeader(key, value) { this._headers[key] = value; }
|
|
25
|
-
async build(context, transaction,
|
|
25
|
+
async build(context, transaction, doNotSucceed) {
|
|
26
26
|
//Stream support
|
|
27
27
|
if (this._streamingOut) return;
|
|
28
28
|
if (this._isStream) return this._pipe(context);
|
|
@@ -42,7 +42,7 @@ export default class IKResponse {
|
|
|
42
42
|
//Check for transaction response proxy
|
|
43
43
|
if (transaction.responseProxy) await transaction.responseProxy(b);
|
|
44
44
|
//Batch does not succeed directly just on upper transaction (which will should be a batch)
|
|
45
|
-
if (!
|
|
45
|
+
if (!doNotSucceed) context.succeed(b);
|
|
46
46
|
}
|
|
47
47
|
_pipe(context) {
|
|
48
48
|
//Check if not streaming
|
|
@@ -10,6 +10,7 @@ import IKCacheRedis from '../Cache/Redis/IKRedis';
|
|
|
10
10
|
import IKLogger from "../Logger/IKLogger";
|
|
11
11
|
import IKValidation from '../Validation/IKValidation';
|
|
12
12
|
import IKPublisher from '../Publisher/IKPublisher';
|
|
13
|
+
import IKExecutionTracker from '../Tracker/IKExecutionTracker';
|
|
13
14
|
//
|
|
14
15
|
export default class IKProcess {
|
|
15
16
|
constructor(config, interval) {
|
|
@@ -20,6 +21,7 @@ export default class IKProcess {
|
|
|
20
21
|
this.validator = new IKValidation(config.validation);
|
|
21
22
|
this.db = this._getDBDriver();
|
|
22
23
|
this.cache = this._getCacheDriver();
|
|
24
|
+
if (config.resourcesTracker) this.tracker = new IKExecutionTracker(config.resourcesTracker, context, this.db);
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
//Main interface
|
|
@@ -49,6 +51,8 @@ export default class IKProcess {
|
|
|
49
51
|
this.logger.exception(e);
|
|
50
52
|
//Rollback DB
|
|
51
53
|
if (this.db) await this.db.rollback();
|
|
54
|
+
//Tracker
|
|
55
|
+
if (this.tracker) await this.tracker.stopTracking();
|
|
52
56
|
} return executionFailed;
|
|
53
57
|
}
|
|
54
58
|
/* DB drivers support */
|
|
@@ -10,6 +10,7 @@ import IKCacheRedis from '../Cache/Redis/IKRedis';
|
|
|
10
10
|
import IKLogger from "../Logger/IKLogger";
|
|
11
11
|
import IKValidation from '../Validation/IKValidation';
|
|
12
12
|
import IKPublisher from '../Publisher/IKPublisher';
|
|
13
|
+
import IKExecutionTracker from '../Tracker/IKExecutionTracker';
|
|
13
14
|
//Request
|
|
14
15
|
import IKRequest from '../API/IKRequest';
|
|
15
16
|
import IKResponse, { IKBadRequestResponseWithRollback } from '../API/IKResponse';
|
|
@@ -20,12 +21,11 @@ export default class IKTransaction {
|
|
|
20
21
|
this._event = event;
|
|
21
22
|
this._context = context;
|
|
22
23
|
this._config = config;
|
|
23
|
-
//
|
|
24
|
-
this.
|
|
25
|
-
this._resp = null;
|
|
26
|
-
//Step function support
|
|
24
|
+
//response behaviour flags
|
|
25
|
+
this._syncReturn = _isBatch;
|
|
27
26
|
this._retrowErrors = _retrowErrors; /* retrow internal errors */
|
|
28
|
-
|
|
27
|
+
this._resp = null;
|
|
28
|
+
//When set, this will be called with the response context right before calling the context suceed/fail - useful for IOing the resp for example.
|
|
29
29
|
this.responseProxy = null;
|
|
30
30
|
//
|
|
31
31
|
this.logger = new IKLogger(config.logger, Utils.logLevel(), (context.awsRequestId ? context.awsRequestId : (event.requestContext ? event.requestContext.requestId : 'unknown')));
|
|
@@ -33,6 +33,7 @@ export default class IKTransaction {
|
|
|
33
33
|
this.publisher = new IKPublisher(config.publisher);
|
|
34
34
|
this.validator = new IKValidation(config.validation);
|
|
35
35
|
this.db = this._getDBDriver();
|
|
36
|
+
if (config.resourcesTracker) this.tracker = new IKExecutionTracker(config.resourcesTracker, context, this.db);
|
|
36
37
|
this.cache = this._getCacheDriver();
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -43,7 +44,7 @@ export default class IKTransaction {
|
|
|
43
44
|
return await this._execute(executionFunc);
|
|
44
45
|
});
|
|
45
46
|
});
|
|
46
|
-
if (this.
|
|
47
|
+
if (this._syncReturn) return this._resp;
|
|
47
48
|
}
|
|
48
49
|
//Executions
|
|
49
50
|
async _execute(executionFunc) {
|
|
@@ -54,11 +55,11 @@ export default class IKTransaction {
|
|
|
54
55
|
this._resp = await executionFunc(this);
|
|
55
56
|
//Answer client
|
|
56
57
|
if (this._resp && this._resp instanceof IKResponse) {
|
|
57
|
-
await this._resp.build(this._context, this, this.
|
|
58
|
+
await this._resp.build(this._context, this, this._syncReturn);
|
|
58
59
|
executionFailed = !!(this._resp.getBody() && this._resp.getBody().rollback);
|
|
59
60
|
} else {
|
|
60
61
|
this._resp = this._getErrorResponse(IKGlobals.ErrorResponseInvalidServerResponse, IKGlobals.ErrorCode_APIError)
|
|
61
|
-
await this._resp.build(this._context, this, this.
|
|
62
|
+
await this._resp.build(this._context, this, this._syncReturn);
|
|
62
63
|
this.logger.error("Invalid response object from main request code.");
|
|
63
64
|
}
|
|
64
65
|
} catch (e) { /*EXECUTION FAIL*/
|
|
@@ -69,7 +70,7 @@ export default class IKTransaction {
|
|
|
69
70
|
//envelope exception?
|
|
70
71
|
if (executionFailed) {
|
|
71
72
|
this._resp = this._getErrorResponse(IKGlobals.ErrorResponseUnhandledError, IKGlobals.ErrorCode_APIError);
|
|
72
|
-
await this._resp.build(this._context, this, this.
|
|
73
|
+
await this._resp.build(this._context, this, this._syncReturn);
|
|
73
74
|
}
|
|
74
75
|
} return executionFailed;
|
|
75
76
|
}
|
|
@@ -101,6 +102,8 @@ export default class IKTransaction {
|
|
|
101
102
|
try {
|
|
102
103
|
await safeExecution();
|
|
103
104
|
await this.logger.flushLogs();
|
|
105
|
+
//Tracker
|
|
106
|
+
if (this.tracker) await this.tracker.stopTracking();
|
|
104
107
|
} catch (e) {
|
|
105
108
|
this.logger.error('Exception when flushing logs.');
|
|
106
109
|
this.logger.exception(e);
|
package/src/Database/DDB/IKDB.js
CHANGED
|
@@ -16,6 +16,7 @@ export default class IKDB_DDB extends IKDB {
|
|
|
16
16
|
super(config, transaction);
|
|
17
17
|
this.tableName = config.tableName;
|
|
18
18
|
this.region = config.region;
|
|
19
|
+
this.stats = { readUnits: 0, writeUnits: 0 };
|
|
19
20
|
//
|
|
20
21
|
// const localConsole = (transaction ? transaction.logger : console);
|
|
21
22
|
// if (config && this.tableName) { localConsole.debug(`Using table: ${this.tableName} on region: ${this.region}`); }
|
|
@@ -37,8 +38,9 @@ export default class IKDB_DDB extends IKDB {
|
|
|
37
38
|
// localConsole.debug("Starting remote database connection");
|
|
38
39
|
//initialize connection
|
|
39
40
|
this.connection = new DynamoDB({
|
|
40
|
-
region: this.region,
|
|
41
|
+
region: this.region, maxAttempts: IKGlobals.DDBMaxAttempts,
|
|
41
42
|
requestHandler: new NodeHttpHandler({
|
|
43
|
+
connectionTimeout: IKGlobals.DDBHttpTimeout, socketTimeout: IKGlobals.DDBHttpTimeout,
|
|
42
44
|
httpsAgent: new Agent({ keepAlive: false, maxSockets: 50, rejectUnauthorized: true }),
|
|
43
45
|
})
|
|
44
46
|
});
|
|
@@ -47,4 +49,8 @@ export default class IKDB_DDB extends IKDB {
|
|
|
47
49
|
DDB_CONN_HASH = sha1(this.region);
|
|
48
50
|
}
|
|
49
51
|
}
|
|
52
|
+
getTrackerStats() {
|
|
53
|
+
if (!(this.stats.readUnits > 0 || this.state.writeUnits > 0)) return null;
|
|
54
|
+
return { tableName: this.tableName, ...this.stats };
|
|
55
|
+
}
|
|
50
56
|
}
|
|
@@ -23,6 +23,7 @@ export default class IKDBQueryBatchWrite extends IKDBBaseQuery {
|
|
|
23
23
|
localConsole.log('Batch writting items: ', query);
|
|
24
24
|
const resp = await dbManager.connection.batchWriteItem(query);
|
|
25
25
|
// localConsole.debug('Raw result: ', resp);
|
|
26
|
+
this._incrementTrackerStats(resp, dbManager);
|
|
26
27
|
return resp;
|
|
27
28
|
}
|
|
28
29
|
|
|
@@ -56,4 +57,8 @@ export default class IKDBQueryBatchWrite extends IKDBBaseQuery {
|
|
|
56
57
|
expression.RequestItems[dbTableName].push({DeleteRequest: item});
|
|
57
58
|
} return expression;
|
|
58
59
|
}
|
|
60
|
+
/* tracker support */
|
|
61
|
+
_incrementTrackerStats(resp, dbManager) {
|
|
62
|
+
if (resp && resp.ConsumedCapacity && resp.ConsumedCapacity.CapacityUnits) dbManager.stats.writeUnits += parseFloat(resp.ConsumedCapacity.CapacityUnits);
|
|
63
|
+
}
|
|
59
64
|
}
|
|
@@ -19,6 +19,7 @@ export default class IKDBQueryUpdate extends IKDBBaseQuery {
|
|
|
19
19
|
localConsole.log("Deleting item: ", query);
|
|
20
20
|
let resp = await dbManager.connection.deleteItem(query);
|
|
21
21
|
// localConsole.debug('Raw result: ', resp);
|
|
22
|
+
this._incrementTrackerStats(resp, dbManager);
|
|
22
23
|
return resp;
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -26,4 +27,8 @@ export default class IKDBQueryUpdate extends IKDBBaseQuery {
|
|
|
26
27
|
return { ...super._rawQuery(dbTableName, isTransaction),
|
|
27
28
|
...(isTransaction ? {} : {ReturnValues: "ALL_OLD" /*request all deleted values*/ })};
|
|
28
29
|
}
|
|
30
|
+
/* tracker support */
|
|
31
|
+
_incrementTrackerStats(resp, dbManager) {
|
|
32
|
+
if (resp && resp.ConsumedCapacity && resp.ConsumedCapacity.CapacityUnits) dbManager.stats.writeUnits += parseFloat(resp.ConsumedCapacity.CapacityUnits);
|
|
33
|
+
}
|
|
29
34
|
}
|
|
@@ -37,6 +37,12 @@ export default class IKDBQueryGet extends IKDBBaseQuery {
|
|
|
37
37
|
localConsole.log('Querying: ', query, appendingItems ? appendingItems.length : null);
|
|
38
38
|
const resp = await dbManager.connection.query(query);
|
|
39
39
|
// localConsole.debug('Raw result: ', resp);
|
|
40
|
+
this._incrementTrackerStats(resp, dbManager);
|
|
40
41
|
return resp;
|
|
41
42
|
}
|
|
43
|
+
|
|
44
|
+
/* tracker support */
|
|
45
|
+
_incrementTrackerStats(resp, dbManager) {
|
|
46
|
+
if (resp && resp.ConsumedCapacity && resp.ConsumedCapacity.CapacityUnits) dbManager.stats.readUnits += parseFloat(resp.ConsumedCapacity.CapacityUnits);
|
|
47
|
+
}
|
|
42
48
|
}
|
|
@@ -61,6 +61,7 @@ export default class IKDBQueryPut extends IKDBBaseQuery {
|
|
|
61
61
|
localConsole.log('Putting item: ', query);
|
|
62
62
|
const resp = await dbManager.connection.putItem(query);
|
|
63
63
|
// localConsole.debug('Raw result: ', resp);
|
|
64
|
+
this._incrementTrackerStats(resp, dbManager);
|
|
64
65
|
return resp;
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -79,4 +80,8 @@ export default class IKDBQueryPut extends IKDBBaseQuery {
|
|
|
79
80
|
}
|
|
80
81
|
} return expression;
|
|
81
82
|
}
|
|
83
|
+
/* tracker support */
|
|
84
|
+
_incrementTrackerStats(resp, dbManager) {
|
|
85
|
+
if (resp && resp.ConsumedCapacity && resp.ConsumedCapacity.CapacityUnits) dbManager.stats.writeUnits += parseFloat(resp.ConsumedCapacity.CapacityUnits);
|
|
86
|
+
}
|
|
82
87
|
}
|
|
@@ -35,6 +35,11 @@ export default class IKDBQueryScan extends IKDBBaseQuery {
|
|
|
35
35
|
localConsole.log('Scanning: ', query, appendingItems ? appendingItems.length : 0);
|
|
36
36
|
const resp = await dbManager.connection.scan(query);
|
|
37
37
|
// localConsole.debug('Raw result: ', resp);
|
|
38
|
+
this._incrementTrackerStats(resp, dbManager);
|
|
38
39
|
return resp;
|
|
39
40
|
}
|
|
41
|
+
/* tracker support */
|
|
42
|
+
_incrementTrackerStats(resp, dbManager) {
|
|
43
|
+
if (resp && resp.ConsumedCapacity && resp.ConsumedCapacity.CapacityUnits) dbManager.stats.readUnits += parseFloat(resp.ConsumedCapacity.CapacityUnits);
|
|
44
|
+
}
|
|
40
45
|
}
|
|
@@ -96,6 +96,7 @@ export default class IKDBQueryUpdate extends IKDBBaseQuery {
|
|
|
96
96
|
localConsole.log("Updating item: ", query);
|
|
97
97
|
let resp = await dbManager.connection.updateItem(query);
|
|
98
98
|
// localConsole.debug('Raw result: ', resp);
|
|
99
|
+
this._incrementTrackerStats(resp, dbManager);
|
|
99
100
|
return resp;
|
|
100
101
|
}
|
|
101
102
|
|
|
@@ -211,4 +212,8 @@ export default class IKDBQueryUpdate extends IKDBBaseQuery {
|
|
|
211
212
|
}
|
|
212
213
|
} return expression;
|
|
213
214
|
}
|
|
215
|
+
/* tracker support */
|
|
216
|
+
_incrementTrackerStats(resp, dbManager) {
|
|
217
|
+
if (resp && resp.ConsumedCapacity && resp.ConsumedCapacity.CapacityUnits) dbManager.stats.writeUnits += parseFloat(resp.ConsumedCapacity.CapacityUnits);
|
|
218
|
+
}
|
|
214
219
|
}
|
|
@@ -17,6 +17,8 @@ export default class IKDB_PSQL extends IKDB {
|
|
|
17
17
|
async commit() { return await (await this._getConnection()).query('COMMIT'); }
|
|
18
18
|
async rollback() { return await (await this._getConnection()).query('ROLLBACK'); }
|
|
19
19
|
async runQuery(qry) { return await qry.run(await this._getConnection()); }
|
|
20
|
+
//tracker support
|
|
21
|
+
getTrackerStats() { return null; }
|
|
20
22
|
//Public
|
|
21
23
|
async sanitize(val) { return val; }
|
|
22
24
|
|
package/src/IKEventProcessor.js
CHANGED
|
@@ -7,7 +7,7 @@ export default class IKEventProcessor {
|
|
|
7
7
|
this.event = event;
|
|
8
8
|
this.context = context;
|
|
9
9
|
this.apiConfig = config;
|
|
10
|
-
this.
|
|
10
|
+
this._syncReturn = isBatch;
|
|
11
11
|
}
|
|
12
12
|
async processEvent(execution, doNotDecodeMessage) {
|
|
13
13
|
const resp = await this._processRawEvent(execution, doNotDecodeMessage);
|
|
@@ -21,7 +21,7 @@ export default class IKEventProcessor {
|
|
|
21
21
|
//Map records with decoded message when required
|
|
22
22
|
const decodedRecords = this.event.Records.map((eventRecord) => (doNotDecodeMessage ? eventRecord.body : JSON.parse(eventRecord.body)));
|
|
23
23
|
//If is batch, return execution
|
|
24
|
-
if (this.
|
|
24
|
+
if (this._syncReturn) return await execution(transaction, decodedRecords);
|
|
25
25
|
//for each available event
|
|
26
26
|
for (let eventRecord of decodedRecords) {
|
|
27
27
|
//Call execution
|
package/src/IKGlobals.js
CHANGED
|
@@ -6,6 +6,9 @@ IKGlobals.DBDrivers = {
|
|
|
6
6
|
IKGlobals.CacheDrivers = {
|
|
7
7
|
REDIS: 'REDIS'
|
|
8
8
|
};
|
|
9
|
+
//DDB Client
|
|
10
|
+
IKGlobals.DDBHttpTimeout = 15000;
|
|
11
|
+
IKGlobals.DDBMaxAttempts = 3;
|
|
9
12
|
//Error messages
|
|
10
13
|
IKGlobals.ErrorResponseValidationFail = 'Input validation failed: '; //400
|
|
11
14
|
IKGlobals.ErrorResponseInvalidServerResponse = 'No valid response, this is a system error.'; //400
|
package/src/Logger/IKLogger.js
CHANGED
|
@@ -9,7 +9,7 @@ const LOG_STRINGS = ['DEBUG', 'INFO', 'WARN', 'ERROR'];
|
|
|
9
9
|
const PURE_CONSOLE = (console.flushLogs ? console.origin : console);
|
|
10
10
|
const DEFAULT_LOG_FUNCTION = PURE_CONSOLE.log.bind(PURE_CONSOLE);
|
|
11
11
|
//
|
|
12
|
-
const blacklist = ['password','phonenumber'
|
|
12
|
+
const blacklist = ['password','phonenumber'/*,'code'*/,'resetCode','recaptchaToken','token','mfa','REFRESH_TOKEN','SECRET_HASH','SecretHash','AccessToken','UserCode','paymentMethodNonce'];
|
|
13
13
|
//
|
|
14
14
|
export default class IKLogger {
|
|
15
15
|
constructor(_config, _LOG_LEVEL, transactionID) {
|
|
@@ -81,7 +81,7 @@ export default class IKLogger {
|
|
|
81
81
|
if (Utils.isOffline()) {
|
|
82
82
|
return ` [${this._timestamp()} - ${LOG_STRINGS[level]}] [${caller}] ${msg.join(" ")}`;
|
|
83
83
|
} else if (Utils.isHybridlessContainer() && this._transactionID) {
|
|
84
|
-
return (isRaw ? '' : ` ${this._transactionID}`) + ` [${LOG_STRINGS[level]}] [${caller}] ${this._supressSensitiveInfo
|
|
84
|
+
return (isRaw ? '' : ` ${this._transactionID}`) + ` [${LOG_STRINGS[level]}] [${caller}] ${(msg.map(this._supressSensitiveInfo).join(" "))}`;
|
|
85
85
|
} else {
|
|
86
86
|
return ` [${LOG_STRINGS[level]}] [${caller}] ${msg.join(" ")}`;
|
|
87
87
|
}
|
|
@@ -127,10 +127,10 @@ export default class IKLogger {
|
|
|
127
127
|
Object.keys(value).forEach(function (elt, i, array) {
|
|
128
128
|
const match = blacklist.find((f) => elt.toLowerCase().includes(f.toLowerCase()));
|
|
129
129
|
if (match) value[elt] = '**SUPRESSED_SENSITIVE_DATA**';
|
|
130
|
-
else value[elt] =
|
|
130
|
+
else value[elt] = value[elt];
|
|
131
131
|
});
|
|
132
132
|
return value;
|
|
133
|
-
} else if (Array.isArray(value)) return value.map(v=>
|
|
133
|
+
} else if (Array.isArray(value)) return value.map(v=>this._supressSensitiveInfo(v));
|
|
134
134
|
return value;
|
|
135
135
|
}
|
|
136
136
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { RTClient } from '@ikonintegration/mod-resources-tracker-client';
|
|
2
|
+
//
|
|
3
|
+
import Utils from "../API/IKUtils";
|
|
4
|
+
//
|
|
5
|
+
const fs = reuiqre('fs');
|
|
6
|
+
//
|
|
7
|
+
export default class IKExecutionTracker {
|
|
8
|
+
constructor(config, context, db) {
|
|
9
|
+
this.context = context;
|
|
10
|
+
this.db = db;
|
|
11
|
+
this.startedOn = Date.now();
|
|
12
|
+
if (config) this.client = this._getClient(config);
|
|
13
|
+
this.claimers = {};
|
|
14
|
+
}
|
|
15
|
+
/* Public */
|
|
16
|
+
appendClaimer(value, key) { this.claimers[value] = key; }
|
|
17
|
+
appendEvent(event) { this.client.appendEvent(event); }
|
|
18
|
+
//
|
|
19
|
+
async stopTracking() {
|
|
20
|
+
try {
|
|
21
|
+
//Check for client and claimers
|
|
22
|
+
if (!this.client || Object.keys(this.claimers).length == 0) return; //disabled
|
|
23
|
+
//detect execution and log (ECS or lambda)
|
|
24
|
+
this._detectExecutionAndLog();
|
|
25
|
+
//detect DB and log (DDB only for now)
|
|
26
|
+
this._collectDDBStats();
|
|
27
|
+
//drain stats
|
|
28
|
+
await this.client.drain();
|
|
29
|
+
} catch (e) { console.error(`Error while tracking execution: ${e}`); }
|
|
30
|
+
}
|
|
31
|
+
/* private tracker */
|
|
32
|
+
_detectExecutionAndLog() {
|
|
33
|
+
//Is running on container?
|
|
34
|
+
if (Utils.isHybridlessContainer()) {
|
|
35
|
+
//ECS, get metadata info and log if applicable and succeeded on it
|
|
36
|
+
const context = this._getECSMetadataObject();
|
|
37
|
+
if (context && context.containerInstanceArn) {
|
|
38
|
+
const extraDetails = { startTime: this.startedOn, endTime: Date.now(), taskConfig: { cpu: process.env.CPU, memory: process.env.MEMORY } };
|
|
39
|
+
this.client.appendEvent(RTClient.newECSExecutionEvent(context.ecsTaskId, context.containerInstanceArn, extraDetails));
|
|
40
|
+
}
|
|
41
|
+
} else this.client.appendEvent(RTClient.newLambdaInvocationEvent(this.context.awsRequestId)); //lambda logging
|
|
42
|
+
}
|
|
43
|
+
_collectDDBStats() {
|
|
44
|
+
const stats = this.db ? this.db.getTrackerStats() : null;
|
|
45
|
+
if (stats) this.client.appendEvent(RTClient.newDynamoEvent(stats.tableName, stats.readUnits, stats,writeUnits));
|
|
46
|
+
}
|
|
47
|
+
/* Private */
|
|
48
|
+
_getClient(config) {
|
|
49
|
+
return new RTClient({ busName: config.busName, region: config.region, source: config.appName });
|
|
50
|
+
}
|
|
51
|
+
/* ECS helper */
|
|
52
|
+
_getECSMetadataObject() {
|
|
53
|
+
try { return JSON.parse(fs.readFileSync(process.env.ECS_CONTAINER_METADATA_FILE)); }
|
|
54
|
+
catch (e) { console.error('Unable to retrieve metadata object: ' + e); }
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|