Logging Architecture & Structured Log Levels0%

Logging Architecture & Structured Log Levels

Beginner12 min read•Updated: Jul 11, 2026
Study Materials

Logging Architecture & Structured Log Levels in Modern JavaScript

Relying on scattered console.log() calls across an enterprise application produces unreadable, unstructured logs that cannot be indexed or filtered in log aggregation platforms (Datadog, Splunk, ElasticSearch). Implementing a Structured Logging Architecture with formal Log Levels is critical for observability and production monitoring.


1. The Standard Log Levels Hierarchy

In production logging standards (RFC 5424 / Syslog / Winston), log levels follow a strict numerical severity hierarchy:

Output
0: TRACE / DEBUG ──► Verbose internal variable states and function inputs
1: INFO ──► General application lifecycle events (server started, user logged in)
2: WARN ──► Recoverable anomalies (cache miss, deprecated API usage)
3: ERROR ──► Action failed, but application continues (DB query failed)
4: FATAL ──► Unrecoverable crash requiring immediate process termination
Output
Log Level Threshold: [ WARN (Level 2) ]
• DEBUG (0): Suppressed! (Zero CPU/disk overhead in production)
• INFO (1): Suppressed!
• WARN (2): Logged & Processed
• ERROR (3): Logged & Processed

2. Structured JSON Logging

In production, logs must never be raw unstructured strings like "User 42 logged in at 10:00". They must be valid JSON objects with standardized fields:

JSON
{
"timestamp": "2026-03-15T14:32:01.892Z",
"level": "INFO",
"service": "billing-service",
"environment": "production",
"traceId": "c8942a-991f",
"userId": "USR-1049",
"message": "Payment processed successfully",
"metadata": {
"amount": 120.00,
"currency": "USD",
"gatewayLatencyMs": 142
}
}

3. Implementing a Production-Grade Logger Class

JavaScript
const LogLevel = {
DEBUG: 0,
INFO: 1,
WARN: 2,
ERROR: 3,
FATAL: 4
};
 
class Logger {
constructor(serviceName, minLevel = LogLevel.INFO) {
this.serviceName = serviceName;
this.minLevel = minLevel;
}
 
setLevel(level) {
this.minLevel = level;
}
 
#log(levelName, levelValue, message, meta = {}) {
// Suppress logs below active severity threshold
if (levelValue < this.minLevel) return;
 
const logEntry = {
timestamp: new Date().toISOString(),
level: levelName,
service: this.serviceName,
message,
...meta
};
 
// Output as single-line JSON string (NDJSON format for Datadog / CloudWatch)
const jsonOutput = JSON.stringify(logEntry);
 
if (levelValue >= LogLevel.ERROR) {
console.error(jsonOutput);
} else if (levelValue === LogLevel.WARN) {
console.warn(jsonOutput);
} else {
console.log(jsonOutput);
}
}
 
debug(msg, meta) { this.#log('DEBUG', LogLevel.DEBUG, msg, meta); }
info(msg, meta) { this.#log('INFO', LogLevel.INFO, msg, meta); }
warn(msg, meta) { this.#log('WARN', LogLevel.WARN, msg, meta); }
error(msg, meta) { this.#log('ERROR', LogLevel.ERROR, msg, meta); }
fatal(msg, meta) { this.#log('FATAL', LogLevel.FATAL, msg, meta); }
}
 
// Instantiate singleton service logger
export const authLogger = new Logger('AuthService', process.env.NODE_ENV === 'production' ? LogLevel.INFO : LogLevel.DEBUG);

4. Context Enrichment & Trace Correlation

In microservices and distributed frontend apps, correlate logs across multiple API requests using a TraceId or CorrelationId:

JavaScript
class ChildLogger {
constructor(parentLogger, contextualMetadata) {
this.parent = parentLogger;
this.context = contextualMetadata;
}
 
info(msg, meta = {}) {
this.parent.info(msg, { ...this.context, ...meta });
}
 
error(msg, meta = {}) {
this.parent.error(msg, { ...this.context, ...meta });
}
}
 
// Create a child logger enriched with current HTTP request context:
const requestLogger = new ChildLogger(authLogger, {
traceId: 'req_a9821f',
ip: '192.168.1.1'
});
 
requestLogger.info('User authenticated successfully');
// Automatically contains traceId, IP, and serviceName in JSON payload!

Interactive Quiz

Practice Quiz

Question 1
What is the primary benefit of structured JSON logging over plain text strings?
Question 2
In an environment where the logging threshold is configured to WARN, which log levels will be emitted?
Question 3
What is a "Correlation ID" (or Trace ID) in distributed application logging?
Question 4
Why should DEBUG level logs be disabled in production environments?
Question 5
How does a Child Logger pattern simplify contextual logging?
Next Lesson

Integrating Error Tracking (Sentry/Monitoring Concepts)

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext