@smb-tech/logger-react 1.0.0
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/README.md +37 -0
- package/dist/api.d.ts +1 -0
- package/dist/api.js +30 -0
- package/dist/api.js.map +1 -0
- package/dist/context.d.ts +21 -0
- package/dist/context.js +48 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +4 -0
- package/dist/logger.js +29 -0
- package/dist/logger.js.map +1 -0
- package/dist/provider.d.ts +6 -0
- package/dist/provider.js +13 -0
- package/dist/provider.js.map +1 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# @smb-tech/logger-react
|
|
2
|
+
|
|
3
|
+
React/browser adapter for structured logging.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Client-side context store
|
|
8
|
+
- TraceId propagation to backend
|
|
9
|
+
- Compatible with fetch / axios
|
|
10
|
+
- Lightweight
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @smb-tech/logger-react
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Example
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { BrowserContextStore, BrowserTraceContextFactory } from '@smb-tech/logger-react';
|
|
22
|
+
|
|
23
|
+
const context = BrowserTraceContextFactory.create();
|
|
24
|
+
BrowserContextStore.set(context);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Sending trace headers
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
const mdc = BrowserContextStore.getMdc();
|
|
31
|
+
|
|
32
|
+
fetch('/api', {
|
|
33
|
+
headers: {
|
|
34
|
+
'x-b3-traceid': mdc.traceId
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
```
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export {};
|
|
2
|
+
/* import { BrowserContextStore, BrowserTraceContextFactory } from './context.js';
|
|
3
|
+
|
|
4
|
+
export async function apiFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
|
|
5
|
+
if (!BrowserContextStore.get()) {
|
|
6
|
+
BrowserContextStore.set(BrowserTraceContextFactory.create());
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const mdc = BrowserContextStore.getMdc();
|
|
10
|
+
const headers = new Headers(init?.headers);
|
|
11
|
+
|
|
12
|
+
if (mdc.requestId) {
|
|
13
|
+
headers.set('x-request-id', mdc.requestId);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (mdc.traceId) {
|
|
17
|
+
headers.set('X-B3-TraceId', mdc.traceId);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (mdc.spanId) {
|
|
21
|
+
headers.set('X-B3-SpanId', mdc.spanId);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return fetch(input, {
|
|
25
|
+
...init,
|
|
26
|
+
headers
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
*/
|
|
30
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface BrowserTraceContext {
|
|
2
|
+
mdc: Record<string, string>;
|
|
3
|
+
}
|
|
4
|
+
export interface BrowserContextOptions {
|
|
5
|
+
traceId?: string;
|
|
6
|
+
requestId?: string;
|
|
7
|
+
spanId?: string;
|
|
8
|
+
mdc?: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
export declare class BrowserTraceContextFactory {
|
|
11
|
+
static create(options?: BrowserContextOptions): BrowserTraceContext;
|
|
12
|
+
}
|
|
13
|
+
export declare class BrowserContextStore {
|
|
14
|
+
private static context;
|
|
15
|
+
static set(context: BrowserTraceContext): void;
|
|
16
|
+
static get(): BrowserTraceContext | null;
|
|
17
|
+
static getMdc(): Record<string, string>;
|
|
18
|
+
static setMdc(key: string, value: string): void;
|
|
19
|
+
static setManyMdc(values: Record<string, string>): void;
|
|
20
|
+
static clear(): void;
|
|
21
|
+
}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
function createHexId(bytes) {
|
|
2
|
+
const data = new Uint8Array(bytes);
|
|
3
|
+
crypto.getRandomValues(data);
|
|
4
|
+
return Array.from(data, (value) => value.toString(16).padStart(2, '0')).join('');
|
|
5
|
+
}
|
|
6
|
+
export class BrowserTraceContextFactory {
|
|
7
|
+
static create(options) {
|
|
8
|
+
const requestId = options?.requestId ?? crypto.randomUUID();
|
|
9
|
+
const traceId = options?.traceId ?? createHexId(16);
|
|
10
|
+
const spanId = options?.spanId ?? createHexId(8);
|
|
11
|
+
return {
|
|
12
|
+
mdc: {
|
|
13
|
+
requestId,
|
|
14
|
+
traceId,
|
|
15
|
+
spanId,
|
|
16
|
+
...(options?.mdc ?? {})
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class BrowserContextStore {
|
|
22
|
+
static context = null;
|
|
23
|
+
static set(context) {
|
|
24
|
+
this.context = context;
|
|
25
|
+
}
|
|
26
|
+
static get() {
|
|
27
|
+
return this.context;
|
|
28
|
+
}
|
|
29
|
+
static getMdc() {
|
|
30
|
+
return this.context?.mdc ?? {};
|
|
31
|
+
}
|
|
32
|
+
static setMdc(key, value) {
|
|
33
|
+
if (!this.context) {
|
|
34
|
+
this.context = { mdc: {} };
|
|
35
|
+
}
|
|
36
|
+
this.context.mdc[key] = value;
|
|
37
|
+
}
|
|
38
|
+
static setManyMdc(values) {
|
|
39
|
+
if (!this.context) {
|
|
40
|
+
this.context = { mdc: {} };
|
|
41
|
+
}
|
|
42
|
+
Object.assign(this.context.mdc, values);
|
|
43
|
+
}
|
|
44
|
+
static clear() {
|
|
45
|
+
this.context = null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAWA,SAAS,WAAW,CAAC,KAAa;IAChC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,OAAO,0BAA0B;IACrC,MAAM,CAAC,MAAM,CAAC,OAA+B;QAC3C,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;QAEjD,OAAO;YACL,GAAG,EAAE;gBACH,SAAS;gBACT,OAAO;gBACP,MAAM;gBACN,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;aACxB;SACF,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,mBAAmB;IACtB,MAAM,CAAC,OAAO,GAA+B,IAAI,CAAC;IAE1D,MAAM,CAAC,GAAG,CAAC,OAA4B;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,MAAM,CAAC,GAAG;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,GAAW,EAAE,KAAa;QACtC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;QAC7B,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAChC,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,MAA8B;QAC9C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;QAC7B,CAAC;QAED,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,CAAC,KAAK;QACV,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
|
package/dist/logger.d.ts
ADDED
package/dist/logger.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Logger } from '@smb-tech/logger-core';
|
|
2
|
+
import { BrowserContextStore } from './context.js';
|
|
3
|
+
class BrowserLogSink {
|
|
4
|
+
dispatch(line, level) {
|
|
5
|
+
if (level === 'ERROR' || level === 'WARN') {
|
|
6
|
+
console.error(line);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
console.log(line);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
class BrowserRuntimeDetailsProvider {
|
|
13
|
+
getThreadLabel() {
|
|
14
|
+
return 'browser-main-thread';
|
|
15
|
+
}
|
|
16
|
+
fallbackId() {
|
|
17
|
+
return crypto.randomUUID();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const sink = new BrowserLogSink();
|
|
21
|
+
const runtimeDetailsProvider = new BrowserRuntimeDetailsProvider();
|
|
22
|
+
export class ReactLogger {
|
|
23
|
+
static get(contextName) {
|
|
24
|
+
return new Logger(contextName, {
|
|
25
|
+
getMdc: () => BrowserContextStore.getMdc()
|
|
26
|
+
}, sink, runtimeDetailsProvider);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,cAAc;IAClB,QAAQ,CAAC,IAAY,EAAE,KAAe;QACpC,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YAC1C,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;CACF;AAED,MAAM,6BAA6B;IACjC,cAAc;QACZ,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IAED,UAAU;QACR,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,IAAI,GAAG,IAAI,cAAc,EAAE,CAAC;AAClC,MAAM,sBAAsB,GAAG,IAAI,6BAA6B,EAAE,CAAC;AAEnE,MAAM,OAAO,WAAW;IACtB,MAAM,CAAC,GAAG,CAAC,WAAmB;QAC5B,OAAO,IAAI,MAAM,CACf,WAAW,EACX;YACE,MAAM,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,MAAM,EAAE;SAC3C,EACD,IAAI,EACJ,sBAAsB,CACvB,CAAC;IACJ,CAAC;CACF"}
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { BrowserContextStore, BrowserTraceContextFactory } from './context.js';
|
|
4
|
+
export function LoggingProvider({ children }) {
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
const existing = BrowserContextStore.get();
|
|
7
|
+
if (!existing) {
|
|
8
|
+
BrowserContextStore.set(BrowserTraceContextFactory.create());
|
|
9
|
+
}
|
|
10
|
+
}, []);
|
|
11
|
+
return _jsx(_Fragment, { children: children });
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAM/E,MAAM,UAAU,eAAe,CAAC,EAAE,QAAQ,EAAwB;IAChE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,EAAE,CAAC;QAC3C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,mBAAmB,CAAC,GAAG,CAAC,0BAA0B,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,4BAAG,QAAQ,GAAI,CAAC;AACzB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@smb-tech/logger-react",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "React/browser adapter for structured logging with client-side context management",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.json"
|
|
21
|
+
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@smb-tech/logger-core": "1.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/react": "^18.3.20",
|
|
30
|
+
"typescript": "^5.8.2"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
}
|
|
35
|
+
}
|