@pallasoft/ps-utilities 2.20.0 → 2.22.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.
Files changed (40) hide show
  1. package/dist/client/http-service.d.ts +1 -0
  2. package/dist/client/http-service.js +1 -1
  3. package/dist/edge-logs/edge-log-level.d.ts +5 -0
  4. package/dist/edge-logs/edge-log-level.js +9 -0
  5. package/dist/edge-logs/edge-logs-config.d.ts +30 -0
  6. package/dist/edge-logs/edge-logs-config.js +35 -0
  7. package/dist/edge-logs/edge-logs-service.d.ts +22 -0
  8. package/dist/edge-logs/edge-logs-service.js +208 -0
  9. package/dist/edge-logs/index.d.ts +11 -0
  10. package/dist/edge-logs/index.js +19 -0
  11. package/dist/esm/client/http-service.js +1 -1
  12. package/dist/esm/edge-logs/edge-log-level.js +6 -0
  13. package/dist/esm/edge-logs/edge-logs-config.js +31 -0
  14. package/dist/esm/edge-logs/edge-logs-service.js +149 -0
  15. package/dist/esm/edge-logs/index.js +3 -0
  16. package/dist/esm/models/edge-log-attribute-value.js +1 -0
  17. package/dist/esm/models/edge-log-attribute.js +1 -0
  18. package/dist/esm/models/edge-log-entry.js +1 -0
  19. package/dist/esm/models/edge-log-options.js +1 -0
  20. package/dist/esm/models/edge-log-payload.js +1 -0
  21. package/dist/esm/models/edge-log-record.js +1 -0
  22. package/dist/esm/models/edge-log-resource-logs.js +1 -0
  23. package/dist/esm/models/edge-log-scope-logs.js +1 -0
  24. package/dist/models/edge-log-attribute-value.d.ts +6 -0
  25. package/dist/models/edge-log-attribute-value.js +2 -0
  26. package/dist/models/edge-log-attribute.d.ts +5 -0
  27. package/dist/models/edge-log-attribute.js +2 -0
  28. package/dist/models/edge-log-entry.d.ts +7 -0
  29. package/dist/models/edge-log-entry.js +2 -0
  30. package/dist/models/edge-log-options.d.ts +8 -0
  31. package/dist/models/edge-log-options.js +2 -0
  32. package/dist/models/edge-log-payload.d.ts +4 -0
  33. package/dist/models/edge-log-payload.js +2 -0
  34. package/dist/models/edge-log-record.d.ts +9 -0
  35. package/dist/models/edge-log-record.js +2 -0
  36. package/dist/models/edge-log-resource-logs.d.ts +8 -0
  37. package/dist/models/edge-log-resource-logs.js +2 -0
  38. package/dist/models/edge-log-scope-logs.d.ts +7 -0
  39. package/dist/models/edge-log-scope-logs.js +2 -0
  40. package/package.json +10 -1
