@payfit/audit-log 3.8.0 → 3.10.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/dist/index.d.ts +13 -3
- package/dist/index.js +1 -1
- package/dist/index.mjs +109 -57
- package/dist/logger.d.ts +2 -0
- package/dist/logger.test.d.ts +1 -0
- package/dist/metrics.d.ts +15 -0
- package/dist/metrics.test.d.ts +1 -0
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import type { Logger } from 'winston';
|
|
2
|
+
import { type IMetricsClient } from './metrics';
|
|
3
|
+
import { IAuditLogTransport } from './transport/interface';
|
|
1
4
|
/**
|
|
2
5
|
* The allowed Namespaces for the AuditLog
|
|
3
6
|
*/
|
|
4
|
-
export type AuditNamespaces = 'employee' | 'company' | 'permissions' | 'absence' | 'expense' | 'payments' | 'auth' | 'billing' | 'modules' | 'integrations' | 'partnerApi' | 'donation' | 'notificationSettings' | 'people' | 'subscriptions' | 'organization' | 'declarations' | 'pricing' | 'payroll' | 'jetlang' | 'files' | 'versioner';
|
|
7
|
+
export type AuditNamespaces = 'employee' | 'company' | 'permissions' | 'absence' | 'expense' | 'payments' | 'auth' | 'billing' | 'modules' | 'integrations' | 'partnerApi' | 'donation' | 'notificationSettings' | 'people' | 'subscriptions' | 'organization' | 'declarations' | 'pricing' | 'payroll' | 'jetlang' | 'files' | 'versioner' | 'live-timing';
|
|
5
8
|
/**
|
|
6
9
|
* The allowed targets for the AuditLog
|
|
7
10
|
*/
|
|
@@ -97,9 +100,16 @@ export interface IAuditLoggerInitialization {
|
|
|
97
100
|
environment: string;
|
|
98
101
|
service: string;
|
|
99
102
|
}
|
|
103
|
+
export interface IAuditLoggerDependencies {
|
|
104
|
+
transport?: IAuditLogTransport;
|
|
105
|
+
logger?: Logger;
|
|
106
|
+
metrics?: IMetricsClient;
|
|
107
|
+
}
|
|
100
108
|
export declare class AuditLogger implements IAuditLogger {
|
|
101
109
|
protected params: IAuditLoggerInitialization;
|
|
102
|
-
private transport;
|
|
103
|
-
|
|
110
|
+
private readonly transport;
|
|
111
|
+
private readonly logger;
|
|
112
|
+
private readonly metrics;
|
|
113
|
+
constructor(params: IAuditLoggerInitialization, deps?: IAuditLoggerDependencies);
|
|
104
114
|
log({ scope, account, ...data }: IAuditLogData): Promise<void>;
|
|
105
115
|
}
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var v=Object.defineProperty;var p=(s,t,e)=>t in s?v(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var n=(s,t,e)=>(p(s,typeof t!="symbol"?t+"":t,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("uuid"),o=require("winston"),S=require("hot-shots"),m=require("@aws-sdk/client-sqs"),E="audit-logs",_="@payfit/audit-log",L=()=>{const s=process.env.LOG_LEVEL;return s&&s.trim()!==""?s.trim():"info"},q=(s,t)=>o.createLogger({level:L(),silent:process.env.NODE_ENV==="test",exitOnError:!1,defaultMeta:{namespace:E,sdk:_,service:s,environment:t},format:o.format.combine(o.format.timestamp(),o.format.errors({stack:!0}),o.format.json()),transports:[new o.transports.Console]}),y="payfit.audit-logs.",d=s=>Object.entries(s).filter(([,t])=>t!==void 0&&t!=="").map(([t,e])=>`${t}:${String(e)}`);class A{constructor(){n(this,"client");this.client=new S.StatsD({prefix:y,errorHandler:()=>{},cacheDns:!0})}increment(t,e){this.client.increment(t,1,d(e))}histogram(t,e,i){this.client.histogram(t,e,d(i))}async close(){await new Promise(t=>{this.client.close(()=>t())})}}const M=()=>new A,D="eu-west-3",U={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"},C={working:"staging",production:"prod"};class O{constructor(t){n(this,"environment");n(this,"client");n(this,"queueUrl");this.environment=t;const e=C[t]??t,i=U[e];if(!i)throw new Error(`audit-logs SDK: no SQS queue URL configured for environment "${t}"`);this.queueUrl=i,this.client=new m.SQSClient({region:D})}async create(t){await this.client.send(new m.SendMessageCommand({QueueUrl:this.queueUrl,MessageBody:JSON.stringify(t)}))}}class N{constructor(t,e={}){n(this,"params");n(this,"transport");n(this,"logger");n(this,"metrics");this.params=t,this.transport=e.transport??new O(t.environment),this.logger=e.logger??q(t.service,t.environment),this.metrics=e.metrics??M()}async log({scope:t,account:e,...i}){const h=f.v4(),{environment:c,service:g}=this.params,r={...i,...e,service:g,id:h,environment:c,...t&&{scope:t}},a={service:g,environment:c,namespace:r.namespace,event:r.event,target:r.target},l=Date.now();try{await this.transport.create(r),this.metrics.increment("sent",a),this.metrics.histogram("send_duration_ms",Date.now()-l,a),this.logger.debug("audit-log sent",{id:r.id,event:r.event,target:r.target})}catch(w){this.metrics.increment("send_failed",a),this.metrics.histogram("send_duration_ms",Date.now()-l,a);const u=w.message;try{this.logger.error("audit-log write failed",{audit_log:r,error:u})}catch{this.metrics.increment("serialization_failed",a);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=N;
|
package/dist/index.mjs
CHANGED
|
@@ -1,80 +1,132 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { v4 as
|
|
5
|
-
import {
|
|
6
|
-
|
|
1
|
+
var p = Object.defineProperty;
|
|
2
|
+
var w = (s, t, e) => t in s ? p(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
|
|
3
|
+
var i = (s, t, e) => (w(s, typeof t != "symbol" ? t + "" : t, e), e);
|
|
4
|
+
import { v4 as v } from "uuid";
|
|
5
|
+
import { createLogger as f, format as a, transports as E } from "winston";
|
|
6
|
+
import { StatsD as _ } from "hot-shots";
|
|
7
|
+
import { SQSClient as S, SendMessageCommand as L } from "@aws-sdk/client-sqs";
|
|
8
|
+
const y = "audit-logs", A = "@payfit/audit-log", D = () => {
|
|
9
|
+
const s = process.env.LOG_LEVEL;
|
|
10
|
+
return s && s.trim() !== "" ? s.trim() : "info";
|
|
11
|
+
}, M = (s, t) => f({
|
|
12
|
+
level: D(),
|
|
13
|
+
silent: process.env.NODE_ENV === "test",
|
|
14
|
+
exitOnError: !1,
|
|
15
|
+
defaultMeta: {
|
|
16
|
+
namespace: y,
|
|
17
|
+
sdk: A,
|
|
18
|
+
service: s,
|
|
19
|
+
environment: t
|
|
20
|
+
},
|
|
21
|
+
format: a.combine(a.timestamp(), a.errors({ stack: !0 }), a.json()),
|
|
22
|
+
transports: [new E.Console()]
|
|
23
|
+
}), U = "payfit.audit-logs.", d = (s) => Object.entries(s).filter(([, t]) => t !== void 0 && t !== "").map(([t, e]) => `${t}:${String(e)}`);
|
|
24
|
+
class q {
|
|
25
|
+
constructor() {
|
|
26
|
+
i(this, "client");
|
|
27
|
+
this.client = new _({
|
|
28
|
+
prefix: U,
|
|
29
|
+
// Loss of metrics never breaks the caller — DogStatsD UDP is best-effort by design.
|
|
30
|
+
errorHandler: () => {
|
|
31
|
+
},
|
|
32
|
+
cacheDns: !0
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
increment(t, e) {
|
|
36
|
+
this.client.increment(t, 1, d(e));
|
|
37
|
+
}
|
|
38
|
+
histogram(t, e, n) {
|
|
39
|
+
this.client.histogram(t, e, d(n));
|
|
40
|
+
}
|
|
41
|
+
async close() {
|
|
42
|
+
await new Promise((t) => {
|
|
43
|
+
this.client.close(() => t());
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const C = () => new q(), N = "eu-west-3", O = {
|
|
7
48
|
dev: "https://sqs.eu-west-3.amazonaws.com/533547282673/audit-logs-ingest",
|
|
8
49
|
staging: "https://sqs.eu-west-3.amazonaws.com/589883667243/audit-logs-ingest",
|
|
9
50
|
prod: "https://sqs.eu-west-3.amazonaws.com/614948436281/audit-logs-ingest"
|
|
10
|
-
},
|
|
51
|
+
}, z = {
|
|
11
52
|
working: "staging",
|
|
12
53
|
production: "prod"
|
|
13
54
|
};
|
|
14
|
-
class
|
|
15
|
-
constructor(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
this.environment =
|
|
20
|
-
const
|
|
21
|
-
if (!
|
|
22
|
-
throw new Error(`audit-logs SDK: no SQS queue URL configured for environment "${
|
|
23
|
-
this.queueUrl =
|
|
55
|
+
class R {
|
|
56
|
+
constructor(t) {
|
|
57
|
+
i(this, "environment");
|
|
58
|
+
i(this, "client");
|
|
59
|
+
i(this, "queueUrl");
|
|
60
|
+
this.environment = t;
|
|
61
|
+
const e = z[t] ?? t, n = O[e];
|
|
62
|
+
if (!n)
|
|
63
|
+
throw new Error(`audit-logs SDK: no SQS queue URL configured for environment "${t}"`);
|
|
64
|
+
this.queueUrl = n, this.client = new S({ region: N });
|
|
24
65
|
}
|
|
25
|
-
async create(
|
|
26
|
-
await this.client.send(new
|
|
66
|
+
async create(t) {
|
|
67
|
+
await this.client.send(new L({
|
|
27
68
|
QueueUrl: this.queueUrl,
|
|
28
|
-
MessageBody: JSON.stringify(
|
|
69
|
+
MessageBody: JSON.stringify(t)
|
|
29
70
|
}));
|
|
30
71
|
}
|
|
31
72
|
}
|
|
32
|
-
class
|
|
33
|
-
constructor(e) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
this
|
|
73
|
+
class x {
|
|
74
|
+
constructor(t, e = {}) {
|
|
75
|
+
i(this, "params");
|
|
76
|
+
i(this, "transport");
|
|
77
|
+
i(this, "logger");
|
|
78
|
+
i(this, "metrics");
|
|
79
|
+
this.params = t, this.transport = e.transport ?? new R(t.environment), this.logger = e.logger ?? M(t.service, t.environment), this.metrics = e.metrics ?? C();
|
|
37
80
|
}
|
|
38
|
-
async log({ scope:
|
|
39
|
-
const
|
|
40
|
-
...
|
|
41
|
-
...
|
|
81
|
+
async log({ scope: t, account: e, ...n }) {
|
|
82
|
+
const u = v(), { environment: c, service: g } = this.params, r = {
|
|
83
|
+
...n,
|
|
84
|
+
...e,
|
|
85
|
+
service: g,
|
|
86
|
+
id: u,
|
|
87
|
+
environment: c,
|
|
88
|
+
...t && { scope: t }
|
|
89
|
+
}, o = {
|
|
42
90
|
service: g,
|
|
43
|
-
id: i,
|
|
44
91
|
environment: c,
|
|
45
|
-
|
|
46
|
-
|
|
92
|
+
namespace: r.namespace,
|
|
93
|
+
event: r.event,
|
|
94
|
+
target: r.target
|
|
95
|
+
}, l = Date.now();
|
|
47
96
|
try {
|
|
48
|
-
await this.transport.create(
|
|
49
|
-
|
|
50
|
-
|
|
97
|
+
await this.transport.create(r), this.metrics.increment("sent", o), this.metrics.histogram("send_duration_ms", Date.now() - l, o), this.logger.debug("audit-log sent", {
|
|
98
|
+
id: r.id,
|
|
99
|
+
event: r.event,
|
|
100
|
+
target: r.target
|
|
101
|
+
});
|
|
102
|
+
} catch (h) {
|
|
103
|
+
this.metrics.increment("send_failed", o), this.metrics.histogram("send_duration_ms", Date.now() - l, o);
|
|
104
|
+
const m = h.message;
|
|
51
105
|
try {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
audit_log: s,
|
|
57
|
-
error: n
|
|
58
|
-
}));
|
|
106
|
+
this.logger.error("audit-log write failed", {
|
|
107
|
+
audit_log: r,
|
|
108
|
+
error: m
|
|
109
|
+
});
|
|
59
110
|
} catch {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
111
|
+
this.metrics.increment("serialization_failed", o);
|
|
112
|
+
try {
|
|
113
|
+
this.logger.error("audit-log write failed (serialization failed)", {
|
|
114
|
+
audit_log_meta: {
|
|
115
|
+
id: r.id,
|
|
116
|
+
service: r.service,
|
|
117
|
+
environment: r.environment,
|
|
118
|
+
namespace: r.namespace,
|
|
119
|
+
event: r.event,
|
|
120
|
+
target: r.target
|
|
121
|
+
},
|
|
122
|
+
error: m
|
|
123
|
+
});
|
|
124
|
+
} catch {
|
|
125
|
+
}
|
|
74
126
|
}
|
|
75
127
|
}
|
|
76
128
|
}
|
|
77
129
|
}
|
|
78
130
|
export {
|
|
79
|
-
|
|
131
|
+
x as AuditLogger
|
|
80
132
|
};
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const METRIC_PREFIX = "payfit.audit-logs.";
|
|
2
|
+
export type MetricName = 'sent' | 'send_failed' | 'serialization_failed' | 'send_duration_ms';
|
|
3
|
+
export interface MetricTags {
|
|
4
|
+
service: string;
|
|
5
|
+
environment: string;
|
|
6
|
+
namespace?: string;
|
|
7
|
+
event?: string;
|
|
8
|
+
target?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface IMetricsClient {
|
|
11
|
+
increment(name: MetricName, tags: MetricTags): void;
|
|
12
|
+
histogram(name: MetricName, value: number, tags: MetricTags): void;
|
|
13
|
+
close(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare const createMetricsClient: () => IMetricsClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payfit/audit-log",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.10.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/PayFit/audit-logs.git",
|
|
@@ -27,8 +27,10 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@aws-sdk/client-sqs": "^3.600.0",
|
|
29
29
|
"axios": "^1.0.0",
|
|
30
|
+
"hot-shots": "^11.0.0",
|
|
30
31
|
"lodash": "^4.17.20",
|
|
31
|
-
"uuid": "^9.0.0"
|
|
32
|
+
"uuid": "^9.0.0",
|
|
33
|
+
"winston": "^3.13.0"
|
|
32
34
|
},
|
|
33
35
|
"devDependencies": {
|
|
34
36
|
"@openapitools/openapi-generator-cli": "2.7.0",
|