Skip to content

@j0nathan-ll0yd/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 "@j0nathan-ll0yd/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 "@j0nathan-ll0yd/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 "@j0nathan-ll0yd/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.).

resetTraceSampling() ​

Clear the cached per-trace sampling decision so the next span rolls a fresh one. The observability wrapper calls it once at the start of every invocation, which keeps each request in a warm container sampled independently while staying internally coherent. Call it directly only in tests.

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 "@j0nathan-ll0yd/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 "@j0nathan-ll0yd/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 "@j0nathan-ll0yd/observability";
import type { LoggingConfig, ResolvedLoggingConfig } from "@j0nathan-ll0yd/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 "@j0nathan-ll0yd/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.

Log-Subscription Alerting ​

createLogSubscriptionNotifier(options?) ​

Build a CloudWatch Logs subscription handler that publishes an SNS notification when a log batch contains errors. This is the cost-free alerting tier: it needs no metric filters and no alarms, so it stays inside the CloudWatch free tier.

typescript
import { createLogSubscriptionNotifier } from "@j0nathan-ll0yd/observability";

export const handler = createLogSubscriptionNotifier({ messageExcerptLength: 300 });

The returned function takes a CloudWatchLogsSubscriptionEvent. Options are LogSubscriptionNotifierOptions; messageExcerptLength (default 300) caps the first and last error excerpts in the SNS body.

Errors from the same function within one delivery are collapsed into a single message with a count. There is no cross-invocation rate limiting, so a sustained error storm still produces one message per log-batch delivery. See Observability Alerting for the wiring.