@millepath/logmanager-client
v0.1.1
Published
Browser SDK client for LogManager
Readme
@millepath/logmanager-client
Browser SDK client for LogManager — send events from the browser to LogManager API securely using RSA-OAEP handshake + HMAC-SHA256 signature.
Installation
npm install @millepath/logmanager-clientUsage
import { LogManager, setupAutocapture } from '@millepath/logmanager-client'
const lm = new LogManager({
mode: 'browser',
client_id: 'client_xxxxx',
public_key: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...',
base_url: 'https://api-logm.millepath.com',
})
// Convenience methods (auto-buffer)
lm.error('Something went wrong', { metadata: { code: 500 } })
lm.audit('User logged in', { metadata: { userId: 1 } })
lm.crash('Out of memory')
lm.support('Ticket #123')
lm.event('click', { target: 'button-submit', page: 'checkout' })
// Flush buffer
await lm.flush()
// Or send directly
await lm.ingest([{
event_type: 'ERROR',
message: 'Direct send',
severity: 'error',
}])API
new LogManager(config)
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| mode | 'browser' | ✅ | Browser mode only |
| client_id | string | ✅ | Client ID from dashboard |
| public_key | string | ✅ | RSA public key (raw base64 DER SPKI) |
| base_url | string | ✅ | Server base URL |
| kid | string | | Key ID (default: 'latest') |
lm.connect()
RSA-OAEP handshake to obtain a session token. Automatically called by ingest() / flush() if not connected.
lm.ingest(events, options?)
Send events directly to the server (bypasses buffer).
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| events | RawEvent[] | | Array of events (max 100) |
| options.format | 'json' \| 'ndjson' | 'json' | Request body format |
lm.disconnect()
Remove session from memory.
lm.flush()
Send all buffered events. Auto-flushes every 5 seconds or when buffer reaches 50 events.
lm.close()
Flush buffer + stop auto-flush timer + disconnect.
Convenience Methods
All these methods buffer events (not sent immediately).
lm.error(message, options?) // event_type: ERROR default severity: error
lm.audit(message, options?) // event_type: AUDIT default severity: info
lm.crash(message, options?) // event_type: CRASH default severity: critical
lm.support(message, options?) // event_type: SUPPORT default severity: info
lm.event(name, metadata?) // AUDIT, for click/hover/etc.EventOptions:
| Field | Type | Description |
|-------|------|-------------|
| severity | Severity | Override severity |
| source | string | Event source |
| timestamp | string | ISO timestamp |
| metadata | object | Additional data |
| environment | string | Environment (production, staging, etc.) |
Autocapture
const cleanup = setupAutocapture(lm, {
error: true, // window.onerror
unhandledRejection: true, // Promise rejection
console: {
level: ['error', 'warn'], // filter methods (string | string[])
include: true, // send to LogManager
},
click: {
selector: 'button, a', // CSS selector
attribute: 'data-track', // read data attribute
},
})
// Remove all listeners + restore console
cleanup()| Feature | Event Type | Detail |
|---------|-----------|--------|
| error | ERROR | Global error + stack trace |
| unhandledRejection | ERROR | Promise rejection + reason |
| console | ERROR | Intercept console.log/warn/error/etc., severity matches level |
| click | AUDIT | Click events (throttled 1s), selector filter, attribute reads data-* |
Event Types
| Event Type | Convenience Method |
|------------|-------------------|
| ERROR | lm.error() |
| AUDIT | lm.audit() / lm.event() |
| AGENT | lm.ingest([{ event_type: 'AGENT', ... }]) |
| CRASH | lm.crash() |
| SUPPORT | lm.support() |
Severity Levels
debug, info, warning, error, critical
NDJSON Format
await lm.ingest(events, { format: 'ndjson' })Error Handling
import { LogManagerError } from '@millepath/logmanager-client'
try {
await lm.ingest([...])
} catch (err) {
if (err instanceof LogManagerError) {
console.error(`[${err.status}] ${err.message}`)
}
}| Status | Meaning |
|--------|---------|
| 400 | Bad request |
| 401 | Invalid session / signature mismatch / timestamp expired |
| 403 | Origin not allowed / client deactivated |
| 404 | Client not found |
| 429 | Rate limit exceeded |
| 413 | Payload exceeds 1 MB |
Security Flow
- Client generates AES 256-bit key
- AES key is encrypted with RSA-OAEP-256 (server's public key)
- Server decrypts with private key, stores session
- Each ingestion request is signed with HMAC-SHA256
- Signature covers
client_id.session_id.expiry— expiry is inside the HMAC, cannot be tampered with
Build
npm run buildLicense
MIT
