Basic Usage
In your terminal, log levels are color-coded:
INFOis blue,SUCCESSis green,WARNINGis yellow,ERRORis red, andCRITICALis bold red.
Root logger
The root logger export is a proxy around a default standalone logger instance.
import { logger } from "@blyp/core";
logger.info("server started on port 3000");
logger.success("database connection established");
logger.warning("rate limit approaching for user 42");
logger.error("failed to reach payment provider");Terminal output:
[INFO] server started on port 3000
[SUCCESS] database connection established
[WARNING] rate limit approaching for user 42
[ERROR] failed to reach payment provider
SUCCESSappears in green,WARNINGin yellow, andERRORin red in a real terminal session.
Log levels
Use the full set of Blyp log levels when you want severity to stay obvious at a glance.
logger.debug("cache lookup: key=session:abc123");
logger.info("server started on port 3000");
logger.success("database connection established");
logger.warning("rate limit approaching", {
userId: 42,
remaining: 10,
});
logger.error("failed to reach payment provider", {
timeoutMs: 5000,
});
logger.critical("out of memory", {
heapUsedPercent: 98,
});Terminal output:
[DEBUG] cache lookup: key=session:abc123
[INFO] server started on port 3000
[SUCCESS] database connection established
[WARNING] rate limit approaching userId=42 remaining=10
[ERROR] failed to reach payment provider timeoutMs=5000
[CRITICAL] out of memory heapUsedPercent=98Structured messages and metadata
Every log method accepts a message and optional extra arguments.
logger.info("user login", {
userId: "usr_123",
tenantId: "tenant_456",
});
logger.table("feature flags", {
betaCheckout: true,
useEdgeCache: false,
});Terminal output:
[INFO] user login userId=usr_123 tenantId=tenant_456
[TABLE] feature flags
betaCheckout=true
useEdgeCache=falseChild loggers
Use child() when you want stable bindings on every log line.
const paymentsLog = logger.child({
service: "payments",
region: "eu-west-1",
});
paymentsLog.info("authorized");
paymentsLog.error("capture failed", { provider: "stripe" });Terminal output:
[INFO] authorized service=payments region=eu-west-1
[ERROR] capture failed service=payments region=eu-west-1 provider=stripeStructured request batches
Use createStructuredLog() when a request or workflow should produce one final structured payload instead of many unrelated lines.
import { createStructuredLog } from "@blyp/core";
const structuredLog = createStructuredLog("checkout", {
service: "web-api",
timestamp: new Date().toISOString(),
});
structuredLog.set({
user: { id: 1, plan: "pro" },
cart: { items: 3, total: 9999 },
payment: { method: "card", status: "success" },
});
structuredLog.emit({
status: 200,
message: "POST /checkout",
});Terminal output on .emit():
[INFO] POST /checkout
service=web-api
user.id=1 user.plan=pro
cart.items=3 cart.total=9999
payment.method=card payment.status=success
status=200Without structured logs - scattered output, hard to correlate:
[INFO] user logged in
[INFO] item added to cart
[INFO] payment processing
[INFO] order createdWith structured logs - one rich event on .emit():
[INFO] POST /checkout
service=web-api
user.id=1 user.plan=pro
cart.items=3 cart.total=9999
payment.method=card payment.status=success
status=200Nothing is logged until
.emit()is called. All.set()calls accumulate context silently. The final emitted event contains everything in one line or structured pretty block.
This is especially useful inside framework handlers because the same root import automatically binds to the active request logger. See Structured Logs for the typed generic form, emit options, and request-scoped behavior.
Dedicated standalone instances
If you need a logger with different level, output directory, or file options, create an instance explicitly.
import { createStandaloneLogger } from "@blyp/core";
const log = createStandaloneLogger({
level: "debug",
pretty: true,
logDir: "logs/payments",
clientLogging: {
enabled: true,
path: "/client-logs",
},
});
log.info("standalone logger ready");Terminal output:
[INFO] standalone logger readyRoot import vs @blyp/core/standalone
Both of these are valid:
import { logger, createStandaloneLogger } from "@blyp/core";Terminal output:
(no terminal output - import only)import type { StandaloneLogger, StandaloneLoggerConfig } from "@blyp/core/standalone";Terminal output:
(no terminal output - type import only)Use the root import for app code and the subpath import when you specifically want standalone type surfaces.