Skip to content

Commit e9fa3bc

Browse files
committed
ref: introduce format function and restructure exports
1 parent a8673b7 commit e9fa3bc

File tree

2 files changed

+102
-46
lines changed

2 files changed

+102
-46
lines changed

packages/core/src/exports.ts

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import type {
1111
Extra,
1212
Extras,
1313
FinishedCheckIn,
14-
LogSeverityLevel,
1514
MonitorConfig,
1615
Primitive,
1716
Session,
@@ -24,6 +23,7 @@ import { logger } from './utils-hoist/logger';
2423
import { uuid4 } from './utils-hoist/misc';
2524
import { timestampInSeconds } from './utils-hoist/time';
2625
import { GLOBAL_OBJ } from './utils-hoist/worldwide';
26+
import { parameterize } from './utils/parameterize';
2727
import type { ExclusiveEventHintOrCaptureContext } from './utils/prepareEvent';
2828
import { parseEventHintOrCaptureContext } from './utils/prepareEvent';
2929

@@ -337,8 +337,6 @@ export function captureSession(end: boolean = false): void {
337337
_sendSessionUpdate();
338338
}
339339

340-
type OmitFirstArg<F> = F extends (x: LogSeverityLevel, ...args: infer P) => infer R ? (...args: P) => R : never;
341-
342340
/**
343341
* A namespace for experimental logging functions.
344342
*
@@ -349,55 +347,106 @@ export const _experiment_log = {
349347
* A utility to record a log with level 'TRACE' and send it to sentry.
350348
*
351349
* Logs represent a message and some parameters which provide context for a trace or error.
352-
* Ex: Sentry._experiment_log.trace`user ${username} just bought ${item}!`
350+
*
351+
* @example
352+
* ```js
353+
* const { trace, fmt } = Sentry._experiment_log;
354+
* trace(fmt`user ${username} just bought ${item}!`);
355+
* ```
353356
*/
354-
trace: sendLog.bind(null, 'trace') as OmitFirstArg<typeof sendLog>,
357+
trace: sendLog('trace'),
355358
/**
356359
* A utility to record a log with level 'DEBUG' and send it to sentry.
357360
*
358361
* Logs represent a message and some parameters which provide context for a trace or error.
359-
* Ex: Sentry._experiment_log.debug`user ${username} just bought ${item}!`
362+
*
363+
* @example
364+
* ```js
365+
* const { debug, fmt } = Sentry._experiment_log;
366+
* debug(fmt`user ${username} just bought ${item}!`);
367+
* ```
360368
*/
361-
debug: sendLog.bind(null, 'debug') as OmitFirstArg<typeof sendLog>,
369+
debug: sendLog('debug'),
362370
/**
363371
* A utility to record a log with level 'INFO' and send it to sentry.
364372
*
365373
* Logs represent a message and some parameters which provide context for a trace or error.
366-
* Ex: Sentry._experiment_log.info`user ${username} just bought ${item}!`
374+
*
375+
* @example
376+
* ```js
377+
* const { info, fmt } = Sentry._experiment_log;
378+
* info(fmt`user ${username} just bought ${item}!`);
379+
* ```
367380
*/
368-
info: sendLog.bind(null, 'info') as OmitFirstArg<typeof sendLog>,
381+
info: sendLog('info'),
369382
/**
370383
* A utility to record a log with level 'INFO' and send it to sentry.
371384
*
372385
* Logs represent a message and some parameters which provide context for a trace or error.
373-
* Ex: Sentry._experiment_log.log`user ${username} just bought ${item}!`
386+
*
387+
* @example
388+
* ```js
389+
* const { log, fmt } = Sentry._experiment_log;
390+
* log(fmt`user ${username} just bought ${item}!`);
391+
* ```
374392
*/
375-
log: sendLog.bind(null, 'log') as OmitFirstArg<typeof sendLog>,
393+
log: sendLog('info', 10),
376394
/**
377395
* A utility to record a log with level 'ERROR' and send it to sentry.
378396
*
379397
* Logs represent a message and some parameters which provide context for a trace or error.
380-
* Ex: Sentry._experiment_log.error`user ${username} just bought ${item}!`
398+
*
399+
* @example
400+
* ```js
401+
* const { error, fmt } = Sentry._experiment_log;
402+
* error(fmt`user ${username} just bought ${item}!`);
403+
* ```
381404
*/
382-
error: sendLog.bind(null, 'error') as OmitFirstArg<typeof sendLog>,
405+
error: sendLog('error'),
383406
/**
384407
* A utility to record a log with level 'WARN' and send it to sentry.
385408
*
386409
* Logs represent a message and some parameters which provide context for a trace or error.
387-
* Ex: Sentry._experiment_log.warn`user ${username} just bought ${item}!`
410+
*
411+
* @example
412+
* ```js
413+
* const { warn, fmt } = Sentry._experiment_log;
414+
* warn(fmt`user ${username} just bought ${item}!`);
415+
* ```
388416
*/
389-
warn: sendLog.bind(null, 'warn') as OmitFirstArg<typeof sendLog>,
417+
warn: sendLog('warn'),
390418
/**
391419
* A utility to record a log with level 'FATAL' and send it to sentry.
392420
*
393421
* Logs represent a message and some parameters which provide context for a trace or error.
394-
* Ex: Sentry._experiment_log.warn`user ${username} just bought ${item}!`
422+
*
423+
* @example
424+
* ```js
425+
* const { fatal, fmt } = Sentry._experiment_log;
426+
* fatal(fmt`user ${username} just bought ${item}!`);
427+
* ```
395428
*/
396-
fatal: sendLog.bind(null, 'fatal') as OmitFirstArg<typeof sendLog>,
429+
fatal: sendLog('fatal'),
430+
431+
/**
432+
* Tagged template function which returns parameterized representation of the message
433+
*
434+
* @example
435+
* ```js
436+
* Sentry._experiment_log.fmt`This is a log statement with ${x} and ${y} params`
437+
* ```
438+
*/
439+
fmt: parameterize,
440+
397441
/**
398442
* A flexible utility to record a log with a custom level and send it to sentry.
399443
*
400444
* You can optionally pass in custom attributes and a custom severity number to be attached to the log.
445+
*
446+
* @example
447+
* ```js
448+
* Sentry._experiment_log.emit({ level: 'info', message: Sentry._experiment_log.fmt`user ${username }just bought ${item}`, attributes: { extra: 123 } })
449+
* ```
401450
*/
402-
captureLog,
451+
emit: captureLog,
403452
};

