Skip to content

Commit 8b30a3c

Browse files
committed
refactor(core): Logger abstraction added
1 parent 7d5e8e4 commit 8b30a3c

12 files changed

Lines changed: 213 additions & 63 deletions

File tree

packages/core/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
export type { HawkStorage } from './storages/hawk-storage';
22
export type { UserManager } from './users/user-manager';
33
export { HawkStorageUserManager } from './users/hawk-storage-user-manager';
4+
export type { Logger, LogType } from './logger/logger';
5+
export { setLogger, log } from './logger/logger';

packages/core/src/logger/logger.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Log level type for categorizing log messages.
3+
*
4+
* Includes standard console methods supported in both browser and Node.js:
5+
* - Standard levels: `log`, `warn`, `error`, `info`
6+
* - Performance timing: `time`, `timeEnd`
7+
*/
8+
export type LogType = 'log' | 'warn' | 'error' | 'info' | 'time' | 'timeEnd';
9+
10+
/**
11+
* Logger function interface for environment-specific logging implementations.
12+
*
13+
* Implementations should handle message formatting, output styling,
14+
* and platform-specific logging mechanisms (e.g., console, file, network).
15+
*
16+
* @param msg - The message to log.
17+
* @param type - Log level/severity (default: 'log').
18+
* @param args - Additional data to include with the log message.
19+
*/
20+
export interface Logger {
21+
(msg: string, type?: LogType, args?: unknown): void;
22+
}
23+
24+
/**
25+
* Global logger instance, set by environment-specific packages.
26+
*/
27+
let loggerInstance: Logger | null = null;
28+
29+
/**
30+
* Registers the environment-specific logger implementation.
31+
*
32+
* This should be called once during application initialization
33+
* by the environment-specific package.
34+
*
35+
* @param logger - Logger implementation to use globally.
36+
*/
37+
export function setLogger(logger: Logger): void {
38+
loggerInstance = logger;
39+
}
40+
41+
/**
42+
* Logs a message using the registered logger implementation.
43+
*
44+
* If no logger has been registered via {@link setLogger}, this is a no-op.
45+
*
46+
* @param msg - Message to log.
47+
* @param type - Log level (default: 'log').
48+
* @param args - Additional arguments to log.
49+
*/
50+
export function log(msg: string, type?: LogType, args?: unknown): void {
51+
if (loggerInstance) {
52+
loggerInstance(msg, type, args);
53+
}
54+
}

packages/javascript/src/addons/breadcrumbs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import type { Breadcrumb, BreadcrumbLevel, BreadcrumbType, Json, JsonNode } from '@hawk.so/types';
55
import Sanitizer from '../modules/sanitizer';
66
import { buildElementSelector } from '../utils/selector';
7-
import log from '../utils/log';
7+
import { log } from '@hawk.so/core';
88
import { isValidBreadcrumb } from '../utils/validation';
99

1010
/**

packages/javascript/src/catcher.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import Socket from './modules/socket';
22
import Sanitizer from './modules/sanitizer';
3-
import log from './utils/log';
43
import StackParser from './modules/stackParser';
54
import type { CatcherMessage, HawkInitialSettings, BreadcrumbsAPI, Transport } from './types';
65
import { VueIntegration } from './integrations/vue';
@@ -18,9 +17,9 @@ import { isErrorProcessed, markErrorAsProcessed } from './utils/event';
1817
import { ConsoleCatcher } from './addons/consoleCatcher';
1918
import { BreadcrumbManager } from './addons/breadcrumbs';
2019
import { validateUser, validateContext, isValidEventPayload } from './utils/validation';
21-
import type { UserManager } from '@hawk.so/core';
22-
import { HawkStorageUserManager } from '@hawk.so/core';
20+
import { HawkStorageUserManager, UserManager, setLogger, log } from '@hawk.so/core';
2321
import { HawkLocalStorage } from './storages/hawk-local-storage';
22+
import { createBrowserLogger } from './logger/logger';
2423
import { id } from './utils/id';
2524

2625
/**
@@ -120,6 +119,8 @@ export default class Catcher {
120119
* @param {HawkInitialSettings|string} settings - If settings is a string, it means an Integration Token
121120
*/
122121
constructor(settings: HawkInitialSettings | string) {
122+
setLogger(createBrowserLogger(VERSION));
123+
123124
if (typeof settings === 'string') {
124125
settings = {
125126
token: settings,
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import type { Logger, LogType } from '@hawk.so/core';
2+
3+
/**
4+
* Creates a browser console logger with Hawk branding and styled output.
5+
*
6+
* The logger outputs to `window.console` with a dark label badge
7+
* containing the Hawk version. Messages are formatted with CSS
8+
* styling for better visibility in browser developer tools.
9+
*
10+
* @param version - Version string to display in log messages.
11+
* @param style - Optional CSS style for the message text (default: 'color: inherit').
12+
* @returns {Logger} Logger function implementation for browser environments.
13+
*
14+
* @example
15+
* ```TypeScript
16+
* import { createBrowserLogger } from '@hawk.so/browser';
17+
* import { setLogger } from '@hawk.so/core';
18+
*
19+
* const logger = createBrowserLogger('3.2.0');
20+
* setLogger(logger);
21+
*
22+
* // Custom styling
23+
* const styledLogger = createBrowserLogger('3.2.0', 'color: blue; font-weight: bold');
24+
* ```
25+
*/
26+
export function createBrowserLogger(version: string, style = 'color: inherit'): Logger {
27+
return (msg: string, type: LogType = 'log', args?: unknown): void => {
28+
if (!('console' in window)) {
29+
return;
30+
}
31+
32+
const editorLabelText = `Hawk (${version})`;
33+
const editorLabelStyle = `line-height: 1em;
34+
color: #fff;
35+
display: inline-block;
36+
line-height: 1em;
37+
background-color: rgba(0,0,0,.7);
38+
padding: 3px 5px;
39+
border-radius: 3px;
40+
margin-right: 2px`;
41+
42+
try {
43+
switch (type) {
44+
case 'time':
45+
case 'timeEnd':
46+
console[type](`( ${editorLabelText} ) ${msg}`);
47+
break;
48+
case 'log':
49+
case 'warn':
50+
case 'error':
51+
case 'info':
52+
if (args !== undefined) {
53+
console[type](`%c${editorLabelText}%c ${msg} %o`, editorLabelStyle, style, args);
54+
} else {
55+
console[type](`%c${editorLabelText}%c ${msg}`, editorLabelStyle, style);
56+
}
57+
break;
58+
}
59+
} catch (ignored) {}
60+
};
61+
}

packages/javascript/src/modules/fetchTimer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import log from '../utils/log';
1+
import { log } from '@hawk.so/core';
22

33
/**
44
* Sends AJAX request and wait for some time.

packages/javascript/src/modules/socket.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import log from '../utils/log';
1+
import { log } from '@hawk.so/core';
22
import type { CatcherMessage } from '@/types';
33
import type { Transport } from '../types/transport';
44

packages/javascript/src/utils/event.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import log from './log';
1+
import { log } from '@hawk.so/core';
22

33
/**
44
* Symbol to mark error as processed by Hawk

packages/javascript/src/utils/log.ts

Lines changed: 0 additions & 46 deletions
This file was deleted.

packages/javascript/src/utils/validation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import log from './log';
1+
import { log } from '@hawk.so/core';
22
import type { AffectedUser, Breadcrumb, EventContext, EventData, JavaScriptAddons } from '@hawk.so/types';
33
import Sanitizer from '../modules/sanitizer';
44

0 commit comments

Comments
 (0)