@takeshape/logger 11.143.2 → 11.154.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takeshape/logger",
3
- "version": "11.143.2",
3
+ "version": "11.154.1",
4
4
  "description": "Logging utility.",
5
5
  "homepage": "https://www.takeshape.io",
6
6
  "repository": {
@@ -1,4 +0,0 @@
1
- export declare const logProviders: readonly ["CLOUDWATCH", "CLOUDWATCH_LAMBDA", "CONSOLE"];
2
- export declare const logLevels: readonly ["DEBUG", "INFO", "WARN", "ERROR"];
3
- export declare const defaultLogProvider: "CLOUDWATCH";
4
- export declare const defaultLogLevel: "INFO";
package/dist/constants.js DELETED
@@ -1,4 +0,0 @@
1
- export const logProviders = ['CLOUDWATCH', 'CLOUDWATCH_LAMBDA', 'CONSOLE'];
2
- export const logLevels = ['DEBUG', 'INFO', 'WARN', 'ERROR'];
3
- export const defaultLogProvider = 'CLOUDWATCH';
4
- export const defaultLogLevel = 'INFO';
package/dist/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from './constants.ts';
2
- export * from './logger.ts';
3
- export * from './types.ts';
package/dist/index.js DELETED
@@ -1,3 +0,0 @@
1
- export * from "./constants.js";
2
- export * from "./logger.js";
3
- export * from "./types.js";
package/dist/logger.d.ts DELETED
@@ -1,25 +0,0 @@
1
- import type Sentry from '@sentry/core';
2
- import type { LogContext, Logger, LogProvider } from './types.ts';
3
- type JsonLog = {
4
- [key: string]: unknown;
5
- timestamp: string;
6
- level: string;
7
- message: string;
8
- requestId?: string;
9
- errorType?: string;
10
- errorMessage?: string;
11
- stackTrace?: string;
12
- };
13
- export declare function formatLogEntry(jsonLog: JsonLog, { prefixMessage }?: {
14
- prefixMessage?: boolean;
15
- }): string;
16
- export declare function shouldReportToSentry(error: Error): boolean;
17
- export declare function getLogLevelScore(logLevel: string): number;
18
- type LoggerOptions = {
19
- provider: LogProvider;
20
- level: string;
21
- sentryClient?: Pick<Sentry.Client, 'captureException' | 'captureMessage'>;
22
- messageOnly?: boolean;
23
- };
24
- export declare function createLogger({ level, ...options }: LoggerOptions, logContext?: LogContext): Logger;
25
- export {};
package/dist/logger.js DELETED
@@ -1,263 +0,0 @@
1
- import cloneDeep from 'lodash/cloneDeep.js';
2
- import merge from 'lodash/merge.js';
3
- import { logLevels } from "./constants.js";
4
- const noop = () => {
5
- // Empty
6
- };
7
- function getFargateEmf(now, metadata) {
8
- return {
9
- _aws: {
10
- Timestamp: now,
11
- CloudWatchMetrics: [
12
- {
13
- Namespace: 'fargate-function-metrics',
14
- Dimensions: [['serviceName', 'taskRevision']],
15
- Metrics: [
16
- {
17
- Name: 'time',
18
- Unit: 'Milliseconds',
19
- StorageResolution: 60
20
- }
21
- ]
22
- }
23
- ]
24
- },
25
- serviceName: metadata.context?.platform?.fargate?.service,
26
- taskRevision: metadata.context?.platform?.fargate?.task_revision,
27
- time: metadata.event?.duration
28
- };
29
- }
30
- function getLambdaEmf(now, metadata) {
31
- return {
32
- _aws: {
33
- Timestamp: now,
34
- CloudWatchMetrics: [
35
- {
36
- Namespace: 'lambda-function-metrics',
37
- Dimensions: [['functionVersion']],
38
- Metrics: [
39
- {
40
- Name: 'time',
41
- Unit: 'Milliseconds',
42
- StorageResolution: 60
43
- }
44
- ]
45
- }
46
- ]
47
- },
48
- functionVersion: '$LATEST',
49
- time: metadata.event?.duration
50
- };
51
- }
52
- /**
53
- * Create a structured JSON log statement, compatible with the Lambda / Cloudwatch format.
54
- *
55
- * @link https://docs.aws.amazon.com/lambda/latest/dg/nodejs-logging.html#nodejs-logging-advanced-JSON
56
- */
57
- function getJsonLog({ level, message, metadata, requestId, error, messageOnly }, emfFn) {
58
- const now = metadata.timestamp ? new Date(metadata.timestamp).valueOf() : Date.now();
59
- // https://docs.aws.amazon.com/lambda/latest/dg/nodejs-logging.html#nodejs-logging-advanced-level
60
- let jsonLog = {
61
- // Set message first, so we can read it without expanding the entry
62
- message,
63
- level,
64
- timestamp: new Date(now).toISOString(),
65
- requestId,
66
- ...(!messageOnly ? metadata : undefined)
67
- };
68
- if (error) {
69
- jsonLog = {
70
- ...jsonLog,
71
- errorType: error.name,
72
- errorMessage: error.message,
73
- stackTrace: error.stack
74
- };
75
- }
76
- if (emfFn && metadata.event?.duration) {
77
- // https://docs.aws.amazon.com/lambda/latest/dg/nodejs-logging.html#nodejs-logging-advanced-emf
78
- jsonLog = {
79
- ...jsonLog,
80
- ...emfFn(now, metadata)
81
- };
82
- }
83
- return jsonLog;
84
- }
85
- export function formatLogEntry(jsonLog, { prefixMessage } = {}) {
86
- if (prefixMessage) {
87
- // \r adds a line break in the message, \n creates a new log entry. This works with Lambda and the jsonLog will be parsed.
88
- return `${jsonLog.message} \r${JSON.stringify(jsonLog)}\n`;
89
- }
90
- // In Fargate, only pure JSON log objects get parsed
91
- return `${JSON.stringify(jsonLog)}\n`;
92
- }
93
- function isFieldNode(node) {
94
- return node.kind === 'Field';
95
- }
96
- function isGraphQLError(error) {
97
- return error.name === 'GraphQLError';
98
- }
99
- function getGraphQLErrorExtras(error) {
100
- const { path, nodes } = error;
101
- const fieldName = nodes?.find(isFieldNode)?.name.value;
102
- return {
103
- path,
104
- fieldName
105
- };
106
- }
107
- function getAggregateErrorExtras(error) {
108
- const errors = error.errors.map((e) => {
109
- if (Array.isArray(e)) {
110
- return e.join(', ');
111
- }
112
- if (typeof e === 'object') {
113
- return e?.message;
114
- }
115
- return e;
116
- });
117
- return {
118
- errors
119
- };
120
- }
121
- function getSentryExtras(error) {
122
- let extras = {};
123
- if (isGraphQLError(error)) {
124
- extras = {
125
- ...extras,
126
- ...getGraphQLErrorExtras(error)
127
- };
128
- if (error.originalError) {
129
- extras = {
130
- ...extras,
131
- ...getSentryExtras(error.originalError)
132
- };
133
- }
134
- }
135
- if (error instanceof AggregateError) {
136
- extras = {
137
- ...extras,
138
- ...getAggregateErrorExtras(error)
139
- };
140
- }
141
- return extras;
142
- }
143
- export function shouldReportToSentry(error) {
144
- if (isGraphQLError(error)) {
145
- if (error.originalError) {
146
- return shouldReportToSentry(error.originalError);
147
- }
148
- return false;
149
- }
150
- if ('reportToSentry' in error) {
151
- return Boolean(error.reportToSentry);
152
- }
153
- return true;
154
- }
155
- function decorateLogFn({ provider, level, sentryClient, messageOnly }, entry) {
156
- return (messageOrError, logMetadata) => {
157
- let metadata = logMetadata;
158
- let message;
159
- let error;
160
- if (messageOrError instanceof Error) {
161
- error = messageOrError;
162
- message = error.message;
163
- }
164
- else {
165
- error = metadata?.error;
166
- message = messageOrError;
167
- }
168
- if (metadata) {
169
- const { error, ...rest } = metadata;
170
- // Merge passed context with the base context, and exclude any message, and the error
171
- metadata = merge({}, entry, rest);
172
- }
173
- else {
174
- metadata = entry;
175
- }
176
- if (sentryClient && (level === 'ERROR' || level === 'WARN')) {
177
- const sentryLevel = level === 'WARN' ? 'warning' : 'error';
178
- const sentryHint = {
179
- captureContext(scope) {
180
- scope.setTransactionName(message);
181
- scope.setLevel(sentryLevel);
182
- scope.addBreadcrumb({
183
- type: 'error',
184
- message,
185
- level: sentryLevel
186
- });
187
- if (entry.context?.user?.id) {
188
- scope.setUser(entry.context.user);
189
- }
190
- const project = entry.context?.custom?.project;
191
- if (project?.id) {
192
- scope.setTag('projectId', project.id);
193
- }
194
- if (project?.schemaId) {
195
- scope.setTag('schemaId', project.schemaId);
196
- }
197
- if (project?.schemaHash) {
198
- scope.setTag('schemaHash', project.schemaHash);
199
- }
200
- if (error) {
201
- scope.setExtras(getSentryExtras(error));
202
- }
203
- return scope;
204
- }
205
- };
206
- if (error) {
207
- if (shouldReportToSentry(error)) {
208
- sentryClient.captureException(error, sentryHint);
209
- }
210
- }
211
- else {
212
- sentryClient.captureMessage(message, sentryLevel, sentryHint);
213
- }
214
- }
215
- if (provider === 'CONSOLE') {
216
- // biome-ignore lint/suspicious/noConsole: allowed
217
- const consoleMethod = console[level.toLowerCase()];
218
- if (!messageOnly) {
219
- consoleMethod(...[message, error, metadata].filter((x) => x));
220
- }
221
- else {
222
- consoleMethod(...[message, error].filter((x) => x));
223
- }
224
- return;
225
- }
226
- const jsonLog = getJsonLog({
227
- level,
228
- message,
229
- metadata,
230
- error,
231
- requestId: metadata?.context?.http?.request_id,
232
- messageOnly
233
- }, provider === 'CLOUDWATCH_LAMBDA' ? getLambdaEmf : getFargateEmf);
234
- process.stdout.write(formatLogEntry(jsonLog, {
235
- prefixMessage: provider === 'CLOUDWATCH_LAMBDA'
236
- }));
237
- };
238
- }
239
- export function getLogLevelScore(logLevel) {
240
- const logLevelUpper = logLevel.toUpperCase();
241
- return logLevels.indexOf((logLevelUpper && logLevels.includes(logLevelUpper) ? logLevelUpper : 'INFO'));
242
- }
243
- export function createLogger({ level, ...options }, logContext = {}) {
244
- const score = getLogLevelScore(level);
245
- const context = cloneDeep(logContext);
246
- const event = {};
247
- return {
248
- debug: score > logLevels.indexOf('DEBUG') ? noop : decorateLogFn({ level: 'DEBUG', ...options }, { context, event }),
249
- info: score > logLevels.indexOf('INFO') ? noop : decorateLogFn({ level: 'INFO', ...options }, { context, event }),
250
- warn: score > logLevels.indexOf('WARN') ? noop : decorateLogFn({ level: 'WARN', ...options }, { context, event }),
251
- error: score > logLevels.indexOf('ERROR') ? noop : decorateLogFn({ level: 'ERROR', ...options }, { context, event }),
252
- updateContext(update) {
253
- // mutates context
254
- merge(context, update);
255
- },
256
- context,
257
- updateEvent(update) {
258
- // mutates event
259
- merge(event, update);
260
- },
261
- event
262
- };
263
- }
package/dist/types.d.ts DELETED
@@ -1,312 +0,0 @@
1
- import type { logLevels, logProviders } from './constants.ts';
2
- /**
3
- * The duration, in fractional milliseconds, that it took to complete this event.
4
- */
5
- export type TimeMs = number;
6
- /**
7
- * The target host of the HTTP request. This may not be the same as the real hostname of the server.
8
- */
9
- export type HttpHost = string;
10
- /**
11
- * The HTTP method for the request.
12
- */
13
- export type HttpMethod = 'CONNECT' | 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'TRACE';
14
- /**
15
- * The path of the HTTP request.
16
- */
17
- export type HttpPath = string;
18
- /**
19
- * The IP address of the computer that issued the request.
20
- */
21
- export type HttpRemoteAddr = string;
22
- /**
23
- * An ID that uniquely identifies the request and can be used to trace requests.
24
- */
25
- export type HttpRequestId = string;
26
- /**
27
- * The body of the HTTP request / response.
28
- */
29
- export type HttpBody = string;
30
- /**
31
- * The value of the Content-Length header representing the size of the request in decimal number of octets.
32
- */
33
- export type HttpContentLength = number;
34
- /**
35
- * The direction of the HTTP request and response (incoming or outgoing).
36
- */
37
- export type HttpDirection = 'incoming' | 'outgoing';
38
- /**
39
- * An encoded JSON string representing *all* HTTP headers. This is used for request inspection without the overhead of creating and indexing fields for every header.
40
- */
41
- export type HttpHeadersJson = string;
42
- /**
43
- * An object representing *select* HTTP headers that need to be searched or graphed.
44
- */
45
- export type HttpHeaders = Record<string, any>;
46
- /**
47
- * The target port of the HTTP request. This may be different than the port the server is listening on.
48
- */
49
- export type HttpPort = number;
50
- /**
51
- * The query parameters present on the URL.
52
- */
53
- export type HttpQueryString = string;
54
- /**
55
- * The HTTP request scheme.
56
- */
57
- export type HttpScheme = 'http' | 'https';
58
- /**
59
- * A short label / name for the service you are sending the request to, ex: elasticsearch
60
- */
61
- export type HttpServiceName = string;
62
- /**
63
- * The status as defined by the HTTP status codes.
64
- */
65
- export type HttpStatus = number;
66
- export type LogErrorBacktrace = {
67
- /**
68
- * Application name, if applicable. For example, erlang / elixir have multiple apps within the same umbrella project.
69
- */
70
- app_name?: string;
71
- /**
72
- * The line file path.
73
- */
74
- file: string;
75
- /**
76
- * The calling function name.
77
- */
78
- function: string;
79
- /**
80
- * The calling line number.
81
- */
82
- line: number;
83
- };
84
- export type LogError = {
85
- /**
86
- * An optional array of lines, representing the call stack, leading up to the error.
87
- */
88
- backtrace?: LogErrorBacktrace[];
89
- /**
90
- * Optional message describing the error.
91
- */
92
- message?: string;
93
- /**
94
- * A JSON encoded string representing additional metadata. This provides insight without the overhead of creating and indexing fields.
95
- */
96
- metadata_json?: string;
97
- /**
98
- * Required name of the error.
99
- */
100
- name: string;
101
- };
102
- export type LogContext = {
103
- /**
104
- * An open ended object where custom context is supplied.
105
- */
106
- custom?: Record<string, Record<string, any>>;
107
- /**
108
- * Context about the HTTP request currently being processed (if any)
109
- */
110
- http?: {
111
- host?: HttpHost;
112
- method: HttpMethod;
113
- path?: HttpPath;
114
- remote_addr?: HttpRemoteAddr;
115
- request_id?: HttpRequestId;
116
- start_at?: TimeMs;
117
- };
118
- /**
119
- * Represents a task or job execution, typically for background tasks or jobs.
120
- */
121
- job?: {
122
- /**
123
- * The attempt number, if applicable.
124
- */
125
- attempt?: number;
126
- /**
127
- * A unique identifier for the job or task.
128
- */
129
- id?: string;
130
- /**
131
- * The name of the queue being processes, if applicable.
132
- */
133
- queue_name?: string;
134
- };
135
- /**
136
- * Contextual information about the hosting platform (AWS, Google Cloud, Heroku, etc) the application is hosted.
137
- */
138
- platform?: {
139
- [k: string]: any;
140
- /**
141
- * A boolean indicating if the application is running in a "live" SST environment (sst dev + live whitelist).
142
- */
143
- isLive?: boolean;
144
- /**
145
- * A boolean indicating if the application is running in a dev SST environment (sst dev).
146
- */
147
- isDev?: boolean;
148
- /**
149
- * Contextual information about the service running on the Fargate
150
- */
151
- fargate?: {
152
- [k: string]: any;
153
- /**
154
- * The unique identifier for the Docker container running inside the Fargate task.
155
- */
156
- container_name: string;
157
- /**
158
- * The collection of key value pairs found in the Kubernetes Pod metadata field Labels
159
- */
160
- labels?: Record<string, any>;
161
- /**
162
- * The Fargate service in which this task is running
163
- */
164
- service: string;
165
- /**
166
- * The task revision in which this container is running.
167
- */
168
- task_revision: string;
169
- /**
170
- * The task arn in which this container is running.
171
- */
172
- task_arn: string;
173
- };
174
- /**
175
- * Contextual information about the Lambda fn
176
- */
177
- lambda?: {
178
- [k: string]: any;
179
- /**
180
- * Function name for the Lambda fn.
181
- */
182
- function_name: string;
183
- };
184
- };
185
- /**
186
- * Contextual information on the current release
187
- */
188
- release?: {
189
- /**
190
- * The git commit sha for the deploy
191
- */
192
- commit_hash?: string;
193
- /**
194
- * When the release was created, ISO8601 date time.
195
- */
196
- created_at?: string;
197
- /**
198
- * Deploy version, can be an unique string. Ex: 1.1.2 or a43fdw
199
- */
200
- version?: string;
201
- };
202
- /**
203
- * Represents a user in the platform being logged. The interpretation of "user" is left to the consumer.
204
- */
205
- user?: {
206
- /**
207
- * An email address for the user. This need not be unique to the user. Note that no validation is performed on this field.
208
- */
209
- email?: string;
210
- /**
211
- * A unique identifier for the user.
212
- */
213
- id?: string;
214
- /**
215
- * Additional custom metadata you'd like to add to the user.
216
- */
217
- meta?: Record<string, any>;
218
- /**
219
- * A display name for the user.
220
- */
221
- name?: string;
222
- /**
223
- * The type of user. Used in systems where there are multiple user types. This helps to denote users in the case of polymorphism.
224
- */
225
- type?: string;
226
- };
227
- };
228
- export type LogEvent = {
229
- /**
230
- * An open ended object used for custom event data. Only a single root key is allowed, this represents the event type and avoids type collisions in the context of the entire schema.
231
- */
232
- custom?: Record<string, Record<string, any>>;
233
- /**
234
- * Represents an error or exception.
235
- */
236
- error?: LogError;
237
- /**
238
- * The duration, in milliseconds, that it took to complete this event.
239
- */
240
- duration?: TimeMs;
241
- /**
242
- * Represents a HTTP request, both incoming and outgoing. Note the direction field.
243
- */
244
- http_request?: {
245
- body?: HttpBody;
246
- content_length?: HttpContentLength;
247
- direction?: HttpDirection;
248
- headers?: HttpHeaders;
249
- headers_json?: HttpHeadersJson;
250
- host?: HttpHost;
251
- method: HttpMethod;
252
- path?: HttpPath;
253
- port?: HttpPort;
254
- query_string?: HttpQueryString;
255
- request_id?: HttpRequestId;
256
- scheme?: HttpScheme;
257
- service_name?: HttpServiceName;
258
- start_time?: TimeMs;
259
- path_parameters?: Record<string, string | undefined>;
260
- query_parameters?: Record<string, string | string[] | undefined>;
261
- route_key?: string;
262
- };
263
- /**
264
- * Represents a HTTP response event, both outgoing and incoming. Note the direction field.
265
- */
266
- http_response?: {
267
- body?: HttpBody;
268
- content_length?: HttpContentLength;
269
- direction?: HttpDirection;
270
- headers?: HttpHeaders;
271
- headers_json?: HttpHeadersJson;
272
- request_id?: HttpRequestId;
273
- service_name?: HttpServiceName;
274
- status: HttpStatus;
275
- end_time?: TimeMs;
276
- };
277
- };
278
- export type LogEntry = {
279
- /**
280
- * The IOS8601 formatted datetime when the log was generated.
281
- */
282
- timestamp?: string | undefined;
283
- /**
284
- * The raw log event message, formatting stripped.
285
- */
286
- message?: string | undefined;
287
- /**
288
- * Contextual metadata about the environment the event takes place in
289
- */
290
- context?: LogContext | undefined;
291
- /**
292
- * A controlled representation of the event this log line represents.
293
- */
294
- event?: LogEvent | undefined;
295
- };
296
- export type LogMetadata = {
297
- error?: Error;
298
- } & Partial<LogEntry>;
299
- export type LogFn = typeof console.log;
300
- export type LoggerFn = (message: string | Error, metadata?: LogMetadata) => void;
301
- export type Logger = {
302
- debug: LoggerFn;
303
- info: LoggerFn;
304
- warn: LoggerFn;
305
- error: LoggerFn;
306
- updateContext: (context: LogContext) => void;
307
- updateEvent: (event: LogEvent) => void;
308
- context: LogContext;
309
- event: LogEvent;
310
- };
311
- export type LogLevel = (typeof logLevels)[number];
312
- export type LogProvider = (typeof logProviders)[number];
package/dist/types.js DELETED
@@ -1 +0,0 @@
1
- export {};