packages/core/src/log.ts

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import { getClient, getCurrentScope } from './currentScopes';
33
import { DEBUG_BUILD } from './debug-build';
44
import type { Scope } from './scope';
55
import { getDynamicSamplingContextFromScope } from './tracing';
6+
import type { ParameterizedString } from './types-hoist';
67
import type { DynamicSamplingContext, LogEnvelope, LogItem } from './types-hoist/envelope';
78
import type { Log, LogAttribute, LogSeverityLevel } from './types-hoist/log';
8-
import { createEnvelope, dropUndefinedKeys, dsnToString, logger } from './utils-hoist';
9+
import { createEnvelope, dropUndefinedKeys, dsnToString, isParameterizedString, logger } from './utils-hoist';
910

1011
const LOG_BUFFER_MAX_LENGTH = 25;
1112

@@ -108,36 +109,30 @@ function addToLogBuffer(client: Client, log: Log, scope: Scope): void {
108109
}
109110

110111
/**
111-
* A utility function to be able to create methods like Sentry.info`...` that use tagged template functions.
112-
*
113-
* The first parameter is bound with, e.g., const info = captureLog.bind(null, 'info')
114-
* The other parameters are in the format to be passed a tagged template, Sentry.info`hello ${world}`
112+
* A utility function to be able to create methods like Sentry.info(...).
115113
*/
116-
export function sendLog(level: LogSeverityLevel, messageArr: TemplateStringsArray, ...values: unknown[]): void {
117-
const message = messageArr.reduce((acc, str, i) => acc + str + (JSON.stringify(values[i]) ?? ''), '');
118-
119-
const attributes = values.reduce<Record<string, unknown>>(
120-
(acc, value, index) => {
121-
acc[`sentry.message.parameters.${index}`] = value;
122-
return acc;
123-
},
124-
{
125-
'sentry.message.template': messageArr.map((s, i) => s + (i < messageArr.length - 1 ? `$param.${i}` : '')).join(''),
126-
},
127-
);
128-
129-
captureLog(level, message, attributes);
114+
export function sendLog(
115+
level: LogSeverityLevel,
116+
severityNumber?: number,
117+
): (message: ParameterizedString | string, customAttributes?: Record<string, unknown>) => void {
118+
return (message: ParameterizedString | string, attributes: Record<string, unknown> = {}): void =>
119+
captureLog({ level, message, attributes, severityNumber });
130120
}
131121

132122
/**
133123
* Sends a log to Sentry.
134124
*/
135-
export function captureLog(
136-
level: LogSeverityLevel,
137-
message: string,
138-
customAttributes: Record<string, unknown> = {},
139-
severityNumber?: number,
140-
): void {
125+
export function captureLog({
126+
level,
127+
message,
128+
attributes,
129+
severityNumber,
130+
}: {
131+
level: LogSeverityLevel;
132+
message: ParameterizedString | string;
133+
attributes?: Record<string, unknown>;
134+
severityNumber?: number;
135+
}): void {
141136
const client = getClient();
142137

143138
if (!client) {
@@ -153,9 +148,19 @@ export function captureLog(
153148
const { release, environment } = client.getOptions();
154149

155150
const logAttributes = {
156-
...customAttributes,
151+
...attributes,
157152
};
158153

154+
if (isParameterizedString(message)) {
155+
const { __sentry_template_string__ = '', __sentry_template_values__ = [] } = message;
156+
if (__sentry_template_string__) {
157+
logAttributes['sentry.message.template'] = __sentry_template_string__;
158+
__sentry_template_values__.forEach((value, index) => {
159+
logAttributes[`sentry.message.parameters.${index}`] = value;
160+
});
161+
}
162+
}
163+
159164
if (release) {
160165
logAttributes['sentry.release'] = release;
161166
}
@@ -166,14 +171,16 @@ export function captureLog(
166171

167172
const scope = getCurrentScope();
168173

169-
const attributes = Object.entries(logAttributes).map<LogAttribute>(([key, value]) => valueToAttribute(key, value));
174+
const finalAttributes = Object.entries(logAttributes).map<LogAttribute>(([key, value]) =>
175+
valueToAttribute(key, value),
176+
);
170177

171178
const log: Log = {
172179
severityText: level,
173180
body: {
174181
stringValue: message,
175182
},
176-
attributes,
183+
attributes: finalAttributes,
177184
timeUnixNano: `${new Date().getTime().toString()}000000`,
178185
traceId: scope.getPropagationContext().traceId,
179186
severityNumber,

0 commit comments

Comments
 (0)