@@ -7,6 +7,7 @@ export interface CreateApiClientOptions {
7
7
  export interface PsHttpRequestConfig {
8
8
  headers?: Record<string, string>;
9
9
  responseType?: 'arraybuffer' | 'json' | 'stream' | 'text';
10
+ signal?: AbortSignal;
10
11
  }
11
12
  export interface PsHttpResponse<T> {
12
13
  data: T;
@@ -71,7 +71,7 @@ var HttpService = /** @class */ (function () {
71
71
  if (config === null || config === void 0 ? void 0 : config.headers)
72
72
  Object.assign(headers, config.headers);
73
73
  body = data === undefined ? undefined : sendsBinaryBody ? data : JSON.stringify(data);
74
- return [4 /*yield*/, fetch(fullUrl, { method: method, headers: headers, body: body })];
74
+ return [4 /*yield*/, fetch(fullUrl, { method: method, headers: headers, body: body, signal: config === null || config === void 0 ? void 0 : config.signal })];
75
75
  case 1:
76
76
  response = _b.sent();
77
77
  if ((config === null || config === void 0 ? void 0 : config.responseType) === 'stream' && response.ok)
@@ -0,0 +1,5 @@
1
+ export declare enum EdgeLogLevel {
2
+ Info = "INFO",
3
+ Warn = "WARN",
4
+ Error = "ERROR"
5
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EdgeLogLevel = void 0;
4
+ var EdgeLogLevel;
5
+ (function (EdgeLogLevel) {
6
+ EdgeLogLevel["Info"] = "INFO";
7
+ EdgeLogLevel["Warn"] = "WARN";
8
+ EdgeLogLevel["Error"] = "ERROR";
9
+ })(EdgeLogLevel || (exports.EdgeLogLevel = EdgeLogLevel = {}));
@@ -0,0 +1,30 @@
1
+ export declare const EdgeLogsConfig: {
2
+ readonly bearerPattern: RegExp;
3
+ readonly defaultEnvironment: "development";
4
+ readonly defaultScheme: "https://";
5
+ readonly emailPattern: RegExp;
6
+ readonly flushTimeoutMilliseconds: 5000;
7
+ readonly maxBufferedEntries: 200;
8
+ readonly maxDepth: 3;
9
+ readonly maxTextLength: 2000;
10
+ readonly nanosPerMillisecondSuffix: "000000";
11
+ readonly offValues: readonly ["", "_"];
12
+ readonly queryPattern: RegExp;
13
+ readonly redactedValue: "[redacted]";
14
+ readonly resourceKeys: {
15
+ readonly environment: "deployment.environment";
16
+ readonly serviceName: "service.name";
17
+ readonly serviceNamespace: "service.namespace";
18
+ readonly serviceVersion: "service.version";
19
+ };
20
+ readonly scopeName: "ps-utilities.edge-logs";
21
+ readonly schemePattern: RegExp;
22
+ readonly sensitiveKeyPattern: RegExp;
23
+ readonly severityNumbers: {
24
+ readonly INFO: 9;
25
+ readonly WARN: 13;
26
+ readonly ERROR: 17;
27
+ };
28
+ readonly signalPath: "/v1/logs";
29
+ readonly trailingSlashesPattern: RegExp;
30
+ };
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.EdgeLogsConfig = void 0;
5
+ var edge_log_level_1 = require("./edge-log-level");
6
+ exports.EdgeLogsConfig = {
7
+ bearerPattern: /Bearer\s+[A-Za-z0-9._~+/=-]+/gi,
8
+ defaultEnvironment: 'development',
9
+ defaultScheme: 'https://',
10
+ emailPattern: /[^\s@"']+@[^\s@"']+\.[^\s@"']+/g,
11
+ flushTimeoutMilliseconds: 5000,
12
+ maxBufferedEntries: 200,
13
+ maxDepth: 3,
14
+ maxTextLength: 2000,
15
+ nanosPerMillisecondSuffix: '000000',
16
+ offValues: ['', '_'],
17
+ queryPattern: /(https?:\/\/[^\s?#"']+|\/[^\s?#"']*)\?[^\s#"']*/g,
18
+ redactedValue: '[redacted]',
19
+ resourceKeys: {
20
+ environment: 'deployment.environment',
21
+ serviceName: 'service.name',
22
+ serviceNamespace: 'service.namespace',
23
+ serviceVersion: 'service.version',
24
+ },
25
+ scopeName: 'ps-utilities.edge-logs',
26
+ schemePattern: /^[a-z][a-z0-9+.-]*:\/\//i,
27
+ sensitiveKeyPattern: /token|secret|password|passwd|authorization|cookie|credential|api[-_]?key|email|body|session|phone|header/i,
28
+ severityNumbers: (_a = {},
29
+ _a[edge_log_level_1.EdgeLogLevel.Info] = 9,
30
+ _a[edge_log_level_1.EdgeLogLevel.Warn] = 13,
31
+ _a[edge_log_level_1.EdgeLogLevel.Error] = 17,
32
+ _a),
33
+ signalPath: '/v1/logs',
34
+ trailingSlashesPattern: /\/+$/,
35
+ };
@@ -0,0 +1,22 @@
1
+ import type { EdgeLogEntry } from '../models/edge-log-entry';
2
+ import type { EdgeLogOptions } from '../models/edge-log-options';
3
+ import type { EdgeLogPayload } from '../models/edge-log-payload';
4
+ import type { EdgeLogRecord } from '../models/edge-log-record';
5
+ export declare class EdgeLogsService {
6
+ private static buffer;
7
+ static isOff(value: string | undefined): boolean;
8
+ static baseUrl(host: string | undefined): string | null;
9
+ static endpoint(host: string | undefined): string | null;
10
+ static isEnabled(options: EdgeLogOptions): boolean;
11
+ static enqueue(options: EdgeLogOptions, entry: EdgeLogEntry): boolean;
12
+ static pending(): number;
13
+ static reset(): void;
14
+ static flush(options: EdgeLogOptions): Promise<boolean>;
15
+ static payload(options: EdgeLogOptions, entries: EdgeLogEntry[]): EdgeLogPayload;
16
+ static record(entry: EdgeLogEntry): EdgeLogRecord;
17
+ static sanitize(source: Record<string, unknown>, depth?: number): Record<string, unknown>;
18
+ static text(value: string): string;
19
+ private static value;
20
+ private static attribute;
21
+ private static attributeValue;
22
+ }
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.EdgeLogsService = void 0;
40
+ var http_auth_scheme_1 = require("../common/constants/http-auth-scheme");
41
+ var http_content_type_1 = require("../common/constants/http-content-type");
42
+ var http_header_1 = require("../common/constants/http-header");
43
+ var http_method_1 = require("../common/constants/http-method");
44
+ var edge_logs_config_1 = require("./edge-logs-config");
45
+ var EdgeLogsService = /** @class */ (function () {
46
+ function EdgeLogsService() {
47
+ }
48
+ EdgeLogsService.isOff = function (value) {
49
+ if (typeof value !== 'string')
50
+ return true;
51
+ return edge_logs_config_1.EdgeLogsConfig.offValues.includes(value.trim());
52
+ };
53
+ EdgeLogsService.baseUrl = function (host) {
54
+ if (EdgeLogsService.isOff(host))
55
+ return null;
56
+ var trimmed = host.trim().replace(edge_logs_config_1.EdgeLogsConfig.trailingSlashesPattern, '');
57
+ var withScheme = edge_logs_config_1.EdgeLogsConfig.schemePattern.test(trimmed)
58
+ ? trimmed
59
+ : "".concat(edge_logs_config_1.EdgeLogsConfig.defaultScheme).concat(trimmed);
60
+ return URL.canParse(withScheme) ? withScheme : null;
61
+ };
62
+ EdgeLogsService.endpoint = function (host) {
63
+ var base = EdgeLogsService.baseUrl(host);
64
+ return base === null ? null : "".concat(base).concat(edge_logs_config_1.EdgeLogsConfig.signalPath);
65
+ };
66
+ EdgeLogsService.isEnabled = function (options) {
67
+ return EdgeLogsService.endpoint(options.host) !== null && !EdgeLogsService.isOff(options.token);
68
+ };
69
+ EdgeLogsService.enqueue = function (options, entry) {
70
+ if (!EdgeLogsService.isEnabled(options))
71
+ return false;
72
+ EdgeLogsService.buffer.push(entry);
73
+ if (EdgeLogsService.buffer.length > edge_logs_config_1.EdgeLogsConfig.maxBufferedEntries)
74
+ EdgeLogsService.buffer.shift();
75
+ return true;
76
+ };
77
+ EdgeLogsService.pending = function () {
78
+ return EdgeLogsService.buffer.length;
79
+ };
80
+ EdgeLogsService.reset = function () {
81
+ EdgeLogsService.buffer = [];
82
+ };
83
+ EdgeLogsService.flush = function (options) {
84
+ return __awaiter(this, void 0, void 0, function () {
85
+ var entries, url, controller, timer, response, _a;
86
+ var _b;
87
+ return __generator(this, function (_c) {
88
+ switch (_c.label) {
89
+ case 0:
90
+ entries = EdgeLogsService.buffer;
91
+ EdgeLogsService.buffer = [];
92
+ url = EdgeLogsService.endpoint(options.host);
93
+ if (entries.length === 0 || url === null || EdgeLogsService.isOff(options.token))
94
+ return [2 /*return*/, false];
95
+ controller = new AbortController();
96
+ timer = setTimeout(function () { return controller.abort(); }, edge_logs_config_1.EdgeLogsConfig.flushTimeoutMilliseconds);
97
+ _c.label = 1;
98
+ case 1:
99
+ _c.trys.push([1, 3, 4, 5]);
100
+ return [4 /*yield*/, fetch(url, {
101
+ body: JSON.stringify(EdgeLogsService.payload(options, entries)),
102
+ headers: (_b = {},
103
+ _b[http_header_1.HttpHeader.authorization] = "".concat(http_auth_scheme_1.HttpAuthScheme.bearerPrefix).concat(options.token.trim()),
104
+ _b[http_header_1.HttpHeader.contentType] = http_content_type_1.HttpContentType.json,
105
+ _b),
106
+ method: http_method_1.HttpMethod.Post,
107
+ signal: controller.signal,
108
+ })];
109
+ case 2:
110
+ response = _c.sent();
111
+ return [2 /*return*/, response.ok];
112
+ case 3:
113
+ _a = _c.sent();
114
+ return [2 /*return*/, false];
115
+ case 4:
116
+ clearTimeout(timer);
117
+ return [7 /*endfinally*/];
118
+ case 5: return [2 /*return*/];
119
+ }
120
+ });
121
+ });
122
+ };
123
+ EdgeLogsService.payload = function (options, entries) {
124
+ var environment = typeof options.environment === 'string' && options.environment.trim() !== ''
125
+ ? options.environment.trim()
126
+ : edge_logs_config_1.EdgeLogsConfig.defaultEnvironment;
127
+ return {
128
+ resourceLogs: [
129
+ {
130
+ resource: {
131
+ attributes: [
132
+ EdgeLogsService.attribute(edge_logs_config_1.EdgeLogsConfig.resourceKeys.serviceName, options.serviceName),
133
+ EdgeLogsService.attribute(edge_logs_config_1.EdgeLogsConfig.resourceKeys.serviceNamespace, options.serviceNamespace),
134
+ EdgeLogsService.attribute(edge_logs_config_1.EdgeLogsConfig.resourceKeys.serviceVersion, options.serviceVersion),
135
+ EdgeLogsService.attribute(edge_logs_config_1.EdgeLogsConfig.resourceKeys.environment, environment),
136
+ ],
137
+ },
138
+ scopeLogs: [
139
+ {
140
+ scope: { name: edge_logs_config_1.EdgeLogsConfig.scopeName },
141
+ logRecords: entries.map(function (entry) { return EdgeLogsService.record(entry); }),
142
+ },
143
+ ],
144
+ },
145
+ ],
146
+ };
147
+ };
148
+ EdgeLogsService.record = function (entry) {
149
+ var timestamp = typeof entry.timestamp === 'number' ? entry.timestamp : Date.now();
150
+ var attributes = EdgeLogsService.sanitize(entry.attributes === undefined ? {} : entry.attributes);
151
+ return {
152
+ attributes: Object.keys(attributes).map(function (key) {
153
+ return EdgeLogsService.attribute(key, attributes[key]);
154
+ }),
155
+ body: { stringValue: EdgeLogsService.text(entry.event) },
156
+ severityNumber: edge_logs_config_1.EdgeLogsConfig.severityNumbers[entry.level],
157
+ severityText: entry.level,
158
+ timeUnixNano: "".concat(Math.floor(timestamp)).concat(edge_logs_config_1.EdgeLogsConfig.nanosPerMillisecondSuffix),
159
+ };
160
+ };
161
+ EdgeLogsService.sanitize = function (source, depth) {
162
+ if (depth === void 0) { depth = 0; }
163
+ var result = {};
164
+ Object.keys(source).forEach(function (key) {
165
+ result[key] = edge_logs_config_1.EdgeLogsConfig.sensitiveKeyPattern.test(key)
166
+ ? edge_logs_config_1.EdgeLogsConfig.redactedValue
167
+ : EdgeLogsService.value(source[key], depth);
168
+ });
169
+ return result;
170
+ };
171
+ EdgeLogsService.text = function (value) {
172
+ return value
173
+ .replace(edge_logs_config_1.EdgeLogsConfig.bearerPattern, edge_logs_config_1.EdgeLogsConfig.redactedValue)
174
+ .replace(edge_logs_config_1.EdgeLogsConfig.emailPattern, edge_logs_config_1.EdgeLogsConfig.redactedValue)
175
+ .replace(edge_logs_config_1.EdgeLogsConfig.queryPattern, '$1')
176
+ .slice(0, edge_logs_config_1.EdgeLogsConfig.maxTextLength);
177
+ };
178
+ EdgeLogsService.value = function (value, depth) {
179
+ if (value === null || value === undefined)
180
+ return '';
181
+ if (typeof value === 'number' || typeof value === 'boolean')
182
+ return value;
183
+ if (typeof value === 'string')
184
+ return EdgeLogsService.text(value);
185
+ if (value instanceof Error)
186
+ return EdgeLogsService.text("".concat(value.name, ": ").concat(value.message));
187
+ if (depth >= edge_logs_config_1.EdgeLogsConfig.maxDepth)
188
+ return edge_logs_config_1.EdgeLogsConfig.redactedValue;
189
+ if (Array.isArray(value))
190
+ return EdgeLogsService.text(JSON.stringify(value.map(function (item) { return EdgeLogsService.value(item, depth + 1); })));
191
+ if (typeof value === 'object')
192
+ return EdgeLogsService.text(JSON.stringify(EdgeLogsService.sanitize(value, depth + 1)));
193
+ return EdgeLogsService.text(String(value));
194
+ };
195
+ EdgeLogsService.attribute = function (key, value) {
196
+ return { key: key, value: EdgeLogsService.attributeValue(value) };
197
+ };
198
+ EdgeLogsService.attributeValue = function (value) {
199
+ if (typeof value === 'boolean')
200
+ return { boolValue: value };
201
+ if (typeof value === 'number' && Number.isFinite(value))
202
+ return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };
203
+ return { stringValue: String(value) };
204
+ };
205
+ EdgeLogsService.buffer = [];
206
+ return EdgeLogsService;
207
+ }());
208
+ exports.EdgeLogsService = EdgeLogsService;
@@ -0,0 +1,11 @@
1
+ export * from './edge-log-level';
2
+ export * from './edge-logs-config';
3
+ export * from './edge-logs-service';
4
+ export type { EdgeLogAttribute } from '../models/edge-log-attribute';
5
+ export type { EdgeLogAttributeValue } from '../models/edge-log-attribute-value';
6
+ export type { EdgeLogEntry } from '../models/edge-log-entry';
7
+ export type { EdgeLogOptions } from '../models/edge-log-options';
8
+ export type { EdgeLogPayload } from '../models/edge-log-payload';
9
+ export type { EdgeLogRecord } from '../models/edge-log-record';
10
+ export type { EdgeLogResourceLogs } from '../models/edge-log-resource-logs';
11
+ export type { EdgeLogScopeLogs } from '../models/edge-log-scope-logs';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./edge-log-level"), exports);
18
+ __exportStar(require("./edge-logs-config"), exports);
19
+ __exportStar(require("./edge-logs-service"), exports);
@@ -21,7 +21,7 @@ export class HttpService {
21
21
  if (config?.headers)
22
22
  Object.assign(headers, config.headers);
23
23
  const body = data === undefined ? undefined : sendsBinaryBody ? data : JSON.stringify(data);
24
- const response = await fetch(fullUrl, { method, headers, body });
24
+ const response = await fetch(fullUrl, { method, headers, body, signal: config?.signal });
25
25
  if (config?.responseType === 'stream' && response.ok)
26
26
  return { data: response.body, headers: response.headers, status: response.status };
27
27
  const responseData = await (config?.responseType === 'arraybuffer'
@@ -0,0 +1,6 @@
1
+ export var EdgeLogLevel;
2
+ (function (EdgeLogLevel) {
3
+ EdgeLogLevel["Info"] = "INFO";
4
+ EdgeLogLevel["Warn"] = "WARN";
5
+ EdgeLogLevel["Error"] = "ERROR";
6
+ })(EdgeLogLevel || (EdgeLogLevel = {}));
@@ -0,0 +1,31 @@
1
+ import { EdgeLogLevel } from './edge-log-level.js';
2
+ export const EdgeLogsConfig = {
3
+ bearerPattern: /Bearer\s+[A-Za-z0-9._~+/=-]+/gi,
4
+ defaultEnvironment: 'development',
5
+ defaultScheme: 'https://',
6
+ emailPattern: /[^\s@"']+@[^\s@"']+\.[^\s@"']+/g,
7
+ flushTimeoutMilliseconds: 5000,
8
+ maxBufferedEntries: 200,
9
+ maxDepth: 3,
10
+ maxTextLength: 2000,
11
+ nanosPerMillisecondSuffix: '000000',
12
+ offValues: ['', '_'],
13
+ queryPattern: /(https?:\/\/[^\s?#"']+|\/[^\s?#"']*)\?[^\s#"']*/g,
14
+ redactedValue: '[redacted]',
15
+ resourceKeys: {
16
+ environment: 'deployment.environment',
17
+ serviceName: 'service.name',
18
+ serviceNamespace: 'service.namespace',
19
+ serviceVersion: 'service.version',
20
+ },
21
+ scopeName: 'ps-utilities.edge-logs',
22
+ schemePattern: /^[a-z][a-z0-9+.-]*:\/\//i,
23
+ sensitiveKeyPattern: /token|secret|password|passwd|authorization|cookie|credential|api[-_]?key|email|body|session|phone|header/i,
24
+ severityNumbers: {
25
+ [EdgeLogLevel.Info]: 9,
26
+ [EdgeLogLevel.Warn]: 13,
27
+ [EdgeLogLevel.Error]: 17,
28
+ },
29
+ signalPath: '/v1/logs',
30
+ trailingSlashesPattern: /\/+$/,
31
+ };
@@ -0,0 +1,149 @@
1
+ import { HttpAuthScheme } from '../common/constants/http-auth-scheme.js';
2
+ import { HttpContentType } from '../common/constants/http-content-type.js';
3
+ import { HttpHeader } from '../common/constants/http-header.js';
4
+ import { HttpMethod } from '../common/constants/http-method.js';
5
+ import { EdgeLogsConfig } from './edge-logs-config.js';
6
+ export class EdgeLogsService {
7
+ static isOff(value) {
8
+ if (typeof value !== 'string')
9
+ return true;
10
+ return EdgeLogsConfig.offValues.includes(value.trim());
11
+ }
12
+ static baseUrl(host) {
13
+ if (EdgeLogsService.isOff(host))
14
+ return null;
15
+ const trimmed = host.trim().replace(EdgeLogsConfig.trailingSlashesPattern, '');
16
+ const withScheme = EdgeLogsConfig.schemePattern.test(trimmed)
17
+ ? trimmed
18
+ : `${EdgeLogsConfig.defaultScheme}${trimmed}`;
19
+ return URL.canParse(withScheme) ? withScheme : null;
20
+ }
21
+ static endpoint(host) {
22
+ const base = EdgeLogsService.baseUrl(host);
23
+ return base === null ? null : `${base}${EdgeLogsConfig.signalPath}`;
24
+ }
25
+ static isEnabled(options) {
26
+ return EdgeLogsService.endpoint(options.host) !== null && !EdgeLogsService.isOff(options.token);
27
+ }
28
+ static enqueue(options, entry) {
29
+ if (!EdgeLogsService.isEnabled(options))
30
+ return false;
31
+ EdgeLogsService.buffer.push(entry);
32
+ if (EdgeLogsService.buffer.length > EdgeLogsConfig.maxBufferedEntries)
33
+ EdgeLogsService.buffer.shift();
34
+ return true;
35
+ }
36
+ static pending() {
37
+ return EdgeLogsService.buffer.length;
38
+ }
39
+ static reset() {
40
+ EdgeLogsService.buffer = [];
41
+ }
42
+ static async flush(options) {
43
+ const entries = EdgeLogsService.buffer;
44
+ EdgeLogsService.buffer = [];
45
+ const url = EdgeLogsService.endpoint(options.host);
46
+ if (entries.length === 0 || url === null || EdgeLogsService.isOff(options.token))
47
+ return false;
48
+ const controller = new AbortController();
49
+ const timer = setTimeout(() => controller.abort(), EdgeLogsConfig.flushTimeoutMilliseconds);
50
+ try {
51
+ const response = await fetch(url, {
52
+ body: JSON.stringify(EdgeLogsService.payload(options, entries)),
53
+ headers: {
54
+ [HttpHeader.authorization]: `${HttpAuthScheme.bearerPrefix}${options.token.trim()}`,
55
+ [HttpHeader.contentType]: HttpContentType.json,
56
+ },
57
+ method: HttpMethod.Post,
58
+ signal: controller.signal,
59
+ });
60
+ return response.ok;
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ finally {
66
+ clearTimeout(timer);
67
+ }
68
+ }
69
+ static payload(options, entries) {
70
+ const environment = typeof options.environment === 'string' && options.environment.trim() !== ''
71
+ ? options.environment.trim()
72
+ : EdgeLogsConfig.defaultEnvironment;
73
+ return {
74
+ resourceLogs: [
75
+ {
76
+ resource: {
77
+ attributes: [
78
+ EdgeLogsService.attribute(EdgeLogsConfig.resourceKeys.serviceName, options.serviceName),
79
+ EdgeLogsService.attribute(EdgeLogsConfig.resourceKeys.serviceNamespace, options.serviceNamespace),
80
+ EdgeLogsService.attribute(EdgeLogsConfig.resourceKeys.serviceVersion, options.serviceVersion),
81
+ EdgeLogsService.attribute(EdgeLogsConfig.resourceKeys.environment, environment),
82
+ ],
83
+ },
84
+ scopeLogs: [
85
+ {
86
+ scope: { name: EdgeLogsConfig.scopeName },
87
+ logRecords: entries.map((entry) => EdgeLogsService.record(entry)),
88
+ },
89
+ ],
90
+ },
91
+ ],
92
+ };
93
+ }
94
+ static record(entry) {
95
+ const timestamp = typeof entry.timestamp === 'number' ? entry.timestamp : Date.now();
96
+ const attributes = EdgeLogsService.sanitize(entry.attributes === undefined ? {} : entry.attributes);
97
+ return {
98
+ attributes: Object.keys(attributes).map((key) => EdgeLogsService.attribute(key, attributes[key])),
99
+ body: { stringValue: EdgeLogsService.text(entry.event) },
100
+ severityNumber: EdgeLogsConfig.severityNumbers[entry.level],
101
+ severityText: entry.level,
102
+ timeUnixNano: `${Math.floor(timestamp)}${EdgeLogsConfig.nanosPerMillisecondSuffix}`,
103
+ };
104
+ }
105
+ static sanitize(source, depth = 0) {
106
+ const result = {};
107
+ Object.keys(source).forEach((key) => {
108
+ result[key] = EdgeLogsConfig.sensitiveKeyPattern.test(key)
109
+ ? EdgeLogsConfig.redactedValue
110
+ : EdgeLogsService.value(source[key], depth);
111
+ });
112
+ return result;
113
+ }
114
+ static text(value) {
115
+ return value
116
+ .replace(EdgeLogsConfig.bearerPattern, EdgeLogsConfig.redactedValue)
117
+ .replace(EdgeLogsConfig.emailPattern, EdgeLogsConfig.redactedValue)
118
+ .replace(EdgeLogsConfig.queryPattern, '$1')
119
+ .slice(0, EdgeLogsConfig.maxTextLength);
120
+ }
121
+ static value(value, depth) {
122
+ if (value === null || value === undefined)
123
+ return '';
124
+ if (typeof value === 'number' || typeof value === 'boolean')
125
+ return value;
126
+ if (typeof value === 'string')
127
+ return EdgeLogsService.text(value);
128
+ if (value instanceof Error)
129
+ return EdgeLogsService.text(`${value.name}: ${value.message}`);
130
+ if (depth >= EdgeLogsConfig.maxDepth)
131
+ return EdgeLogsConfig.redactedValue;
132
+ if (Array.isArray(value))
133
+ return EdgeLogsService.text(JSON.stringify(value.map((item) => EdgeLogsService.value(item, depth + 1))));
134
+ if (typeof value === 'object')
135
+ return EdgeLogsService.text(JSON.stringify(EdgeLogsService.sanitize(value, depth + 1)));
136
+ return EdgeLogsService.text(String(value));
137
+ }
138
+ static attribute(key, value) {
139
+ return { key, value: EdgeLogsService.attributeValue(value) };
140
+ }
141
+ static attributeValue(value) {
142
+ if (typeof value === 'boolean')
143
+ return { boolValue: value };
144
+ if (typeof value === 'number' && Number.isFinite(value))
145
+ return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };
146
+ return { stringValue: String(value) };
147
+ }
148
+ }
149
+ EdgeLogsService.buffer = [];
@@ -0,0 +1,3 @@
1
+ export * from './edge-log-level.js';
2
+ export * from './edge-logs-config.js';
3
+ export * from './edge-logs-service.js';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ export interface EdgeLogAttributeValue {
2
+ stringValue?: string;
3
+ intValue?: string;
4
+ doubleValue?: number;
5
+ boolValue?: boolean;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ import { EdgeLogAttributeValue } from './edge-log-attribute-value';
2
+ export interface EdgeLogAttribute {
3
+ key: string;
4
+ value: EdgeLogAttributeValue;
5
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ import { EdgeLogLevel } from '../edge-logs/edge-log-level';
2
+ export interface EdgeLogEntry {
3
+ level: EdgeLogLevel;
4
+ event: string;
5
+ attributes?: Record<string, unknown>;
6
+ timestamp?: number;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ export interface EdgeLogOptions {
2
+ host: string | undefined;
3
+ token: string | undefined;
4
+ serviceName: string;
5
+ serviceNamespace: string;
6
+ serviceVersion: string;
7
+ environment: string | undefined;
8
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ import { EdgeLogResourceLogs } from './edge-log-resource-logs';
2
+ export interface EdgeLogPayload {
3
+ resourceLogs: EdgeLogResourceLogs[];
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ import { EdgeLogAttribute } from './edge-log-attribute';
2
+ import { EdgeLogAttributeValue } from './edge-log-attribute-value';
3
+ export interface EdgeLogRecord {
4
+ timeUnixNano: string;
5
+ severityNumber: number;
6
+ severityText: string;
7
+ body: EdgeLogAttributeValue;
8
+ attributes: EdgeLogAttribute[];
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ import { EdgeLogAttribute } from './edge-log-attribute';
2
+ import { EdgeLogScopeLogs } from './edge-log-scope-logs';
3
+ export interface EdgeLogResourceLogs {
4
+ resource: {
5
+ attributes: EdgeLogAttribute[];
6
+ };
7
+ scopeLogs: EdgeLogScopeLogs[];
8
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ import { EdgeLogRecord } from './edge-log-record';
2
+ export interface EdgeLogScopeLogs {
3
+ scope: {
4
+ name: string;
5
+ };
6
+ logRecords: EdgeLogRecord[];
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pallasoft/ps-utilities",
3
- "version": "2.20.0",
3
+ "version": "2.22.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -19,6 +19,12 @@
19
19
  "require": "./dist/server/index.js",
20
20
  "default": "./dist/server/index.js"
21
21
  },
22
+ "./edge-logs": {
23
+ "types": "./dist/edge-logs/index.d.ts",
24
+ "module": "./dist/esm/edge-logs/index.js",
25
+ "require": "./dist/edge-logs/index.js",
26
+ "default": "./dist/edge-logs/index.js"
27
+ },
22
28
  "./build": {
23
29
  "types": "./dist/build/index.d.ts",
24
30
  "require": "./dist/build/index.js",
@@ -109,6 +115,9 @@
109
115
  },
110
116
  "typesVersions": {
111
117
  "*": {
118
+ "edge-logs": [
119
+ "dist/edge-logs/index.d.ts"
120
+ ],
112
121
  "server": [
113
122
  "dist/server/index.d.ts"
114
123
  ],