@zintrust/trace 0.4.83 → 0.4.84
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/build-manifest.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zintrust/trace",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"buildDate": "2026-04-08T17:
|
|
3
|
+
"version": "0.4.84",
|
|
4
|
+
"buildDate": "2026-04-08T17:51:22.444Z",
|
|
5
5
|
"buildEnvironment": {
|
|
6
6
|
"node": "v22.22.1",
|
|
7
7
|
"platform": "darwin",
|
|
8
8
|
"arch": "arm64"
|
|
9
9
|
},
|
|
10
10
|
"git": {
|
|
11
|
-
"commit": "
|
|
11
|
+
"commit": "d4c31a0d",
|
|
12
12
|
"branch": "release"
|
|
13
13
|
},
|
|
14
14
|
"package": {
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
},
|
|
23
23
|
"files": {
|
|
24
24
|
"build-manifest.json": {
|
|
25
|
-
"size":
|
|
26
|
-
"sha256": "
|
|
25
|
+
"size": 14440,
|
|
26
|
+
"sha256": "04b7ac17fd2a9abf208db4df6218eea2f97a4ce4e1dc6ce8d826036924e7ab84"
|
|
27
27
|
},
|
|
28
28
|
"cli-register.d.ts": {
|
|
29
29
|
"size": 255,
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
},
|
|
80
80
|
"index.js": {
|
|
81
81
|
"size": 3255,
|
|
82
|
-
"sha256": "
|
|
82
|
+
"sha256": "f95401dc3b5ad76937e32978770c9568cf90e453bb1e77d0ecc8611e664b5ce0"
|
|
83
83
|
},
|
|
84
84
|
"migrations/20260331000001_create_zin_trace_entries_table.d.ts": {
|
|
85
85
|
"size": 304,
|
|
@@ -174,8 +174,8 @@
|
|
|
174
174
|
"sha256": "5f49df97a830ad895653fa4a18b3a1b31ca4a5066d6f8150ee02dca013e16397"
|
|
175
175
|
},
|
|
176
176
|
"storage/TraceWriteDiagnostics.js": {
|
|
177
|
-
"size":
|
|
178
|
-
"sha256": "
|
|
177
|
+
"size": 6714,
|
|
178
|
+
"sha256": "398b2cb74e2e7278c6a3b5d29537e7a95581e0a1cb9fb5831f7ff13ac70805e4"
|
|
179
179
|
},
|
|
180
180
|
"storage/index.d.ts": {
|
|
181
181
|
"size": 100,
|
|
@@ -6,19 +6,98 @@ const diagnosticsState = {
|
|
|
6
6
|
lastLoggedAtByFingerprint: new Map(),
|
|
7
7
|
totalFailures: 0,
|
|
8
8
|
};
|
|
9
|
+
const asRecord = (value) => {
|
|
10
|
+
if (value === null || typeof value !== 'object')
|
|
11
|
+
return null;
|
|
12
|
+
return value;
|
|
13
|
+
};
|
|
14
|
+
const getAttachedErrorDetails = (error) => {
|
|
15
|
+
if (error instanceof Error && 'details' in error) {
|
|
16
|
+
const details = error.details;
|
|
17
|
+
if (details !== undefined)
|
|
18
|
+
return details;
|
|
19
|
+
}
|
|
20
|
+
const record = asRecord(error);
|
|
21
|
+
return record?.['details'];
|
|
22
|
+
};
|
|
23
|
+
const getTextValue = (value) => {
|
|
24
|
+
if (typeof value !== 'string')
|
|
25
|
+
return null;
|
|
26
|
+
const trimmed = value.trim();
|
|
27
|
+
return trimmed === '' ? null : trimmed;
|
|
28
|
+
};
|
|
29
|
+
const describeBodyDetails = (body) => {
|
|
30
|
+
const code = getTextValue(body['code']);
|
|
31
|
+
const message = getTextValue(body['message']);
|
|
32
|
+
if (code !== null && message !== null)
|
|
33
|
+
return `${code}: ${message}`;
|
|
34
|
+
if (code !== null)
|
|
35
|
+
return code;
|
|
36
|
+
if (message !== null)
|
|
37
|
+
return message;
|
|
38
|
+
return null;
|
|
39
|
+
};
|
|
40
|
+
const describeRecordDetails = (record) => {
|
|
41
|
+
const body = asRecord(record['body']);
|
|
42
|
+
if (body !== null) {
|
|
43
|
+
const describedBody = describeBodyDetails(body);
|
|
44
|
+
if (describedBody !== null)
|
|
45
|
+
return describedBody;
|
|
46
|
+
}
|
|
47
|
+
const nested = describeErrorDetails(record['details']);
|
|
48
|
+
if (nested !== null)
|
|
49
|
+
return nested;
|
|
50
|
+
const message = getTextValue(record['message']);
|
|
51
|
+
if (message !== null)
|
|
52
|
+
return message;
|
|
53
|
+
const code = getTextValue(record['code']);
|
|
54
|
+
if (code !== null)
|
|
55
|
+
return code;
|
|
56
|
+
return null;
|
|
57
|
+
};
|
|
58
|
+
const describeErrorDetails = (details) => {
|
|
59
|
+
const text = getTextValue(details);
|
|
60
|
+
if (text !== null)
|
|
61
|
+
return text;
|
|
62
|
+
const record = asRecord(details);
|
|
63
|
+
if (record === null)
|
|
64
|
+
return null;
|
|
65
|
+
return describeRecordDetails(record);
|
|
66
|
+
};
|
|
67
|
+
const withOptionalDetail = (context, errorDetails) => {
|
|
68
|
+
if (errorDetails === undefined)
|
|
69
|
+
return context;
|
|
70
|
+
return { ...context, errorDetails };
|
|
71
|
+
};
|
|
9
72
|
const getErrorMessage = (error) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
73
|
+
let baseMessage = '';
|
|
74
|
+
if (error instanceof Error && error.message.trim() !== '') {
|
|
75
|
+
baseMessage = error.message;
|
|
76
|
+
}
|
|
77
|
+
else if (typeof error === 'string' && error.trim() !== '') {
|
|
78
|
+
baseMessage = error;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
try {
|
|
82
|
+
const serialized = JSON.stringify(error);
|
|
83
|
+
if (typeof serialized === 'string' && serialized !== '')
|
|
84
|
+
baseMessage = serialized;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// ignore serialization failures
|
|
88
|
+
}
|
|
18
89
|
}
|
|
19
|
-
|
|
20
|
-
|
|
90
|
+
const detailsSummary = describeErrorDetails(getAttachedErrorDetails(error));
|
|
91
|
+
if (detailsSummary !== null &&
|
|
92
|
+
detailsSummary !== '' &&
|
|
93
|
+
baseMessage !== '' &&
|
|
94
|
+
!baseMessage.includes(detailsSummary)) {
|
|
95
|
+
return `${baseMessage} (${detailsSummary})`;
|
|
21
96
|
}
|
|
97
|
+
if (baseMessage !== '')
|
|
98
|
+
return baseMessage;
|
|
99
|
+
if (detailsSummary !== null && detailsSummary !== '')
|
|
100
|
+
return detailsSummary;
|
|
22
101
|
return 'Unknown trace storage error';
|
|
23
102
|
};
|
|
24
103
|
const buildFingerprint = (context) => {
|
|
@@ -32,25 +111,26 @@ const buildFingerprint = (context) => {
|
|
|
32
111
|
const reportFailure = (logger, context) => {
|
|
33
112
|
const now = Date.now();
|
|
34
113
|
const errorMessage = getErrorMessage(context.error);
|
|
114
|
+
const errorDetails = getAttachedErrorDetails(context.error);
|
|
35
115
|
const fingerprint = buildFingerprint(context);
|
|
36
116
|
const lastLoggedAt = diagnosticsState.lastLoggedAtByFingerprint.get(fingerprint);
|
|
37
117
|
diagnosticsState.degraded = true;
|
|
38
118
|
diagnosticsState.lastErrorMessage = errorMessage;
|
|
39
119
|
diagnosticsState.lastFailureAt = now;
|
|
40
120
|
diagnosticsState.totalFailures += 1;
|
|
41
|
-
if (
|
|
121
|
+
if (logger === undefined)
|
|
42
122
|
return;
|
|
43
123
|
if (typeof lastLoggedAt === 'number' && now - lastLoggedAt < LOG_WINDOW_MS)
|
|
44
124
|
return;
|
|
45
125
|
diagnosticsState.lastLoggedAtByFingerprint.set(fingerprint, now);
|
|
46
|
-
logger.warn('[trace] Trace storage write degraded', {
|
|
126
|
+
logger.warn('[trace] Trace storage write degraded', withOptionalDetail({
|
|
47
127
|
connectionName: context.connectionName,
|
|
48
128
|
error: errorMessage,
|
|
49
129
|
lastFailureAt: now,
|
|
50
130
|
operation: context.operation,
|
|
51
131
|
totalFailures: diagnosticsState.totalFailures,
|
|
52
132
|
watcherType: context.watcherType ?? null,
|
|
53
|
-
});
|
|
133
|
+
}, errorDetails));
|
|
54
134
|
};
|
|
55
135
|
const wrapStorageMethod = (method, describeFailure, connectionName, logger) => {
|
|
56
136
|
return async (...args) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zintrust/trace",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.84",
|
|
4
4
|
"description": "Trace assistant for ZinTrust: logs requests, queries, exceptions, jobs, and more.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"node": ">=20.0.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@zintrust/core": "^0.4.
|
|
43
|
+
"@zintrust/core": "^0.4.83"
|
|
44
44
|
},
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|
|
@@ -32,17 +32,104 @@ const diagnosticsState: TraceWriteDiagnosticsState = {
|
|
|
32
32
|
totalFailures: 0,
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
const asRecord = (value: unknown): Record<string, unknown> | null => {
|
|
36
|
+
if (value === null || typeof value !== 'object') return null;
|
|
37
|
+
return value as Record<string, unknown>;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const getAttachedErrorDetails = (error: unknown): unknown => {
|
|
41
|
+
if (error instanceof Error && 'details' in error) {
|
|
42
|
+
const details = (error as Error & { details?: unknown }).details;
|
|
43
|
+
if (details !== undefined) return details;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const record = asRecord(error);
|
|
47
|
+
return record?.['details'];
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const getTextValue = (value: unknown): string | null => {
|
|
51
|
+
if (typeof value !== 'string') return null;
|
|
52
|
+
|
|
53
|
+
const trimmed = value.trim();
|
|
54
|
+
return trimmed === '' ? null : trimmed;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const describeBodyDetails = (body: Record<string, unknown>): string | null => {
|
|
58
|
+
const code = getTextValue(body['code']);
|
|
59
|
+
const message = getTextValue(body['message']);
|
|
60
|
+
|
|
61
|
+
if (code !== null && message !== null) return `${code}: ${message}`;
|
|
62
|
+
if (code !== null) return code;
|
|
63
|
+
if (message !== null) return message;
|
|
64
|
+
|
|
65
|
+
return null;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const describeRecordDetails = (record: Record<string, unknown>): string | null => {
|
|
69
|
+
const body = asRecord(record['body']);
|
|
70
|
+
if (body !== null) {
|
|
71
|
+
const describedBody = describeBodyDetails(body);
|
|
72
|
+
if (describedBody !== null) return describedBody;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const nested = describeErrorDetails(record['details']);
|
|
76
|
+
if (nested !== null) return nested;
|
|
77
|
+
|
|
78
|
+
const message = getTextValue(record['message']);
|
|
79
|
+
if (message !== null) return message;
|
|
80
|
+
|
|
81
|
+
const code = getTextValue(record['code']);
|
|
82
|
+
if (code !== null) return code;
|
|
83
|
+
|
|
84
|
+
return null;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const describeErrorDetails = (details: unknown): string | null => {
|
|
88
|
+
const text = getTextValue(details);
|
|
89
|
+
if (text !== null) return text;
|
|
90
|
+
|
|
91
|
+
const record = asRecord(details);
|
|
92
|
+
if (record === null) return null;
|
|
93
|
+
return describeRecordDetails(record);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const withOptionalDetail = (
|
|
97
|
+
context: Record<string, unknown>,
|
|
98
|
+
errorDetails: unknown
|
|
99
|
+
): Record<string, unknown> => {
|
|
100
|
+
if (errorDetails === undefined) return context;
|
|
101
|
+
return { ...context, errorDetails };
|
|
102
|
+
};
|
|
103
|
+
|
|
35
104
|
const getErrorMessage = (error: unknown): string => {
|
|
36
|
-
|
|
37
|
-
if (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
105
|
+
let baseMessage = '';
|
|
106
|
+
if (error instanceof Error && error.message.trim() !== '') {
|
|
107
|
+
baseMessage = error.message;
|
|
108
|
+
} else if (typeof error === 'string' && error.trim() !== '') {
|
|
109
|
+
baseMessage = error;
|
|
110
|
+
} else {
|
|
111
|
+
try {
|
|
112
|
+
const serialized = JSON.stringify(error);
|
|
113
|
+
if (typeof serialized === 'string' && serialized !== '') baseMessage = serialized;
|
|
114
|
+
} catch {
|
|
115
|
+
// ignore serialization failures
|
|
116
|
+
}
|
|
44
117
|
}
|
|
45
118
|
|
|
119
|
+
const detailsSummary = describeErrorDetails(getAttachedErrorDetails(error));
|
|
120
|
+
if (
|
|
121
|
+
detailsSummary !== null &&
|
|
122
|
+
detailsSummary !== '' &&
|
|
123
|
+
baseMessage !== '' &&
|
|
124
|
+
!baseMessage.includes(detailsSummary)
|
|
125
|
+
) {
|
|
126
|
+
return `${baseMessage} (${detailsSummary})`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (baseMessage !== '') return baseMessage;
|
|
130
|
+
|
|
131
|
+
if (detailsSummary !== null && detailsSummary !== '') return detailsSummary;
|
|
132
|
+
|
|
46
133
|
return 'Unknown trace storage error';
|
|
47
134
|
};
|
|
48
135
|
|
|
@@ -61,6 +148,7 @@ const reportFailure = (
|
|
|
61
148
|
): void => {
|
|
62
149
|
const now = Date.now();
|
|
63
150
|
const errorMessage = getErrorMessage(context.error);
|
|
151
|
+
const errorDetails = getAttachedErrorDetails(context.error);
|
|
64
152
|
const fingerprint = buildFingerprint(context);
|
|
65
153
|
const lastLoggedAt = diagnosticsState.lastLoggedAtByFingerprint.get(fingerprint);
|
|
66
154
|
|
|
@@ -69,18 +157,24 @@ const reportFailure = (
|
|
|
69
157
|
diagnosticsState.lastFailureAt = now;
|
|
70
158
|
diagnosticsState.totalFailures += 1;
|
|
71
159
|
|
|
72
|
-
if (
|
|
160
|
+
if (logger === undefined) return;
|
|
73
161
|
if (typeof lastLoggedAt === 'number' && now - lastLoggedAt < LOG_WINDOW_MS) return;
|
|
74
162
|
|
|
75
163
|
diagnosticsState.lastLoggedAtByFingerprint.set(fingerprint, now);
|
|
76
|
-
logger.warn(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
164
|
+
logger.warn(
|
|
165
|
+
'[trace] Trace storage write degraded',
|
|
166
|
+
withOptionalDetail(
|
|
167
|
+
{
|
|
168
|
+
connectionName: context.connectionName,
|
|
169
|
+
error: errorMessage,
|
|
170
|
+
lastFailureAt: now,
|
|
171
|
+
operation: context.operation,
|
|
172
|
+
totalFailures: diagnosticsState.totalFailures,
|
|
173
|
+
watcherType: context.watcherType ?? null,
|
|
174
|
+
},
|
|
175
|
+
errorDetails
|
|
176
|
+
)
|
|
177
|
+
);
|
|
84
178
|
};
|
|
85
179
|
|
|
86
180
|
const wrapStorageMethod = <TArgs extends unknown[], TResult>(
|