Skip to content

Commit c0bc817

Browse files
committed
Implement custom browser logger
1 parent 2c04e18 commit c0bc817

File tree

6 files changed

+149
-0
lines changed

6 files changed

+149
-0
lines changed

src/hooks.client.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
getClientSentryIntegrations,
88
setClientPosthogSessionId,
99
} from '$lib/client/sentry/utils';
10+
import { logger } from '$lib/client/logging';
1011

1112
setupBrowserPosthogClient(config.posthog.projectApiKey, config.posthog.apiHost);
1213
setupSentryClient({
@@ -23,6 +24,8 @@ setupSentryClient({
2324
});
2425
setClientPosthogSessionId();
2526

27+
logger.debug('Client app started');
28+
2629
export const handleError = handleErrorWithSentry((async ({ error }) => {
2730
const message = 'Internal Client Error';
2831
if (dev) {

src/lib/client/core/config/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ export const config = {
2222
organization: PUBLIC_SENTRY_ORGANIZATION,
2323
projectId: getSentryProjectId(),
2424
},
25+
logger: {
26+
get minLogLevel(): string {
27+
return globalThis.localStorage.getItem('LOGGER_MIN_LOG_LEVEL') ?? 'info';
28+
},
29+
get isDebugContextShown(): boolean {
30+
return (
31+
globalThis.localStorage.getItem('LOGGER_SHOW_DEBUG_CONTEXT') === 'true'
32+
);
33+
},
34+
},
2535
};
2636

2737
function getSentryProjectId(): number | undefined {

src/lib/client/logging/client.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { config } from '$lib/client/core/config';
2+
import type { LoggerContext } from '$lib/shared/logging/types';
3+
import {
4+
enrichContextWithDebugInfo,
5+
enrichLoggerContextWithSentryTraceId,
6+
} from '$lib/shared/logging/utils';
7+
import type { LogLevelName } from './types';
8+
import { logLevelColors, logLevels, logTimestampColors } from './utils';
9+
10+
export const logger = (function () {
11+
const createLogger = (methodName: LogLevelName) => {
12+
return (
13+
message: string,
14+
context: LoggerContext = {},
15+
stackLevel: number = 3,
16+
) => {
17+
if (!shouldBeLogged(methodName)) {
18+
return;
19+
}
20+
21+
const contextClone = enrichLoggerContextWithSentryTraceId(context);
22+
23+
console[methodName](
24+
...createLogPrefixStrings(methodName),
25+
message,
26+
'\n',
27+
config.logger.isDebugContextShown
28+
? enrichContextWithDebugInfo(
29+
contextClone,
30+
window.location.origin,
31+
stackLevel,
32+
)
33+
: contextClone,
34+
);
35+
36+
// Sentry libraries automatically record breadcrumbs for console logs,
37+
// so there is not need to manually record them.
38+
};
39+
};
40+
41+
const logger = Object.keys(logLevels).reduce(
42+
(acc, methodName) => {
43+
acc[methodName as LogLevelName] = createLogger(
44+
methodName as LogLevelName,
45+
);
46+
return acc;
47+
},
48+
{} as Record<
49+
LogLevelName,
50+
(message: string, context?: LoggerContext, stackLevel?: number) => void
51+
>,
52+
);
53+
54+
return logger;
55+
})();
56+
57+
function shouldBeLogged(logLevel: LogLevelName): boolean {
58+
const requestedLogLevel = logLevels[logLevel];
59+
const minLogLevel = logLevels[config.logger.minLogLevel as LogLevelName];
60+
61+
return requestedLogLevel >= minLogLevel;
62+
}
63+
64+
function createLogPrefixStrings(logLevel: LogLevelName): string[] {
65+
const currentUtcTime = new Date().toISOString();
66+
const logTimestampColor = logTimestampColors[logLevel];
67+
const logLevelColor = logLevelColors[logLevel];
68+
const logLevelCommonStyles =
69+
'font-weight: bold; padding: 2px 4px; border-radius: 2px;';
70+
71+
return [
72+
`%c[${currentUtcTime}]%c\t%c${logLevel}%c\t:`,
73+
`color: ${logTimestampColor.color}; font-weight: bold;`,
74+
'',
75+
`background-color: ${logLevelColor.backgroundColor}; color: ${logLevelColor.color}; ${logLevelCommonStyles}`,
76+
'',
77+
];
78+
}

src/lib/client/logging/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './client';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import type { logLevels } from '../utils';
2+
3+
export type LogLevelName = keyof typeof logLevels;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import type { LogLevelName } from '../types';
2+
3+
export const logLevels = {
4+
debug: 10,
5+
log: 20,
6+
info: 30,
7+
warn: 40,
8+
error: 50,
9+
} as const;
10+
11+
export const logLevelColors = {
12+
debug: {
13+
backgroundColor: '#666',
14+
color: '#fff',
15+
},
16+
error: {
17+
backgroundColor: '#f05033',
18+
color: '#fff',
19+
},
20+
info: {
21+
backgroundColor: '#3174f1',
22+
color: '#fff',
23+
},
24+
log: {
25+
backgroundColor: '#712bde',
26+
color: '#fff',
27+
},
28+
warn: {
29+
backgroundColor: '#f5a623',
30+
color: '#000',
31+
},
32+
} satisfies {
33+
[key in LogLevelName]: { backgroundColor: string; color: string };
34+
};
35+
36+
export const logTimestampColors = {
37+
debug: {
38+
color: '#999',
39+
},
40+
error: {
41+
color: '#ff1a1a',
42+
},
43+
info: {
44+
color: '#3291ff',
45+
},
46+
log: {
47+
color: '#8367d3',
48+
},
49+
warn: {
50+
color: '#f7b955',
51+
},
52+
} satisfies {
53+
[key in LogLevelName]: { color: string };
54+
};

0 commit comments

Comments
 (0)