@payfit/audit-log 3.7.1 → 3.9.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 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
- constructor(params: IAuditLoggerInitialization);
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 d=Object.defineProperty;var m=(r,e,t)=>e in r?d(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var n=(r,e,t)=>(m(r,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("uuid"),i=require("@aws-sdk/client-sqs"),p="eu-west-3",S={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"},h={working:"staging",production:"prod"};class v{constructor(e){n(this,"environment");n(this,"client");n(this,"queueUrl");this.environment=e;const t=h[e]??e,o=S[t];if(!o)throw new Error(`audit-logs SDK: no SQS queue URL configured for environment "${e}"`);this.queueUrl=o,this.client=new i.SQSClient({region:p})}async create(e){await this.client.send(new i.SendMessageCommand({QueueUrl:this.queueUrl,MessageBody:JSON.stringify(e)}))}}class q{constructor(e){n(this,"params");n(this,"transport");this.params=e,this.transport=new v(e.environment)}async log({scope:e,account:t,...o}){const c=w.v4(),{environment:u,service:g}=this.params,s={...o,...t,service:g,id:c,environment:u,...e&&{scope:e}};try{await this.transport.create(s)}catch(l){const a=l.message;try{console.error(JSON.stringify({status:"error",namespace:"audit-logs",message:"audit-log write failed",audit_log:s,error:a}))}catch{console.error(JSON.stringify({status:"error",namespace:"audit-logs",message:"audit-log write failed (serialization failed)",audit_log_meta:{id:s.id,service:s.service,environment:s.environment,namespace:s.namespace,event:s.event,target:s.target},error:a}))}}}}exports.AuditLogger=q;
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 l = Object.defineProperty;
2
- var d = (r, e, t) => e in r ? l(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
3
- var o = (r, e, t) => (d(r, typeof e != "symbol" ? e + "" : e, t), t);
4
- import { v4 as m } from "uuid";
5
- import { SQSClient as p, SendMessageCommand as w } from "@aws-sdk/client-sqs";
6
- const h = "eu-west-3", S = {
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
- }, v = {
51
+ }, z = {
11
52
  working: "staging",
12
53
  production: "prod"
13
54
  };
14
- class f {
15
- constructor(e) {
16
- o(this, "environment");
17
- o(this, "client");
18
- o(this, "queueUrl");
19
- this.environment = e;
20
- const t = v[e] ?? e, a = S[t];
21
- if (!a)
22
- throw new Error(`audit-logs SDK: no SQS queue URL configured for environment "${e}"`);
23
- this.queueUrl = a, this.client = new p({ region: h });
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(e) {
26
- await this.client.send(new w({
66
+ async create(t) {
67
+ await this.client.send(new L({
27
68
  QueueUrl: this.queueUrl,
28
- MessageBody: JSON.stringify(e)
69
+ MessageBody: JSON.stringify(t)
29
70
  }));
30
71
  }
31
72
  }
32
- class E {
33
- constructor(e) {
34
- o(this, "params");
35
- o(this, "transport");
36
- this.params = e, this.transport = new f(e.environment);
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: e, account: t, ...a }) {
39
- const i = m(), { environment: c, service: g } = this.params, s = {
40
- ...a,
41
- ...t,
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
- ...e && { scope: e }
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(s);
49
- } catch (u) {
50
- const n = u.message;
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
- console.error(JSON.stringify({
53
- status: "error",
54
- namespace: "audit-logs",
55
- message: "audit-log write failed",
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
- console.error(JSON.stringify({
61
- status: "error",
62
- namespace: "audit-logs",
63
- message: "audit-log write failed (serialization failed)",
64
- audit_log_meta: {
65
- id: s.id,
66
- service: s.service,
67
- environment: s.environment,
68
- namespace: s.namespace,
69
- event: s.event,
70
- target: s.target
71
- },
72
- error: n
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
- E as AuditLogger
131
+ x as AuditLogger
80
132
  };
@@ -0,0 +1,2 @@
1
+ import { type Logger } from 'winston';
2
+ export declare const createSdkLogger: (service: string, environment: string) => Logger;
@@ -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.7.1",
3
+ "version": "3.9.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",