@payfit/audit-log 3.5.0-rc.21 → 3.5.0-rc.22
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/dist/compression.d.ts +2 -0
- package/dist/compression.test.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +76 -56
- package/dist/transport/implementation.d.ts +4 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var w=Object.defineProperty;var p=(s,e,t)=>e in s?w(s,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[e]=t;var i=(s,e,t)=>(p(s,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("uuid"),a=require("winston"),S=require("hot-shots"),d=require("@aws-sdk/client-sqs"),E=require("zlib"),y="audit-logs",_="@payfit/audit-log",q=()=>{const s=process.env.LOG_LEVEL;return s&&s.trim()!==""?s.trim():"info"},L=(s,e)=>a.createLogger({level:q(),silent:process.env.NODE_ENV==="test",exitOnError:!1,defaultMeta:{namespace:y,sdk:_,service:s,environment:e},format:a.format.combine(a.format.timestamp(),a.format.errors({stack:!0}),a.format.json()),transports:[new a.transports.Console]}),M="payfit.audit-logs.",h=s=>Object.entries(s).filter(([,e])=>e!==void 0&&e!=="").map(([e,t])=>`${e}:${String(t)}`);class A{constructor(){i(this,"client");this.client=new S.StatsD({prefix:M,errorHandler:()=>{},cacheDns:!0})}increment(e,t){this.client.increment(e,1,h(t))}histogram(e,t,n){this.client.histogram(e,t,h(n))}async close(){await new Promise(e=>{this.client.close(()=>e())})}}const b=()=>new A;function C(s){return E.brotliCompressSync(Buffer.from(s,"utf8")).toString("base64")}function U(s){return s instanceof Error&&s.message.includes("Message must be shorter than")}const O="eu-west-3",z={dev:"https://sqs.eu-west-3.amazonaws.com/533547282673/audit-logs-ingest",staging:"https://sqs.eu-west-3.amazonaws.com/589883667243/audit-logs-ingest",prod:"https://sqs.eu-west-3.amazonaws.com/614948436281/audit-logs-ingest"},D={working:"staging",production:"prod"};class N{constructor(e,t){i(this,"environment");i(this,"logger");i(this,"client");i(this,"queueUrl");this.environment=e,this.logger=t;const n=D[e]??e,o=z[n];if(!o)throw new Error(`audit-logs SDK: no SQS queue URL configured for environment "${e}"`);this.queueUrl=o,this.client=new d.SQSClient({region:O})}async create(e){var n;const t=JSON.stringify(e);try{await this.send(t)}catch(o){if(!U(o))throw o;(n=this.logger)==null||n.info("audit-log payload exceeds the SQS size limit, retrying with Brotli compression",{id:e.id,namespace:e.namespace}),await this.send(C(t))}}async send(e){await this.client.send(new d.SendMessageCommand({QueueUrl:this.queueUrl,MessageBody:e}))}}class Q{constructor(e,t={}){i(this,"params");i(this,"transport");i(this,"logger");i(this,"metrics");this.params=e,this.logger=t.logger??L(e.service,e.environment),this.transport=t.transport??new N(e.environment,this.logger),this.metrics=t.metrics??b()}async log({scope:e,account:t,...n}){const o=v.v4(),{environment:g,service:l}=this.params,r={...n,...t,service:l,id:o,environment:g,...e&&{scope:e}},c={service:l,environment:g,namespace:r.namespace,event:r.event,target:r.target},m=Date.now();try{await this.transport.create(r),this.metrics.increment("sent",c),this.metrics.histogram("send_duration_ms",Date.now()-m,c),this.logger.debug("audit-log sent",{id:r.id,event:r.event,target:r.target})}catch(f){this.metrics.increment("send_failed",c),this.metrics.histogram("send_duration_ms",Date.now()-m,c);const u=f.message;try{this.logger.error("audit-log write failed",{audit_log:r,error:u})}catch{this.metrics.increment("serialization_failed",c);try{this.logger.error("audit-log write failed (serialization failed)",{audit_log_meta:{id:r.id,service:r.service,environment:r.environment,namespace:r.namespace,event:r.event,target:r.target},error:u})}catch{}}}}}exports.AuditLogger=Q;
|
package/dist/index.mjs
CHANGED
|
@@ -1,114 +1,134 @@
|
|
|
1
1
|
var p = Object.defineProperty;
|
|
2
|
-
var
|
|
3
|
-
var i = (s,
|
|
4
|
-
import { v4 as
|
|
5
|
-
import { createLogger as
|
|
6
|
-
import { StatsD as
|
|
7
|
-
import { SQSClient as
|
|
8
|
-
|
|
2
|
+
var f = (s, e, t) => e in s ? p(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
|
|
3
|
+
var i = (s, e, t) => (f(s, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
|
+
import { v4 as w } from "uuid";
|
|
5
|
+
import { createLogger as v, format as c, transports as S } from "winston";
|
|
6
|
+
import { StatsD as E } from "hot-shots";
|
|
7
|
+
import { SQSClient as _, SendMessageCommand as y } from "@aws-sdk/client-sqs";
|
|
8
|
+
import { brotliCompressSync as L } from "zlib";
|
|
9
|
+
const M = "audit-logs", A = "@payfit/audit-log", C = () => {
|
|
9
10
|
const s = process.env.LOG_LEVEL;
|
|
10
11
|
return s && s.trim() !== "" ? s.trim() : "info";
|
|
11
|
-
},
|
|
12
|
-
level:
|
|
12
|
+
}, U = (s, e) => v({
|
|
13
|
+
level: C(),
|
|
13
14
|
silent: process.env.NODE_ENV === "test",
|
|
14
15
|
exitOnError: !1,
|
|
15
16
|
defaultMeta: {
|
|
16
|
-
namespace:
|
|
17
|
+
namespace: M,
|
|
17
18
|
sdk: A,
|
|
18
19
|
service: s,
|
|
19
|
-
environment:
|
|
20
|
+
environment: e
|
|
20
21
|
},
|
|
21
|
-
format:
|
|
22
|
-
transports: [new
|
|
23
|
-
}),
|
|
24
|
-
class
|
|
22
|
+
format: c.combine(c.timestamp(), c.errors({ stack: !0 }), c.json()),
|
|
23
|
+
transports: [new S.Console()]
|
|
24
|
+
}), q = "payfit.audit-logs.", u = (s) => Object.entries(s).filter(([, e]) => e !== void 0 && e !== "").map(([e, t]) => `${e}:${String(t)}`);
|
|
25
|
+
class b {
|
|
25
26
|
constructor() {
|
|
26
27
|
i(this, "client");
|
|
27
|
-
this.client = new
|
|
28
|
-
prefix:
|
|
28
|
+
this.client = new E({
|
|
29
|
+
prefix: q,
|
|
29
30
|
// Loss of metrics never breaks the caller — DogStatsD UDP is best-effort by design.
|
|
30
31
|
errorHandler: () => {
|
|
31
32
|
},
|
|
32
33
|
cacheDns: !0
|
|
33
34
|
});
|
|
34
35
|
}
|
|
35
|
-
increment(
|
|
36
|
-
this.client.increment(
|
|
36
|
+
increment(e, t) {
|
|
37
|
+
this.client.increment(e, 1, u(t));
|
|
37
38
|
}
|
|
38
|
-
histogram(
|
|
39
|
-
this.client.histogram(
|
|
39
|
+
histogram(e, t, n) {
|
|
40
|
+
this.client.histogram(e, t, u(n));
|
|
40
41
|
}
|
|
41
42
|
async close() {
|
|
42
|
-
await new Promise((
|
|
43
|
-
this.client.close(() =>
|
|
43
|
+
await new Promise((e) => {
|
|
44
|
+
this.client.close(() => e());
|
|
44
45
|
});
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
|
-
const
|
|
48
|
+
const D = () => new b();
|
|
49
|
+
function N(s) {
|
|
50
|
+
return L(Buffer.from(s, "utf8")).toString("base64");
|
|
51
|
+
}
|
|
52
|
+
function O(s) {
|
|
53
|
+
return s instanceof Error && s.message.includes("Message must be shorter than");
|
|
54
|
+
}
|
|
55
|
+
const z = "eu-west-3", Q = {
|
|
48
56
|
dev: "https://sqs.eu-west-3.amazonaws.com/533547282673/audit-logs-ingest",
|
|
49
57
|
staging: "https://sqs.eu-west-3.amazonaws.com/589883667243/audit-logs-ingest",
|
|
50
58
|
prod: "https://sqs.eu-west-3.amazonaws.com/614948436281/audit-logs-ingest"
|
|
51
|
-
},
|
|
59
|
+
}, R = {
|
|
52
60
|
working: "staging",
|
|
53
61
|
production: "prod"
|
|
54
62
|
};
|
|
55
|
-
class
|
|
56
|
-
constructor(t) {
|
|
63
|
+
class k {
|
|
64
|
+
constructor(e, t) {
|
|
57
65
|
i(this, "environment");
|
|
66
|
+
i(this, "logger");
|
|
58
67
|
i(this, "client");
|
|
59
68
|
i(this, "queueUrl");
|
|
60
|
-
this.environment = t;
|
|
61
|
-
const
|
|
62
|
-
if (!
|
|
63
|
-
throw new Error(`audit-logs SDK: no SQS queue URL configured for environment "${
|
|
64
|
-
this.queueUrl =
|
|
69
|
+
this.environment = e, this.logger = t;
|
|
70
|
+
const n = R[e] ?? e, o = Q[n];
|
|
71
|
+
if (!o)
|
|
72
|
+
throw new Error(`audit-logs SDK: no SQS queue URL configured for environment "${e}"`);
|
|
73
|
+
this.queueUrl = o, this.client = new _({ region: z });
|
|
74
|
+
}
|
|
75
|
+
async create(e) {
|
|
76
|
+
var n;
|
|
77
|
+
const t = JSON.stringify(e);
|
|
78
|
+
try {
|
|
79
|
+
await this.send(t);
|
|
80
|
+
} catch (o) {
|
|
81
|
+
if (!O(o))
|
|
82
|
+
throw o;
|
|
83
|
+
(n = this.logger) == null || n.info("audit-log payload exceeds the SQS size limit, retrying with Brotli compression", { id: e.id, namespace: e.namespace }), await this.send(N(t));
|
|
84
|
+
}
|
|
65
85
|
}
|
|
66
|
-
async
|
|
67
|
-
await this.client.send(new
|
|
86
|
+
async send(e) {
|
|
87
|
+
await this.client.send(new y({
|
|
68
88
|
QueueUrl: this.queueUrl,
|
|
69
|
-
MessageBody:
|
|
89
|
+
MessageBody: e
|
|
70
90
|
}));
|
|
71
91
|
}
|
|
72
92
|
}
|
|
73
|
-
class
|
|
74
|
-
constructor(
|
|
93
|
+
class V {
|
|
94
|
+
constructor(e, t = {}) {
|
|
75
95
|
i(this, "params");
|
|
76
96
|
i(this, "transport");
|
|
77
97
|
i(this, "logger");
|
|
78
98
|
i(this, "metrics");
|
|
79
|
-
this.params =
|
|
99
|
+
this.params = e, this.logger = t.logger ?? U(e.service, e.environment), this.transport = t.transport ?? new k(e.environment, this.logger), this.metrics = t.metrics ?? D();
|
|
80
100
|
}
|
|
81
|
-
async log({ scope:
|
|
82
|
-
const
|
|
101
|
+
async log({ scope: e, account: t, ...n }) {
|
|
102
|
+
const o = w(), { environment: g, service: l } = this.params, r = {
|
|
83
103
|
...n,
|
|
84
|
-
...
|
|
85
|
-
service:
|
|
86
|
-
id:
|
|
87
|
-
environment:
|
|
88
|
-
...
|
|
89
|
-
},
|
|
90
|
-
service:
|
|
91
|
-
environment:
|
|
104
|
+
...t,
|
|
105
|
+
service: l,
|
|
106
|
+
id: o,
|
|
107
|
+
environment: g,
|
|
108
|
+
...e && { scope: e }
|
|
109
|
+
}, a = {
|
|
110
|
+
service: l,
|
|
111
|
+
environment: g,
|
|
92
112
|
namespace: r.namespace,
|
|
93
113
|
event: r.event,
|
|
94
114
|
target: r.target
|
|
95
|
-
},
|
|
115
|
+
}, m = Date.now();
|
|
96
116
|
try {
|
|
97
|
-
await this.transport.create(r), this.metrics.increment("sent",
|
|
117
|
+
await this.transport.create(r), this.metrics.increment("sent", a), this.metrics.histogram("send_duration_ms", Date.now() - m, a), this.logger.debug("audit-log sent", {
|
|
98
118
|
id: r.id,
|
|
99
119
|
event: r.event,
|
|
100
120
|
target: r.target
|
|
101
121
|
});
|
|
102
122
|
} catch (h) {
|
|
103
|
-
this.metrics.increment("send_failed",
|
|
104
|
-
const
|
|
123
|
+
this.metrics.increment("send_failed", a), this.metrics.histogram("send_duration_ms", Date.now() - m, a);
|
|
124
|
+
const d = h.message;
|
|
105
125
|
try {
|
|
106
126
|
this.logger.error("audit-log write failed", {
|
|
107
127
|
audit_log: r,
|
|
108
|
-
error:
|
|
128
|
+
error: d
|
|
109
129
|
});
|
|
110
130
|
} catch {
|
|
111
|
-
this.metrics.increment("serialization_failed",
|
|
131
|
+
this.metrics.increment("serialization_failed", a);
|
|
112
132
|
try {
|
|
113
133
|
this.logger.error("audit-log write failed (serialization failed)", {
|
|
114
134
|
audit_log_meta: {
|
|
@@ -119,7 +139,7 @@ class x {
|
|
|
119
139
|
event: r.event,
|
|
120
140
|
target: r.target
|
|
121
141
|
},
|
|
122
|
-
error:
|
|
142
|
+
error: d
|
|
123
143
|
});
|
|
124
144
|
} catch {
|
|
125
145
|
}
|
|
@@ -128,5 +148,5 @@ class x {
|
|
|
128
148
|
}
|
|
129
149
|
}
|
|
130
150
|
export {
|
|
131
|
-
|
|
151
|
+
V as AuditLogger
|
|
132
152
|
};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import type { Logger } from 'winston';
|
|
1
2
|
import { IAuditLogCreationData, IAuditLogTransport } from './interface';
|
|
2
3
|
export declare class Transport implements IAuditLogTransport {
|
|
3
4
|
protected environment: string;
|
|
5
|
+
private logger?;
|
|
4
6
|
private client;
|
|
5
7
|
private queueUrl;
|
|
6
|
-
constructor(environment: string);
|
|
8
|
+
constructor(environment: string, logger?: Logger | undefined);
|
|
7
9
|
create(auditLogData: IAuditLogCreationData): Promise<void>;
|
|
10
|
+
private send;
|
|
8
11
|
}
|