@squiz/optimization-utils 1.0.0 → 1.1.1
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/CHANGELOG.md +13 -0
- package/dist/{package.d.ts → index.d.ts} +2 -1
- package/dist/{package.js → index.js} +3 -2
- package/dist/index.js.map +1 -0
- package/dist/logger/LoggerMessage.d.ts +4 -0
- package/dist/logger/LoggerMessage.js +6 -1
- package/dist/logger/LoggerMessage.js.map +1 -1
- package/dist/logger/LogsHandler.d.ts +11 -0
- package/dist/logger/LogsHandler.js +66 -0
- package/dist/logger/LogsHandler.js.map +1 -0
- package/dist/logger/LogsLambdaHandler.d.ts +13 -0
- package/dist/logger/LogsLambdaHandler.js +31 -0
- package/dist/logger/LogsLambdaHandler.js.map +1 -0
- package/package.json +3 -3
- package/src/{package.ts → index.ts} +13 -1
- package/src/logger/LoggerMessage.ts +7 -0
- package/src/logger/LogsHandler.ts +66 -0
- package/src/logger/LogsLambdaHandler.ts +43 -0
- package/src/logger/__tests__/LogsHandler.spec.ts +77 -0
- package/dist/package.js.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -9,6 +9,7 @@ export * from './logger/SquizRemoteLogger';
|
|
|
9
9
|
export * from './logger/RemoteLogger';
|
|
10
10
|
export * from './logger/LoggerMessage';
|
|
11
11
|
export * from './logger/Logger';
|
|
12
|
+
export * from './logger/LogsLambdaHandler';
|
|
12
13
|
export * from './httpClient/HttpRequestBuilder';
|
|
13
14
|
export * from './httpClient/HttpClient';
|
|
14
15
|
export * from './httpClient/FetchHttpClient';
|
|
@@ -17,7 +18,7 @@ export * from './event/DynamoDBEventMapper';
|
|
|
17
18
|
export * from './event/DomainEvent';
|
|
18
19
|
export * from './event/AggregateRoot';
|
|
19
20
|
export * from './date/DateManipulator';
|
|
21
|
+
export * from './event/EventHandler';
|
|
20
22
|
export * from './config/ConfigurationLoader';
|
|
21
23
|
export * from './cloudflare/ImplCloudflareKVHttpService';
|
|
22
24
|
export * from './cloudflare/CloudflareKVHttpService';
|
|
23
|
-
export * from './event/EventHandler';
|
|
@@ -25,6 +25,7 @@ __exportStar(require("./logger/SquizRemoteLogger"), exports);
|
|
|
25
25
|
__exportStar(require("./logger/RemoteLogger"), exports);
|
|
26
26
|
__exportStar(require("./logger/LoggerMessage"), exports);
|
|
27
27
|
__exportStar(require("./logger/Logger"), exports);
|
|
28
|
+
__exportStar(require("./logger/LogsLambdaHandler"), exports);
|
|
28
29
|
__exportStar(require("./httpClient/HttpRequestBuilder"), exports);
|
|
29
30
|
__exportStar(require("./httpClient/HttpClient"), exports);
|
|
30
31
|
__exportStar(require("./httpClient/FetchHttpClient"), exports);
|
|
@@ -33,8 +34,8 @@ __exportStar(require("./event/DynamoDBEventMapper"), exports);
|
|
|
33
34
|
__exportStar(require("./event/DomainEvent"), exports);
|
|
34
35
|
__exportStar(require("./event/AggregateRoot"), exports);
|
|
35
36
|
__exportStar(require("./date/DateManipulator"), exports);
|
|
37
|
+
__exportStar(require("./event/EventHandler"), exports);
|
|
36
38
|
__exportStar(require("./config/ConfigurationLoader"), exports);
|
|
37
39
|
__exportStar(require("./cloudflare/ImplCloudflareKVHttpService"), exports);
|
|
38
40
|
__exportStar(require("./cloudflare/CloudflareKVHttpService"), exports);
|
|
39
|
-
|
|
40
|
-
//# sourceMappingURL=package.js.map
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC;AAEvC,gEAA8C;AAE9C,yDAAuC;AACvC,wDAAsC;AAEtC,iDAA+B;AAE/B,wDAAsC;AACtC,mEAAiD;AAEjD,6DAA2C;AAC3C,wDAAsC;AACtC,yDAAuC;AACvC,kDAAgC;AAChC,6DAA2C;AAE3C,kEAAgD;AAChD,0DAAwC;AACxC,+DAA6C;AAE7C,8DAA4C;AAE5C,8DAA4C;AAC5C,sDAAoC;AACpC,wDAAsC;AAEtC,yDAAuC;AACvC,uDAAqC;AAErC,+DAA6C;AAE7C,2EAAyD;AACzD,uEAAqD"}
|
|
@@ -8,6 +8,9 @@ export declare const TENANT_ID_METADATA: (tenantId: string | ValueOf) => {
|
|
|
8
8
|
export declare const PROCESSABLE_LOG_METADATA: {
|
|
9
9
|
readonly processable: true;
|
|
10
10
|
};
|
|
11
|
+
export declare const REMOTE_LOG_METADATA: {
|
|
12
|
+
readonly remote: true;
|
|
13
|
+
};
|
|
11
14
|
export type LogMessage = (message: string | any) => [string | any, Record<string, unknown>];
|
|
12
15
|
export type CreateLog = {
|
|
13
16
|
attachMetadata: (metadata: Record<string, unknown>) => CreateLog;
|
|
@@ -17,6 +20,7 @@ export type CreateLog = {
|
|
|
17
20
|
attachExperimentId: (experimentId: string | ValueOf) => CreateLog;
|
|
18
21
|
attachCaller: <T extends abstract new (...args: any) => any>(caller: InstanceType<T> | string) => CreateLog;
|
|
19
22
|
isProcessable: () => CreateLog;
|
|
23
|
+
remote: () => CreateLog;
|
|
20
24
|
getMetadata: () => Record<string, unknown>;
|
|
21
25
|
create: <T extends abstract new (...args: any) => any>(caller?: InstanceType<T> | string) => LogMessage;
|
|
22
26
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PROCESSABLE_LOG_METADATA = exports.TENANT_ID_METADATA = void 0;
|
|
3
|
+
exports.REMOTE_LOG_METADATA = exports.PROCESSABLE_LOG_METADATA = exports.TENANT_ID_METADATA = void 0;
|
|
4
4
|
exports.createLogMessage = createLogMessage;
|
|
5
5
|
exports.createLog = createLog;
|
|
6
6
|
const crypto_1 = require("crypto");
|
|
@@ -22,6 +22,7 @@ const TENANT_ID_METADATA = (tenantId) => ({
|
|
|
22
22
|
});
|
|
23
23
|
exports.TENANT_ID_METADATA = TENANT_ID_METADATA;
|
|
24
24
|
exports.PROCESSABLE_LOG_METADATA = { processable: true };
|
|
25
|
+
exports.REMOTE_LOG_METADATA = { remote: true };
|
|
25
26
|
function createLog(opts) {
|
|
26
27
|
opts = {
|
|
27
28
|
metadata: {
|
|
@@ -62,6 +63,9 @@ function createLog(opts) {
|
|
|
62
63
|
const isProcessable = () => {
|
|
63
64
|
return attachMetadata(exports.PROCESSABLE_LOG_METADATA);
|
|
64
65
|
};
|
|
66
|
+
const remote = () => {
|
|
67
|
+
return attachMetadata(exports.REMOTE_LOG_METADATA);
|
|
68
|
+
};
|
|
65
69
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
66
70
|
const attachCaller = (caller) => {
|
|
67
71
|
return attachMetadata({
|
|
@@ -88,6 +92,7 @@ function createLog(opts) {
|
|
|
88
92
|
isProcessable,
|
|
89
93
|
attachCaller,
|
|
90
94
|
getMetadata: () => opts?.metadata ?? {},
|
|
95
|
+
remote,
|
|
91
96
|
create,
|
|
92
97
|
};
|
|
93
98
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoggerMessage.js","sourceRoot":"","sources":["../../src/logger/LoggerMessage.ts"],"names":[],"mappings":";;;AAeA,4CAWC;
|
|
1
|
+
{"version":3,"file":"LoggerMessage.js","sourceRoot":"","sources":["../../src/logger/LoggerMessage.ts"],"names":[],"mappings":";;;AAeA,4CAWC;AAqCD,8BA8FC;AA7JD,mCAAoC;AAMpC,8DAA8D;AAC9D,MAAM,eAAe,GAAG,CACtB,qBAA+C,EACvC,EAAE,CACV,OAAO,qBAAqB,KAAK,QAAQ;IACvC,CAAC,CAAC,qBAAqB;IACvB,CAAC,CAAC,qBAAqB,CAAC,WAAW,CAAC,IAAI,CAAC;AAE7C,8DAA8D;AAC9D,SAAgB,gBAAgB,CAC9B,GAAG,QAAyC;IAE5C,MAAM,OAAO,GAAG,IAAA,mBAAU,GAAE,CAAC;IAE7B,MAAM,iBAAiB,GAAG,CAAC,GAAG,QAAQ,EAAE,YAAY,OAAO,EAAE,CAAC;SAC3D,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SACxB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;IAEZ,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,iBAAiB,IAAI,OAAO,IAAI,EAAE,EAAE,CAAC;AAC9D,CAAC;AAEM,MAAM,kBAAkB,GAAG,CAChC,QAA0B,EAG1B,EAAE,CAAC,CAAC;IACJ,QAAQ,EAAE,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE;CACvE,CAAC,CAAC;AANU,QAAA,kBAAkB,sBAM5B;AAEU,QAAA,wBAAwB,GAAG,EAAE,WAAW,EAAE,IAAI,EAAW,CAAC;AAC1D,QAAA,mBAAmB,GAAG,EAAE,MAAM,EAAE,IAAI,EAAW,CAAC;AA0B7D,SAAgB,SAAS,CAAC,IAGzB;IACC,IAAI,GAAG;QACL,QAAQ,EAAE;YACR,OAAO,EAAE,IAAA,mBAAU,GAAE;YACrB,GAAG,IAAI,EAAE,QAAQ;SAClB;QACD,OAAO,EAAE,IAAI,EAAE,OAAO;KACvB,CAAC;IAEF,MAAM,cAAc,GAAG,CACrB,QAAoD,EACzC,EAAE;QACb,OAAO,SAAS,CAAC;YACf,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;YACjB,QAAQ,EAAE;gBACR,GAAG,IAAI,EAAE,QAAQ;gBACjB,GAAG,QAAQ;aACZ;SACF,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,QAA0B,EAAa,EAAE;QAC/D,OAAO,cAAc,CAAC,IAAA,0BAAkB,EAAC,QAAQ,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC;IAEF,MAAM,kBAAkB,GAAG,CAAC,YAA8B,EAAa,EAAE;QACvE,OAAO,cAAc,CAAC;YACpB,YAAY,EACV,OAAO,YAAY,KAAK,QAAQ;gBAC9B,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,YAAY,CAAC,OAAO,EAAE;SAC7B,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,CAAC,SAAiB,EAAa,EAAE;QACvD,OAAO,cAAc,CAAC;YACpB,SAAS;SACV,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,mBAAmB,GAAG,CAAC,EAAU,EAAa,EAAE;QACpD,OAAO,cAAc,CAAC;YACpB,aAAa,EAAE,EAAE;SAClB,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,GAAc,EAAE;QACpC,OAAO,cAAc,CAAC,gCAAwB,CAAC,CAAC;IAClD,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,GAAc,EAAE;QAC7B,OAAO,cAAc,CAAC,2BAAmB,CAAC,CAAC;IAC7C,CAAC,CAAC;IAEF,8DAA8D;IAC9D,MAAM,YAAY,GAAG,CACnB,MAAkB,EACP,EAAE;QACb,OAAO,cAAc,CAAC;YACpB,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC;SAChC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,8DAA8D;IAC9D,MAAM,MAAM,GAAG,CACb,MAAmB,EAEmD,EAAE;QACxE,MAAM,QAAQ,GAAG;YACf,GAAG,IAAI,EAAE,QAAQ;YACjB,GAAG,CAAC,MAAM,IAAI;gBACZ,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC;aAChC,CAAC;SACH,CAAC;QAEF,8DAA8D;QAC9D,OAAO,CAAC,OAAqB,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACxD,CAAC,CAAC;IAEF,OAAO;QACL,cAAc;QACd,cAAc;QACd,kBAAkB;QAClB,eAAe;QACf,mBAAmB;QACnB,aAAa;QACb,YAAY;QACZ,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,QAAQ,IAAI,EAAE;QACvC,MAAM;QACN,MAAM;KACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CloudWatchLogsEvent } from 'aws-lambda';
|
|
2
|
+
import { RemoteLogger } from './RemoteLogger';
|
|
3
|
+
import { Logger } from './Logger';
|
|
4
|
+
export declare class LogsHandler {
|
|
5
|
+
private readonly remoteLogger;
|
|
6
|
+
private readonly logger;
|
|
7
|
+
constructor(remoteLogger: RemoteLogger, logger: Logger);
|
|
8
|
+
handle(event: CloudWatchLogsEvent): Promise<void>;
|
|
9
|
+
private mapLogs;
|
|
10
|
+
private decodeLogs;
|
|
11
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.LogsHandler = void 0;
|
|
19
|
+
const zlib_1 = __importDefault(require("zlib"));
|
|
20
|
+
const inversify_1 = require("inversify");
|
|
21
|
+
const util_1 = require("util");
|
|
22
|
+
const RemoteLogger_1 = require("./RemoteLogger");
|
|
23
|
+
const Logger_1 = require("./Logger");
|
|
24
|
+
const LoggerMessage_1 = require("./LoggerMessage");
|
|
25
|
+
let LogsHandler = class LogsHandler {
|
|
26
|
+
remoteLogger;
|
|
27
|
+
logger;
|
|
28
|
+
constructor(remoteLogger, logger) {
|
|
29
|
+
this.remoteLogger = remoteLogger;
|
|
30
|
+
this.logger = logger;
|
|
31
|
+
}
|
|
32
|
+
async handle(event) {
|
|
33
|
+
const logMessage = (0, LoggerMessage_1.createLogMessage)(this);
|
|
34
|
+
this.logger.debug(logMessage(`started mapping CloudWatchLogsEvent`));
|
|
35
|
+
const remoteLogs = this.mapLogs(event, logMessage);
|
|
36
|
+
this.logger.debug(logMessage(`finished mapping CloudWatchLogsEvent`));
|
|
37
|
+
this.logger.debug(logMessage(`started sending logs (count: ${remoteLogs.length}) into the RemoteLogger`));
|
|
38
|
+
await this.remoteLogger.log(remoteLogs);
|
|
39
|
+
this.logger.debug(logMessage('finished sending logs into the RemoteLogger'));
|
|
40
|
+
}
|
|
41
|
+
mapLogs(event, logMessage) {
|
|
42
|
+
const logs = this.decodeLogs(event);
|
|
43
|
+
this.logger.debug(logMessage(`received decoded logs: ${(0, util_1.inspect)(logs, { depth: 4 })}`));
|
|
44
|
+
const isRemoteLog = (log) => !!log;
|
|
45
|
+
return logs
|
|
46
|
+
.map((log) => {
|
|
47
|
+
const result = RemoteLogger_1.REMOTE_LOG_SCHEMA.safeParse(JSON.parse(log.message));
|
|
48
|
+
return result.success ? result.data : undefined;
|
|
49
|
+
})
|
|
50
|
+
.filter(isRemoteLog);
|
|
51
|
+
}
|
|
52
|
+
decodeLogs(event) {
|
|
53
|
+
const payload = Buffer.from(event.awslogs.data, 'base64');
|
|
54
|
+
const logs = JSON.parse(zlib_1.default.unzipSync(payload).toString());
|
|
55
|
+
return logs.logEvents;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
exports.LogsHandler = LogsHandler;
|
|
59
|
+
exports.LogsHandler = LogsHandler = __decorate([
|
|
60
|
+
(0, inversify_1.injectable)(),
|
|
61
|
+
__param(0, (0, inversify_1.inject)(RemoteLogger_1.RemoteLogger)),
|
|
62
|
+
__param(1, (0, inversify_1.inject)(Logger_1.Logger)),
|
|
63
|
+
__metadata("design:paramtypes", [RemoteLogger_1.RemoteLogger,
|
|
64
|
+
Logger_1.Logger])
|
|
65
|
+
], LogsHandler);
|
|
66
|
+
//# sourceMappingURL=LogsHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogsHandler.js","sourceRoot":"","sources":["../../src/logger/LogsHandler.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AACA,gDAAwB;AACxB,yCAA+C;AAC/C,+BAA+B;AAE/B,iDAA4E;AAC5E,qCAAkC;AAClC,mDAAmD;AAG5C,IAAM,WAAW,GAAjB,MAAM,WAAW;IAGH;IAEA;IAJnB,YAEmB,YAA0B,EAE1B,MAAc;QAFd,iBAAY,GAAZ,YAAY,CAAc;QAE1B,WAAM,GAAN,MAAM,CAAQ;IAC9B,CAAC;IAEJ,KAAK,CAAC,MAAM,CAAC,KAA0B;QACrC,MAAM,UAAU,GAAG,IAAA,gCAAgB,EAAC,IAAI,CAAC,CAAC;QAE1C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,qCAAqC,CAAC,CAAC,CAAC;QACrE,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAEnD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,sCAAsC,CAAC,CAAC,CAAC;QAEtE,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,UAAU,CACR,gCAAgC,UAAU,CAAC,MAAM,yBAAyB,CAC3E,CACF,CAAC;QACF,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,UAAU,CAAC,6CAA6C,CAAC,CAC1D,CAAC;IACJ,CAAC;IAEO,OAAO,CACb,KAA0B,EAC1B,UAA+C;QAE/C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAEpC,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,UAAU,CAAC,0BAA0B,IAAA,cAAO,EAAC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CACpE,CAAC;QACF,MAAM,WAAW,GAAG,CAAC,GAA0B,EAAoB,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAE5E,OAAO,IAAI;aACR,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,MAAM,GAAG,gCAAiB,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;YAEpE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QAClD,CAAC,CAAC;aACD,MAAM,CAAC,WAAW,CAAC,CAAC;IACzB,CAAC;IAEO,UAAU,CAChB,KAA0B;QAE1B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,cAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QAE5D,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;CACF,CAAA;AAvDY,kCAAW;sBAAX,WAAW;IADvB,IAAA,sBAAU,GAAE;IAGR,WAAA,IAAA,kBAAM,EAAC,2BAAY,CAAC,CAAA;IAEpB,WAAA,IAAA,kBAAM,EAAC,eAAM,CAAC,CAAA;qCADgB,2BAAY;QAElB,eAAM;GALtB,WAAW,CAuDvB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CloudWatchLogsEvent } from 'aws-lambda';
|
|
2
|
+
import { LogsHandler } from './LogsHandler';
|
|
3
|
+
import { Logger } from './Logger';
|
|
4
|
+
import { Container } from 'inversify';
|
|
5
|
+
export declare const CLOUDWATCH_FILTER_PATTERN = "{ $.level = \"info\" || $.level = \"warn\" || ($.level = \"error\" && $.processable IS TRUE) || $.remote IS TRUE }";
|
|
6
|
+
export type LogsLambdaHandler = (event: CloudWatchLogsEvent) => Promise<{
|
|
7
|
+
status: string;
|
|
8
|
+
}>;
|
|
9
|
+
export declare function createLogsLambdaHandler(instances: {
|
|
10
|
+
logsHandler: LogsHandler;
|
|
11
|
+
logger: Logger;
|
|
12
|
+
}): LogsLambdaHandler;
|
|
13
|
+
export declare function createLogsLambdaHandler(container: Container): LogsLambdaHandler;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CLOUDWATCH_FILTER_PATTERN = void 0;
|
|
4
|
+
exports.createLogsLambdaHandler = createLogsLambdaHandler;
|
|
5
|
+
const LogsHandler_1 = require("./LogsHandler");
|
|
6
|
+
const Logger_1 = require("./Logger");
|
|
7
|
+
const inversify_1 = require("inversify");
|
|
8
|
+
exports.CLOUDWATCH_FILTER_PATTERN = `{ $.level = "info" || $.level = "warn" || ($.level = "error" && $.processable IS TRUE) || $.remote IS TRUE }`;
|
|
9
|
+
function createLogsLambdaHandler(opts) {
|
|
10
|
+
let logsHandler;
|
|
11
|
+
let logger;
|
|
12
|
+
if (opts instanceof inversify_1.Container) {
|
|
13
|
+
logsHandler = opts.get(LogsHandler_1.LogsHandler);
|
|
14
|
+
logger = opts.get(Logger_1.Logger);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
logsHandler = opts.logsHandler;
|
|
18
|
+
logger = opts.logger;
|
|
19
|
+
}
|
|
20
|
+
return async (event) => {
|
|
21
|
+
try {
|
|
22
|
+
await logsHandler.handle(event);
|
|
23
|
+
return { status: 'ok' };
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
logger.error(e);
|
|
27
|
+
throw e;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=LogsLambdaHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogsLambdaHandler.js","sourceRoot":"","sources":["../../src/logger/LogsLambdaHandler.ts"],"names":[],"mappings":";;;AAkBA,0DAwBC;AAzCD,+CAA4C;AAC5C,qCAAkC;AAClC,yCAAsC;AAEzB,QAAA,yBAAyB,GAAG,8GAA8G,CAAC;AAaxJ,SAAgB,uBAAuB,CACrC,IAA8D;IAE9D,IAAI,WAAwB,CAAC;IAC7B,IAAI,MAAc,CAAC;IAEnB,IAAI,IAAI,YAAY,qBAAS,EAAE,CAAC;QAC9B,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,yBAAW,CAAC,CAAC;QACpC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,eAAM,CAAC,CAAC;IAC5B,CAAC;SAAM,CAAC;QACN,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QAC/B,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,OAAO,KAAK,EAAE,KAA0B,EAAE,EAAE;QAC1C,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAEhC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC1B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAChB,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@squiz/optimization-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "",
|
|
5
|
-
"main": "dist/
|
|
6
|
-
"types": "dist/
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
7
|
"repository": "https://gitlab.squiz.net/optimization/optimization-utils",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "rm -rf dist && tsc",
|
|
@@ -1,23 +1,35 @@
|
|
|
1
1
|
export * from './valueObject/TenantId';
|
|
2
|
+
|
|
2
3
|
export * from './validation/handleValidation';
|
|
4
|
+
|
|
3
5
|
export * from './typesUtils/utilities';
|
|
4
6
|
export * from './typesUtils/DynamoDB';
|
|
7
|
+
|
|
5
8
|
export * from './testing/mock';
|
|
9
|
+
|
|
6
10
|
export * from './scheduler/Scheduler';
|
|
7
11
|
export * from './scheduler/EventBridgeScheduler';
|
|
12
|
+
|
|
8
13
|
export * from './logger/SquizRemoteLogger';
|
|
9
14
|
export * from './logger/RemoteLogger';
|
|
10
15
|
export * from './logger/LoggerMessage';
|
|
11
16
|
export * from './logger/Logger';
|
|
17
|
+
export * from './logger/LogsLambdaHandler';
|
|
18
|
+
|
|
12
19
|
export * from './httpClient/HttpRequestBuilder';
|
|
13
20
|
export * from './httpClient/HttpClient';
|
|
14
21
|
export * from './httpClient/FetchHttpClient';
|
|
22
|
+
|
|
15
23
|
export * from './exception/DomainException';
|
|
24
|
+
|
|
16
25
|
export * from './event/DynamoDBEventMapper';
|
|
17
26
|
export * from './event/DomainEvent';
|
|
18
27
|
export * from './event/AggregateRoot';
|
|
28
|
+
|
|
19
29
|
export * from './date/DateManipulator';
|
|
30
|
+
export * from './event/EventHandler';
|
|
31
|
+
|
|
20
32
|
export * from './config/ConfigurationLoader';
|
|
33
|
+
|
|
21
34
|
export * from './cloudflare/ImplCloudflareKVHttpService';
|
|
22
35
|
export * from './cloudflare/CloudflareKVHttpService';
|
|
23
|
-
export * from './event/EventHandler';
|
|
@@ -35,6 +35,7 @@ export const TENANT_ID_METADATA = (
|
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
export const PROCESSABLE_LOG_METADATA = { processable: true } as const;
|
|
38
|
+
export const REMOTE_LOG_METADATA = { remote: true } as const;
|
|
38
39
|
|
|
39
40
|
export type LogMessage = (
|
|
40
41
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -52,6 +53,7 @@ export type CreateLog = {
|
|
|
52
53
|
caller: InstanceType<T> | string,
|
|
53
54
|
) => CreateLog;
|
|
54
55
|
isProcessable: () => CreateLog;
|
|
56
|
+
remote: () => CreateLog;
|
|
55
57
|
getMetadata: () => Record<string, unknown>;
|
|
56
58
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
57
59
|
create: <T extends abstract new (...args: any) => any>(
|
|
@@ -112,6 +114,10 @@ export function createLog(opts?: {
|
|
|
112
114
|
return attachMetadata(PROCESSABLE_LOG_METADATA);
|
|
113
115
|
};
|
|
114
116
|
|
|
117
|
+
const remote = (): CreateLog => {
|
|
118
|
+
return attachMetadata(REMOTE_LOG_METADATA);
|
|
119
|
+
};
|
|
120
|
+
|
|
115
121
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
116
122
|
const attachCaller = <T extends abstract new (...args: any) => any>(
|
|
117
123
|
caller: T | string,
|
|
@@ -146,6 +152,7 @@ export function createLog(opts?: {
|
|
|
146
152
|
isProcessable,
|
|
147
153
|
attachCaller,
|
|
148
154
|
getMetadata: () => opts?.metadata ?? {},
|
|
155
|
+
remote,
|
|
149
156
|
create,
|
|
150
157
|
};
|
|
151
158
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { CloudWatchLogsEvent } from 'aws-lambda';
|
|
2
|
+
import zlib from 'zlib';
|
|
3
|
+
import { inject, injectable } from 'inversify';
|
|
4
|
+
import { inspect } from 'util';
|
|
5
|
+
import type { CloudWatchLogsLogEvent } from 'aws-lambda/trigger/cloudwatch-logs';
|
|
6
|
+
import { REMOTE_LOG_SCHEMA, RemoteLog, RemoteLogger } from './RemoteLogger';
|
|
7
|
+
import { Logger } from './Logger';
|
|
8
|
+
import { createLogMessage } from './LoggerMessage';
|
|
9
|
+
|
|
10
|
+
@injectable()
|
|
11
|
+
export class LogsHandler {
|
|
12
|
+
constructor(
|
|
13
|
+
@inject(RemoteLogger)
|
|
14
|
+
private readonly remoteLogger: RemoteLogger,
|
|
15
|
+
@inject(Logger)
|
|
16
|
+
private readonly logger: Logger,
|
|
17
|
+
) {}
|
|
18
|
+
|
|
19
|
+
async handle(event: CloudWatchLogsEvent): Promise<void> {
|
|
20
|
+
const logMessage = createLogMessage(this);
|
|
21
|
+
|
|
22
|
+
this.logger.debug(logMessage(`started mapping CloudWatchLogsEvent`));
|
|
23
|
+
const remoteLogs = this.mapLogs(event, logMessage);
|
|
24
|
+
|
|
25
|
+
this.logger.debug(logMessage(`finished mapping CloudWatchLogsEvent`));
|
|
26
|
+
|
|
27
|
+
this.logger.debug(
|
|
28
|
+
logMessage(
|
|
29
|
+
`started sending logs (count: ${remoteLogs.length}) into the RemoteLogger`,
|
|
30
|
+
),
|
|
31
|
+
);
|
|
32
|
+
await this.remoteLogger.log(remoteLogs);
|
|
33
|
+
this.logger.debug(
|
|
34
|
+
logMessage('finished sending logs into the RemoteLogger'),
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private mapLogs(
|
|
39
|
+
event: CloudWatchLogsEvent,
|
|
40
|
+
logMessage: ReturnType<typeof createLogMessage>,
|
|
41
|
+
): Array<RemoteLog> {
|
|
42
|
+
const logs = this.decodeLogs(event);
|
|
43
|
+
|
|
44
|
+
this.logger.debug(
|
|
45
|
+
logMessage(`received decoded logs: ${inspect(logs, { depth: 4 })}`),
|
|
46
|
+
);
|
|
47
|
+
const isRemoteLog = (log: undefined | RemoteLog): log is RemoteLog => !!log;
|
|
48
|
+
|
|
49
|
+
return logs
|
|
50
|
+
.map((log) => {
|
|
51
|
+
const result = REMOTE_LOG_SCHEMA.safeParse(JSON.parse(log.message));
|
|
52
|
+
|
|
53
|
+
return result.success ? result.data : undefined;
|
|
54
|
+
})
|
|
55
|
+
.filter(isRemoteLog);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private decodeLogs(
|
|
59
|
+
event: CloudWatchLogsEvent,
|
|
60
|
+
): Array<CloudWatchLogsLogEvent> {
|
|
61
|
+
const payload = Buffer.from(event.awslogs.data, 'base64');
|
|
62
|
+
const logs = JSON.parse(zlib.unzipSync(payload).toString());
|
|
63
|
+
|
|
64
|
+
return logs.logEvents;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { CloudWatchLogsEvent } from 'aws-lambda';
|
|
2
|
+
import { LogsHandler } from './LogsHandler';
|
|
3
|
+
import { Logger } from './Logger';
|
|
4
|
+
import { Container } from 'inversify';
|
|
5
|
+
|
|
6
|
+
export const CLOUDWATCH_FILTER_PATTERN = `{ $.level = "info" || $.level = "warn" || ($.level = "error" && $.processable IS TRUE) || $.remote IS TRUE }`;
|
|
7
|
+
|
|
8
|
+
export type LogsLambdaHandler = (
|
|
9
|
+
event: CloudWatchLogsEvent,
|
|
10
|
+
) => Promise<{ status: string }>;
|
|
11
|
+
|
|
12
|
+
export function createLogsLambdaHandler(instances: {
|
|
13
|
+
logsHandler: LogsHandler;
|
|
14
|
+
logger: Logger;
|
|
15
|
+
}): LogsLambdaHandler;
|
|
16
|
+
export function createLogsLambdaHandler(
|
|
17
|
+
container: Container,
|
|
18
|
+
): LogsLambdaHandler;
|
|
19
|
+
export function createLogsLambdaHandler(
|
|
20
|
+
opts: { logsHandler: LogsHandler; logger: Logger } | Container,
|
|
21
|
+
): LogsLambdaHandler {
|
|
22
|
+
let logsHandler: LogsHandler;
|
|
23
|
+
let logger: Logger;
|
|
24
|
+
|
|
25
|
+
if (opts instanceof Container) {
|
|
26
|
+
logsHandler = opts.get(LogsHandler);
|
|
27
|
+
logger = opts.get(Logger);
|
|
28
|
+
} else {
|
|
29
|
+
logsHandler = opts.logsHandler;
|
|
30
|
+
logger = opts.logger;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return async (event: CloudWatchLogsEvent) => {
|
|
34
|
+
try {
|
|
35
|
+
await logsHandler.handle(event);
|
|
36
|
+
|
|
37
|
+
return { status: 'ok' };
|
|
38
|
+
} catch (e) {
|
|
39
|
+
logger.error(e);
|
|
40
|
+
throw e;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { LogsHandler } from '../LogsHandler';
|
|
2
|
+
import zlib from 'zlib';
|
|
3
|
+
import { CloudWatchLogsEvent } from 'aws-lambda';
|
|
4
|
+
import { faker } from '@faker-js/faker';
|
|
5
|
+
import { CloudWatchLogsLogEvent } from 'aws-lambda/trigger/cloudwatch-logs';
|
|
6
|
+
import { RemoteLog, RemoteLogger, RemoteLogLevel } from '../RemoteLogger';
|
|
7
|
+
import { createLoggerMock, createRemoteLoggerMock } from '../../testing/mock';
|
|
8
|
+
import { TenantId } from '../../valueObject/TenantId';
|
|
9
|
+
|
|
10
|
+
const createCloudWatchEvent = (
|
|
11
|
+
logs: Array<Record<string, unknown>>,
|
|
12
|
+
): CloudWatchLogsEvent => {
|
|
13
|
+
const cloudWatchLogsLogEvents: Array<CloudWatchLogsLogEvent> = logs.map(
|
|
14
|
+
(l) => {
|
|
15
|
+
return {
|
|
16
|
+
id: faker.number.bigInt().toString(),
|
|
17
|
+
timestamp: faker.date.past().valueOf(),
|
|
18
|
+
message: JSON.stringify(l),
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
);
|
|
22
|
+
const base64 = Buffer.from(
|
|
23
|
+
JSON.stringify({ logEvents: cloudWatchLogsLogEvents }),
|
|
24
|
+
);
|
|
25
|
+
const zipped = zlib.gzipSync(base64);
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
awslogs: {
|
|
29
|
+
data: zipped.toString('base64'),
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
describe('LogsHandler', () => {
|
|
35
|
+
let logsHandler: LogsHandler;
|
|
36
|
+
let remoteLogger: RemoteLogger;
|
|
37
|
+
const remoteLog: Omit<RemoteLog, 'tenantId'> & {
|
|
38
|
+
tenantId: string;
|
|
39
|
+
} = {
|
|
40
|
+
level: faker.helpers.arrayElement(Object.values(RemoteLogLevel)),
|
|
41
|
+
message: faker.word.words(),
|
|
42
|
+
tenantId: faker.word.words(),
|
|
43
|
+
timestamp: faker.date.past(),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
beforeEach(() => {
|
|
47
|
+
remoteLogger = createRemoteLoggerMock();
|
|
48
|
+
|
|
49
|
+
logsHandler = new LogsHandler(remoteLogger, createLoggerMock());
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should decode a CloudWatchLogsEvent and send to the RemoteLogger', async () => {
|
|
53
|
+
await logsHandler.handle(createCloudWatchEvent([remoteLog]));
|
|
54
|
+
|
|
55
|
+
expect(remoteLogger.log).toHaveBeenCalledWith([
|
|
56
|
+
{
|
|
57
|
+
...remoteLog,
|
|
58
|
+
tenantId: new TenantId(remoteLog.tenantId),
|
|
59
|
+
},
|
|
60
|
+
]);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should decode a CloudWatchLogsEvent and send only the RemoteLogs to the RemoteLogger', async () => {
|
|
64
|
+
const otherLog = {
|
|
65
|
+
test: faker.word.words(),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
await logsHandler.handle(createCloudWatchEvent([remoteLog, otherLog]));
|
|
69
|
+
|
|
70
|
+
expect(remoteLogger.log).toHaveBeenCalledWith([
|
|
71
|
+
{
|
|
72
|
+
...remoteLog,
|
|
73
|
+
tenantId: new TenantId(remoteLog.tenantId),
|
|
74
|
+
},
|
|
75
|
+
]);
|
|
76
|
+
});
|
|
77
|
+
});
|
package/dist/package.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"package.js","sourceRoot":"","sources":["../src/package.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC;AACvC,gEAA8C;AAC9C,yDAAuC;AACvC,wDAAsC;AACtC,iDAA+B;AAC/B,wDAAsC;AACtC,mEAAiD;AACjD,6DAA2C;AAC3C,wDAAsC;AACtC,yDAAuC;AACvC,kDAAgC;AAChC,kEAAgD;AAChD,0DAAwC;AACxC,+DAA6C;AAC7C,8DAA4C;AAC5C,8DAA4C;AAC5C,sDAAoC;AACpC,wDAAsC;AACtC,yDAAuC;AACvC,+DAA6C;AAC7C,2EAAyD;AACzD,uEAAqD;AACrD,uDAAqC"}
|