@smb-tech/logger-react
v1.0.2
Published
React/browser adapter for structured logging with client-side context management
Maintainers
Readme
@smb-tech/logger-react
React/browser adapter for @smb-tech/logger-core.
It provides browser trace context, React initialization, browser logging, and helpers for propagating tracing headers through fetch or Axios.
Installation
npm install @smb-tech/logger-reactThis package depends on @smb-tech/logger-core and has a peer dependency on React.
Setup
Wrap your React app with LoggingProvider:
import React from 'react';
import ReactDOM from 'react-dom/client';
import { LoggingProvider } from '@smb-tech/logger-react';
import { App } from './App';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<LoggingProvider
level={import.meta.env.VITE_LOG_LEVEL}
timezone={import.meta.env.VITE_LOGGER_TIMEZONE}
sensitiveKeys={['authorization', 'password', 'token']}
>
<App />
</LoggingProvider>
</React.StrictMode>
);For Vite, use:
VITE_LOG_LEVEL=INFO
VITE_LOGGER_TIMEZONE=UTCtimezone formats the single ts field with the configured IANA timezone. Leave it unset, or set it to UTC, to keep the default UTC ts format.
Browser Logging
import { BrowserContextStore, ReactLogger } from '@smb-tech/logger-react';
const logger = ReactLogger.get('ProfilePage');
BrowserContextStore.setMdc('screen', 'profile');
logger.info((event) => {
event
.message('Profile saved')
.tag('ui')
.with('section', 'preferences');
});Logs are written to the browser console as JSON strings.
Context
Create a browser trace context manually:
import { BrowserContextStore, BrowserTraceContextFactory } from '@smb-tech/logger-react';
const context = BrowserTraceContextFactory.create({
mdc: {
screen: 'checkout'
}
});
BrowserContextStore.set(context);Read the current MDC:
const mdc = BrowserContextStore.getMdc();
console.log(mdc.traceId, mdc.spanId);Add metadata:
BrowserContextStore.setMdc('feature', 'checkout');
BrowserContextStore.setManyMdc({
tenantId: 'tenant-1',
flow: 'checkout-submit'
});Clear context:
BrowserContextStore.clear();HTTP Trace Modes
Browser request helpers support three modes:
root: creates a new execution context.child: keeps currenttraceId, creates a newspanId, and setsparentSpanId.reuse: uses the current context if it exists, otherwise creates one.
Fetch
import { apiFetch } from '@smb-tech/logger-react';
const response = await apiFetch('http://localhost:3000/health', undefined, {
mode: 'root',
mdc: {
flow: 'frontend-to-backend'
}
});
const payload = await response.json();For manual fetch control:
import { prepareTraceRequestInit } from '@smb-tech/logger-react';
const request = prepareTraceRequestInit({
method: 'POST',
body: JSON.stringify({ name: 'Ada' })
}, {
mode: 'root',
mdc: {
flow: 'create-user'
}
});
await fetch('/api/users', request.init);Axios
import axios, { AxiosHeaders } from 'axios';
import { getTraceHeaders, resolveBrowserHttpContext } from '@smb-tech/logger-react';
export const apiClient = axios.create({
baseURL: 'http://localhost:3000'
});
apiClient.interceptors.request.use((config) => {
const context = resolveBrowserHttpContext({ mode: 'reuse' });
const headers = AxiosHeaders.from(config.headers);
Object.entries(getTraceHeaders(context)).forEach(([key, value]) => {
headers.set(key, value);
});
config.headers = headers;
return config;
});Start a new trace before a specific flow:
import { startHttpExecutionContext } from '@smb-tech/logger-react';
const context = startHttpExecutionContext({
mdc: {
flow: 'frontend-to-backend'
}
});
console.log(context.mdc.traceId);API Reference
Context:
BrowserTraceContextFactory.create(options?)BrowserTraceContextFactory.createExecution(options?)BrowserTraceContextFactory.createChildExecution(options?)BrowserContextStore.set(context)BrowserContextStore.get()BrowserContextStore.getMdc()BrowserContextStore.getPersistentMdc()BrowserContextStore.setMdc(key, value)BrowserContextStore.setManyMdc(values)BrowserContextStore.clear()
HTTP:
startHttpExecutionContext(options?)startHttpChildExecutionContext(options?)resolveBrowserHttpContext(options?)getTraceHeaders(context?)applyBrowserTraceHeaders(headers, context?)prepareTraceRequestInit(init?, options?)apiFetch(input, init?, options?)
Logging:
ReactLogger.get(contextName)LoggingProvider
Headers
The browser helpers send:
x-request-idX-B3-TraceIdX-B3-SpanIdX-B3-ParentSpanId
Your backend must allow those headers in CORS preflight responses.
