Skip to content

@mantleframework/observability

Unified logging, metrics, tracing, and PII sanitization built on AWS Lambda Powertools and OpenTelemetry.

Logging

logger

Pre-configured Powertools Logger singleton (lazy -- env vars checked on first access, not import).

typescript
import { logger, logInfo, logWarn, logError, logDebug } from '@mantleframework/observability'

// Direct logger usage
logger.info('Processing item', { itemId: '123' })
logger.appendKeys({ correlationId: 'abc' })

// Convenience functions (preferred)
logInfo('Processing item', { itemId: '123' })
logWarn('Rate limit approaching')
logError('Operation failed', { error })
logDebug('Detailed trace info')

createLogger(options?)

Create a custom Logger instance with specific options. Use when you need a logger with different settings than the default singleton.

logDebug(message, data?)

Log at DEBUG level. Used for I/O payloads and troubleshooting.

logInfo(message, data?)

Log at INFO level. Used for business events -- always on in production.

logWarn(message, data?)

Log at WARN level. Used for validation/auth failures -- always on.

logError(message, data?)

Log at ERROR level. Used for handler exceptions -- always on.

Metrics

metrics

Pre-configured Powertools Metrics singleton (lazy -- env vars checked on first access, not import).

typescript
import { metrics, MetricUnit } from '@mantleframework/observability'

metrics.addMetric('ItemsProcessed', MetricUnit.Count, 1)
metrics.addMetric('ProcessingTime', MetricUnit.Milliseconds, 150)

createMetrics(options?)

Create a custom Metrics instance with specific options.

MetricUnit

Enum of CloudWatch metric units: Count, Milliseconds, Seconds, Bytes, Percent, etc.

Middleware

injectLambdaContext(logger)

Middy middleware to inject Lambda context (function name, request ID, cold start) into the logger.

logMetrics(metrics)

Middy middleware to publish accumulated metrics after handler execution.

Tracing (OpenTelemetry)

startSpan(name)

Start a new OpenTelemetry span.

typescript
import { startSpan, endSpan, addAnnotation, addMetadata } from '@mantleframework/observability'

const span = startSpan('database-query')
try {
  addAnnotation(span, 'table', 'users')
  const result = await query()
  addMetadata(span, 'rowCount', result.length)
  endSpan(span)
  return result
} catch (error) {
  endSpan(span, error)
  throw error
}

endSpan(span, error?)

End a span, optionally recording an error.

getCurrentSpan()

Get the currently active span from the OpenTelemetry context.

getTracer()

Get the OpenTelemetry tracer instance.

addAnnotation(span, key, value)

Add an indexed annotation to a span (searchable in X-Ray).

addMetadata(span, key, value)

Add metadata to a span (stored but not indexed).

SpanKind

OpenTelemetry span kind enum (CLIENT, SERVER, INTERNAL, etc.).

Span (type)

OpenTelemetry Span type.

Tracing Wrappers

withTracing(name, fn)

Functional wrapper that executes an async function within a traced span.

typescript
import { withTracing } from '@mantleframework/observability'

const result = await withTracing('my-operation', async () => {
  return await doWork()
})

@Traced(spanName?)

Stage 3 method decorator that wraps a class method with an OpenTelemetry span. Defaults to the method name if no span name is provided.

typescript
import { Traced } from '@mantleframework/observability'

class MyService {
  @Traced('fetch-user')
  static async fetchUser(id: string) {
    // automatically wrapped in a span named 'fetch-user'
  }
}

Logging Config

resolveLoggingConfig(handlerConfig?)

Merge handler-level logging config with environment variable overrides and defaults. Used internally by define*Handler factories.

typescript
import { resolveLoggingConfig } from '@mantleframework/observability'
import type { LoggingConfig, ResolvedLoggingConfig } from '@mantleframework/observability'

const config = resolveLoggingConfig({ logEvent: true, sanitize: true })

LoggingConfig

typescript
interface LoggingConfig {
  logEvent?: boolean           // default: true, env: LOG_EVENT
  logResponse?: boolean        // default: true, env: LOG_RESPONSE
  sanitize?: boolean           // default: true, env: LOG_SANITIZE
  sensitivePatterns?: RegExp[] // default: []
  sampleRate?: number          // Powertools DEBUG sampling rate (0.0-1.0)
}

ResolvedLoggingConfig

Fully-resolved config with all optional fields set (except sampleRate which remains optional).

PII Sanitization

sanitizeData(data, additionalPatterns?)

Recursively redact sensitive fields from a value before logging. Handles objects, arrays, Maps, Sets, and circular references. Primitives and null are returned as-is.

typescript
import { sanitizeData, DEFAULT_SENSITIVE_PATTERNS } from '@mantleframework/observability'

const safe = sanitizeData({ email: 'user@test.com', name: 'Alice' })
// { email: '[REDACTED]', name: 'Alice' }

DEFAULT_SENSITIVE_PATTERNS

Array of RegExp patterns for field names that are redacted by default. Covers:

  • Auth: authorization, token, refreshToken, accessToken, password, apiKey, secret, privateKey, sessionId, csrfToken, jwt, otp, pin, recoveryCode
  • PII: email, phoneNumber, phone, ssn, firstName, lastName, dateOfBirth, dob, birthDate, address, passport, nationalId, taxId, driverLicense
  • PCI-DSS: creditCard, cardNumber, cvv, cvc, pan, expiryDate, accountNumber
  • HIPAA: medicalRecordNumber, mrn, diagnosis
  • Network: ipAddress
  • Environment: uvExposure

Custom patterns per handler:

typescript
const api = defineApiHandler({
  logging: { sensitivePatterns: [/^deviceId$/i, /^customField$/i] },
})

Fixture Logging

logIncomingFixture(name, data, options?)

Log incoming event data for test fixture generation at DEBUG level.

logOutgoingFixture(name, data, options?)

Log outgoing response data for test fixture generation at DEBUG level.

FixtureOptions (type)

Options for fixture logging functions.