Richer HTTP logging, context tree, and startup banner#255
Conversation
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdds multi-line log output with a configurable context-tree renderer, new logger options for service/thresholds/verbosity, replaces the single-line formatter with Changes
Sequence Diagram(s)sequenceDiagram
actor Client
participant Logger
participant Formatter as formatLogOutput()
participant ContextTree as buildContextTree()
participant Console as Console/Transport
Client->>Logger: incoming HTTP request / event
Logger->>Formatter: formatLogOutput(level, meta, options)
Formatter->>ContextTree: expand data.context (contextDepth, showContextTree)
ContextTree-->>Formatter: return contextLines[]
Formatter->>Formatter: build main line (tokens: icon, service, statusText, speed)
Formatter-->>Logger: { main, contextLines }
Logger->>Console: log main (append contextLines if any)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/logixlysia/src/logger/create-logger.ts (1)
165-199:⚠️ Potential issue | 🟡 MinorPadding before classification makes every colored method fall back to white.
getColoredMethod()compares against exact tokens likeGET, but it now receives padded values such asGET. In TTY output, all known methods will miss their branch and use the fallback style.🎨 Suggested fix
const getColoredMethod = (method: string, useColors: boolean): string => { - if (!useColors) { - return method - } - const upper = method.toUpperCase() + const padded = upper.padEnd(METHOD_PAD) + + if (!useColors) { + return padded + } + if (upper === 'GET') { - return chalk.green.bold(upper) + return chalk.green.bold(padded) } if (upper === 'POST') { - return chalk.blue.bold(upper) + return chalk.blue.bold(padded) } if (upper === 'PUT') { - return chalk.yellow.bold(upper) + return chalk.yellow.bold(padded) } if (upper === 'PATCH') { - return chalk.yellowBright.bold(upper) + return chalk.yellowBright.bold(padded) } if (upper === 'DELETE') { - return chalk.red.bold(upper) + return chalk.red.bold(padded) } if (upper === 'OPTIONS') { - return chalk.cyan.bold(upper) + return chalk.cyan.bold(padded) } if (upper === 'HEAD') { - return chalk.greenBright.bold(upper) + return chalk.greenBright.bold(padded) } if (upper === 'TRACE') { - return chalk.magenta.bold(upper) + return chalk.magenta.bold(padded) } if (upper === 'CONNECT') { - return chalk.cyanBright.bold(upper) + return chalk.cyanBright.bold(padded) } - return chalk.white.bold(upper) + return chalk.white.bold(padded) } @@ - const methodPadded = request.method.toUpperCase().padEnd(METHOD_PAD) - const coloredMethod = getColoredMethod(methodPadded, useColors) + const coloredMethod = getColoredMethod(request.method, useColors)Also applies to: 441-442
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/logixlysia/src/logger/create-logger.ts` around lines 165 - 199, getColoredMethod is comparing the raw method string against exact tokens but receives padded values (e.g., "GET "), causing every known method to hit the fallback; fix it by trimming whitespace before classification (use method.trim() then toUpperCase()) so comparisons use the normalized token (update the local `upper` calculation in getColoredMethod and the other similar occurrence around the 441-442 area).
🧹 Nitpick comments (2)
packages/logixlysia/src/extensions/banner.ts (1)
57-61: Minor: Simplify spread in Math.max call.The spread
...(logixlysiaLine ? [logixlysiaLine.length] : [0])could be simplified sinceMath.maxignores additional arguments. Using0directly would suffice whenlogixlysiaLineis null.Suggested simplification
const contentWidth = Math.max( versionLine.length, urlDisplayLine.length, - ...(logixlysiaLine ? [logixlysiaLine.length] : [0]) + logixlysiaLine?.length ?? 0 )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/logixlysia/src/extensions/banner.ts` around lines 57 - 61, The Math.max invocation used to compute contentWidth is overly complex: replace Math.max(versionLine.length, urlDisplayLine.length, ...(logixlysiaLine ? [logixlysiaLine.length] : [0])) with a simpler call that passes 0 when logixlysiaLine is falsy (e.g., Math.max(versionLine.length, urlDisplayLine.length, logixlysiaLine ? logixlysiaLine.length : 0)); update the expression that defines contentWidth to use versionLine, urlDisplayLine, and the conditional logixlysiaLine.length directly.packages/logixlysia/src/logger/create-logger.ts (1)
291-332: Preferfor...ofappends in the context-tree helpers.Both helpers are on the per-request formatting path, and the current spread-into-accumulator plus indexed loop add avoidable churn for something that can stay simple with
for...of.As per coding guidelines, "Prefer `for...of` loops over `.forEach()` and indexed `for` loops" and "Avoid spread syntax in accumulators within loops."♻️ Suggested cleanup
const collectContextEntries = ( obj: Record<string, unknown>, prefix: string, depthRemaining: number ): [string, string][] => { const out: [string, string][] = [] for (const [k, v] of Object.entries(obj)) { const key = prefix ? `${prefix}.${k}` : k const expandable = isExpandableObject(v) && depthRemaining > 1 if (expandable) { - out.push(...collectContextEntries(v, key, depthRemaining - 1)) + for (const entry of collectContextEntries(v, key, depthRemaining - 1)) { + out.push(entry) + } } else { out.push([key, stringifyTreeValue(v)]) } } return out } @@ - for (let i = 0; i < entries.length; i++) { - const branch = i === last ? '└─' : '├─' - const pair = entries[i] - if (!pair) { - continue - } - const [k, v] = pair + for (const [i, [k, v]] of entries.entries()) { + const branch = i === last ? '└─' : '├─' const keyPart = useColors ? chalk.cyan(k) : k const valPart = useColors ? chalk.white(v) : v lines.push(` ${branch} ${keyPart} ${valPart}`) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/logixlysia/src/logger/create-logger.ts` around lines 291 - 332, The helpers collectContextEntries and formatEntriesToTreeLines use spread-into-accumulator and an indexed for loop which causes extra churn; replace the spread call out.push(...collectContextEntries(v, key, depthRemaining - 1)) with a direct for...of over the recursive result (for (const entry of collectContextEntries(...)) out.push(entry)) in collectContextEntries, and rewrite the indexed for loop in formatEntriesToTreeLines to a for...of over entries.entries() (or maintain a simple counter) to get index and pair (so you can still compute last and branch) and push directly into lines without using array indexing or spread; keep existing key/value coloring and continue to guard for falsy pair if desired.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/logixlysia/src/logger/create-logger.ts`:
- Around line 430-438: formatLine() currently inherits the new default
showContextTree behavior so ctxString becomes empty for non-empty object
contexts and breaks existing one-line `{context}` users; inside formatLine()
(the function computing ctxString using showTree, ctxString, and
getContextString) override the config to force showContextTree:false (or
otherwise detect callers expecting one-line context) so that
getContextString(data.context) is used for object contexts, preserving the old
one-line payload; update the same logic at the other occurrence (the block
around the second instance noted) to apply the same override.
---
Outside diff comments:
In `@packages/logixlysia/src/logger/create-logger.ts`:
- Around line 165-199: getColoredMethod is comparing the raw method string
against exact tokens but receives padded values (e.g., "GET "), causing every
known method to hit the fallback; fix it by trimming whitespace before
classification (use method.trim() then toUpperCase()) so comparisons use the
normalized token (update the local `upper` calculation in getColoredMethod and
the other similar occurrence around the 441-442 area).
---
Nitpick comments:
In `@packages/logixlysia/src/extensions/banner.ts`:
- Around line 57-61: The Math.max invocation used to compute contentWidth is
overly complex: replace Math.max(versionLine.length, urlDisplayLine.length,
...(logixlysiaLine ? [logixlysiaLine.length] : [0])) with a simpler call that
passes 0 when logixlysiaLine is falsy (e.g., Math.max(versionLine.length,
urlDisplayLine.length, logixlysiaLine ? logixlysiaLine.length : 0)); update the
expression that defines contentWidth to use versionLine, urlDisplayLine, and the
conditional logixlysiaLine.length directly.
In `@packages/logixlysia/src/logger/create-logger.ts`:
- Around line 291-332: The helpers collectContextEntries and
formatEntriesToTreeLines use spread-into-accumulator and an indexed for loop
which causes extra churn; replace the spread call
out.push(...collectContextEntries(v, key, depthRemaining - 1)) with a direct
for...of over the recursive result (for (const entry of
collectContextEntries(...)) out.push(entry)) in collectContextEntries, and
rewrite the indexed for loop in formatEntriesToTreeLines to a for...of over
entries.entries() (or maintain a simple counter) to get index and pair (so you
can still compute last and branch) and push directly into lines without using
array indexing or spread; keep existing key/value coloring and continue to guard
for falsy pair if desired.
🪄 Autofix (Beta)
❌ Autofix failed (check again to retry)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c16d492c-a9e8-4323-a4ca-f19fb6ba4d7b
📒 Files selected for processing (11)
.changeset/rich-logging-banner.mdapps/elysia/src/routers/index.tspackages/logixlysia/__tests__/extensions/start-server.test.tspackages/logixlysia/__tests__/logger/create-logger.test.tspackages/logixlysia/__tests__/logger/format-output.test.tspackages/logixlysia/src/extensions/banner.tspackages/logixlysia/src/extensions/index.tspackages/logixlysia/src/interfaces.tspackages/logixlysia/src/logger/create-logger.tspackages/logixlysia/src/logger/handle-http-error.tspackages/logixlysia/src/logger/index.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: 🏗️ Build
- GitHub Check: agent
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Preferunknownoveranywhen the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions
Files:
packages/logixlysia/__tests__/logger/create-logger.test.tspackages/logixlysia/src/logger/index.tspackages/logixlysia/src/logger/handle-http-error.tspackages/logixlysia/src/extensions/index.tsapps/elysia/src/routers/index.tspackages/logixlysia/__tests__/extensions/start-server.test.tspackages/logixlysia/src/interfaces.tspackages/logixlysia/src/extensions/banner.tspackages/logixlysia/__tests__/logger/format-output.test.tspackages/logixlysia/src/logger/create-logger.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{ts,tsx,js,jsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Preferfor...ofloops over.forEach()and indexedforloops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Useconstby default,letonly when reassignment is needed, nevervar
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Removeconsole.log,debugger, andalertstatements from production code
ThrowErrorobjects with descriptive messages, not strings or other values
Usetry-catchblocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Keep functions focused and under reasonable cognitive complexity limits
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Group related code together and separate concerns
Don't useeval()or assign directly todocument.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use proper image components (e.g., Next.js<Image>) over<img>tags
Files:
packages/logixlysia/__tests__/logger/create-logger.test.tspackages/logixlysia/src/logger/index.tspackages/logixlysia/src/logger/handle-http-error.tspackages/logixlysia/src/extensions/index.tsapps/elysia/src/routers/index.tspackages/logixlysia/__tests__/extensions/start-server.test.tspackages/logixlysia/src/interfaces.tspackages/logixlysia/src/extensions/banner.tspackages/logixlysia/__tests__/logger/format-output.test.tspackages/logixlysia/src/logger/create-logger.ts
**/*.{test,spec}.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{test,spec}.{ts,tsx,js,jsx}: Write assertions insideit()ortest()blocks
Avoid done callbacks in async tests - use async/await instead
Don't use.onlyor.skipin committed code
Keep test suites reasonably flat - avoid excessivedescribenesting
Files:
packages/logixlysia/__tests__/logger/create-logger.test.tspackages/logixlysia/__tests__/extensions/start-server.test.tspackages/logixlysia/__tests__/logger/format-output.test.ts
**/index.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Avoid barrel files (index files that re-export everything)
Files:
packages/logixlysia/src/logger/index.tspackages/logixlysia/src/extensions/index.tsapps/elysia/src/routers/index.ts
🧠 Learnings (2)
📚 Learning: 2025-12-21T17:02:32.986Z
Learnt from: CR
Repo: PunGrumpy/logixlysia PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-12-21T17:02:32.986Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Write assertions inside `it()` or `test()` blocks
Applied to files:
packages/logixlysia/__tests__/logger/create-logger.test.tspackages/logixlysia/__tests__/logger/format-output.test.ts
📚 Learning: 2025-12-21T17:02:32.986Z
Learnt from: CR
Repo: PunGrumpy/logixlysia PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-12-21T17:02:32.986Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Keep test suites reasonably flat - avoid excessive `describe` nesting
Applied to files:
packages/logixlysia/__tests__/logger/create-logger.test.tspackages/logixlysia/__tests__/logger/format-output.test.ts
🔇 Additional comments (16)
packages/logixlysia/src/extensions/banner.ts (3)
12-19: LGTM! Clean version loading pattern.The IIFE pattern for loading the logixlysia package version mirrors the existing
elysiaPkgapproach, maintaining consistency. Error handling gracefully falls back to an empty object.
31-84: Well-structured row-spec model for banner rendering.The discriminated union
RowSpecand the row-based rendering loop cleanly separate layout specification from rendering logic. Thefor...ofloop at line 69 aligns with coding guidelines.
86-92: LGTM! Clean helper function.The function correctly returns
nullwhen no version is available, enabling the caller to conditionally include the line.packages/logixlysia/src/extensions/index.ts (2)
2-2: LGTM! Import updated correctly.The import now includes
getLogixlysiaVersionLineto support the new banner signature.
18-28: Clean separation of simple vs banner formats.The code maintains backward compatibility for the
simpleformat while using the new two-argumentrenderBannercall for the banner format. The extra space inurlDisplayLine(🦊 ${url}) is intentional for banner visual alignment.packages/logixlysia/__tests__/logger/create-logger.test.ts (2)
2-2: LGTM! Type import added for proper casting.Importing the
pinotype allows for explicit casting of test doubles, improving type safety.
104-104: Proper test double typing pattern.The
as unknown as typeof pinodouble-cast is the correct approach when the fake doesn't fully implement the real interface. This pattern is consistently applied across all affected tests.packages/logixlysia/__tests__/extensions/start-server.test.ts (2)
26-43: Simple format test correctly preserved.The test for the simple message format verifies the original combined message string
'🦊 Elysia is running at http://localhost:3000', which is still used whenstartupMessageFormat: 'simple'is configured.
19-21: No actionable concern - assertion correctly verifies version inclusion.The test correctly asserts that the banner output contains
'logixlysia v'. ThegetLogixlysiaVersionLine()function includes proper error handling and returnsnullonly if the version is unavailable—in which case the banner gracefully omits that line and the test assertion appropriately fails, indicating an actual problem. This is correct test behavior, not brittleness. The package.json is accessible in the test environment with version "6.2.3" available.packages/logixlysia/src/logger/index.ts (2)
13-13: LGTM! Import updated to new formatting API.The import correctly switches from
formatLinetoformatLogOutputto support the new multi-line logging format.
102-110: Clean message assembly from formatLogOutput result.The destructuring and conditional concatenation correctly handles both single-line and multi-line output scenarios. The pattern
contextLines.length > 0check before joining is appropriate.packages/logixlysia/src/logger/handle-http-error.ts (2)
5-5: LGTM! Import updated to match new API.The import correctly uses
formatLogOutputfrom the create-logger module.
59-68: Consistent message assembly pattern.The message assembly logic mirrors the pattern in
index.ts(lines 102-110). While this is duplicated, the scope is small enough that extracting a helper would add unnecessary indirection.apps/elysia/src/routers/index.ts (1)
12-18: Demo app updated to showcase new logger options.The configuration demonstrates the new features:
service, performance thresholds, and context tree. Note thatslowThreshold: 500,verySlowThreshold: 1000, andshowContextTree: truematch the defaults defined increate-logger.ts, so they're illustrative for the demo rather than functional overrides.packages/logixlysia/src/interfaces.ts (1)
77-86: Well-documented interface additions.The new configuration options are properly typed and documented with JSDoc comments that include default values. The defaults mentioned (500, 1000, true, 1) match the implementations in
create-logger.ts(per context snippets showingDEFAULT_SLOW_MS = 500,DEFAULT_VERY_SLOW_MS = 1000, and inline defaults forshowContextTreeandcontextDepth).packages/logixlysia/__tests__/logger/format-output.test.ts (1)
10-184: Nice coverage on the formatter split.These cases pin the new
main/contextLinescontract, threshold handling, and nested/error context rendering well.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
…logging options - Added new configuration options: `service`, `slowThreshold`, `verySlowThreshold`, `showContextTree`, and `contextDepth` to the API reference. - Updated the usage documentation to reflect changes in placeholder descriptions, including `statusText`, `icon`, and `speed`. - Improved formatting section to clarify the use of placeholders in custom log formats and the context tree feature.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
packages/logixlysia/src/logger/create-logger.ts (1)
362-372: ReuseisExpandableObject(ctx)here instead of the casts.This branch re-implements the same narrowing rules and then asserts
ctxtwice. Using the existing type guard keeps the top-level check aligned with the recursive renderer and removes the assertions.♻️ Suggested cleanup
- if ( - ctx && - typeof ctx === 'object' && - !Array.isArray(ctx) && - Object.keys(ctx as object).length > 0 && - depth >= 1 - ) { - entries.push( - ...collectContextEntries(ctx as Record<string, unknown>, '', depth) - ) + if (isExpandableObject(ctx) && Object.keys(ctx).length > 0 && depth >= 1) { + entries.push(...collectContextEntries(ctx, '', depth)) }As per coding guidelines, "Leverage TypeScript's type narrowing instead of type assertions".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/logixlysia/src/logger/create-logger.ts` around lines 362 - 372, Replace the manual typeof/Array/Object.keys type checks and double-cast of ctx with the existing type guard isExpandableObject to keep type narrowing consistent: in create-logger where ctx is evaluated before calling collectContextEntries, use isExpandableObject(ctx) && depth >= 1 and then call collectContextEntries(ctx, '', depth) without casting; this removes the redundant assertions and aligns the top-level check with the recursive renderer logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/logixlysia/src/logger/create-logger.ts`:
- Around line 430-438: The current ctxString branch uses getContextString()
(which does a raw JSON.stringify) and can throw on circular arrays/objects;
change this path to use the same safe stringify strategy as stringifyTreeValue()
instead of getContextString() whenever showTree is false or when context is an
array, and update the deprecated formatLine() shim (which forces
showContextTree: false) to also call stringifyTreeValue() for its context
serialization; locate references to showTree, ctxString, getContextString,
stringifyTreeValue, and formatLine to replace the unsafe JSON.stringify usage
with the safer stringifyTreeValue approach.
- Around line 441-442: The code pads the HTTP verb before calling
getColoredMethod, causing mismatches (methodPadded like "GET ") so the color
branches never match; instead pass the raw verb (request.method or
request.method.toUpperCase()) into getColoredMethod and move padding into the
helper (or add a padSize parameter to getColoredMethod and do padEnd(METHOD_PAD)
inside it), then apply coloring and return the already-padded colored string;
update the getColoredMethod signature and call sites accordingly (referencing
methodPadded, getColoredMethod, request.method, METHOD_PAD).
- Around line 334-345: The renderContextTreeLines function accepts
options.config?.contextDepth which may be Infinity and lead to unbounded
recursion; normalize and clamp that value to a finite non-negative integer
(e.g., let depth = Number.isFinite(rawDepth) ? Math.max(0, Math.floor(rawDepth))
: DEFAULT_MAX_DEPTH) and reuse that normalized depth when calling
collectContextEntries and formatEntriesToTreeLines; apply the same
normalization/clamping pattern to the other context-depth usage (the block
around collectContextEntries/formatEntriesToTreeLines at the later occurrence)
so both helpers receive the safe integer depth.
---
Nitpick comments:
In `@packages/logixlysia/src/logger/create-logger.ts`:
- Around line 362-372: Replace the manual typeof/Array/Object.keys type checks
and double-cast of ctx with the existing type guard isExpandableObject to keep
type narrowing consistent: in create-logger where ctx is evaluated before
calling collectContextEntries, use isExpandableObject(ctx) && depth >= 1 and
then call collectContextEntries(ctx, '', depth) without casting; this removes
the redundant assertions and aligns the top-level check with the recursive
renderer logic.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5daaa79e-9c9a-4a75-92e0-2e8a28c53e6a
📒 Files selected for processing (1)
packages/logixlysia/src/logger/create-logger.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Preferunknownoveranywhen the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions
Files:
packages/logixlysia/src/logger/create-logger.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{ts,tsx,js,jsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Preferfor...ofloops over.forEach()and indexedforloops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Useconstby default,letonly when reassignment is needed, nevervar
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Removeconsole.log,debugger, andalertstatements from production code
ThrowErrorobjects with descriptive messages, not strings or other values
Usetry-catchblocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Keep functions focused and under reasonable cognitive complexity limits
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Group related code together and separate concerns
Don't useeval()or assign directly todocument.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use proper image components (e.g., Next.js<Image>) over<img>tags
Files:
packages/logixlysia/src/logger/create-logger.ts
| export const renderContextTreeLines = ( | ||
| ctx: Record<string, unknown>, | ||
| options: Options, | ||
| useColors: boolean | ||
| ): string[] => { | ||
| const depth = options.config?.contextDepth ?? 1 | ||
| if (depth < 1) { | ||
| return [] | ||
| } | ||
|
|
||
| const entries = collectContextEntries(ctx, '', depth) | ||
| return formatEntriesToTreeLines(entries, useColors) |
There was a problem hiding this comment.
Clamp contextDepth to a finite integer before recursing.
depth < 1 still accepts Infinity, and Infinity - 1 stays Infinity. If a caller uses contextDepth: Infinity to mean “expand all”, a cyclic context object will recurse until the stack blows. Please normalize once with something like Number.isFinite() + integer clamping and reuse that value in both helpers.
Also applies to: 357-359
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/logixlysia/src/logger/create-logger.ts` around lines 334 - 345, The
renderContextTreeLines function accepts options.config?.contextDepth which may
be Infinity and lead to unbounded recursion; normalize and clamp that value to a
finite non-negative integer (e.g., let depth = Number.isFinite(rawDepth) ?
Math.max(0, Math.floor(rawDepth)) : DEFAULT_MAX_DEPTH) and reuse that normalized
depth when calling collectContextEntries and formatEntriesToTreeLines; apply the
same normalization/clamping pattern to the other context-depth usage (the block
around collectContextEntries/formatEntriesToTreeLines at the later occurrence)
so both helpers receive the safe integer depth.
| const showTree = config?.showContextTree !== false | ||
| const ctxString = | ||
| showTree && | ||
| data.context && | ||
| typeof data.context === 'object' && | ||
| !Array.isArray(data.context) && | ||
| Object.keys(data.context as object).length > 0 | ||
| ? '' | ||
| : getContextString(data.context) |
There was a problem hiding this comment.
Inline {context} can still throw on circular values.
This path falls back to getContextString() whenever the tree is disabled, and arrays always go through it. getContextString() does a raw JSON.stringify(), so a circular array/object will raise while formatting logs. That also affects the deprecated formatLine() shim, because it forces showContextTree: false. Please switch this path to the same safe stringify strategy used by stringifyTreeValue().
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/logixlysia/src/logger/create-logger.ts` around lines 430 - 438, The
current ctxString branch uses getContextString() (which does a raw
JSON.stringify) and can throw on circular arrays/objects; change this path to
use the same safe stringify strategy as stringifyTreeValue() instead of
getContextString() whenever showTree is false or when context is an array, and
update the deprecated formatLine() shim (which forces showContextTree: false) to
also call stringifyTreeValue() for its context serialization; locate references
to showTree, ctxString, getContextString, stringifyTreeValue, and formatLine to
replace the unsafe JSON.stringify usage with the safer stringifyTreeValue
approach.
| const methodPadded = request.method.toUpperCase().padEnd(METHOD_PAD) | ||
| const coloredMethod = getColoredMethod(methodPadded, useColors) |
There was a problem hiding this comment.
Pass the raw verb into getColoredMethod().
Line 441 pads before classification, so getColoredMethod() receives values like GET and POST . None of those match the exact verb branches, which means colored output falls through to the default white style for every method. Padding needs to happen after the verb has been matched, inside the helper.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/logixlysia/src/logger/create-logger.ts` around lines 441 - 442, The
code pads the HTTP verb before calling getColoredMethod, causing mismatches
(methodPadded like "GET ") so the color branches never match; instead pass
the raw verb (request.method or request.method.toUpperCase()) into
getColoredMethod and move padding into the helper (or add a padSize parameter to
getColoredMethod and do padEnd(METHOD_PAD) inside it), then apply coloring and
return the already-padded colored string; update the getColoredMethod signature
and call sites accordingly (referencing methodPadded, getColoredMethod,
request.method, METHOD_PAD).
…options - Enhanced the demo code to include new logging options: `service`, `showContextTree`, `contextDepth`, `slowThreshold`, and `verySlowThreshold`. - Updated the README to align with the changes in the demo, ensuring accurate documentation of the new features and their usage.
…ry structure - Updated the Background component to improve accessibility and visual styling. - Refactored log entry structure to include new properties: `durationMs`, `service`, `message`, and `contextLines`. - Adjusted HTTP method color coding for better clarity. - Introduced utility functions for formatting timestamps and durations, enhancing log readability.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/docs/app/(home)/components/playground/index.tsx (1)
186-191: Consider using a generic placeholder instead of an email.The demo data includes
email: 'ada@example.com'. While this is clearly fake data usingexample.com, consider using a non-email identifier like{ key: 'accountId', value: 'acct_123' }to avoid implicitly suggesting that logging emails is a common practice.🔧 Optional: Replace email with generic identifier
contextLines: [ - { key: 'email', value: 'ada@example.com' }, + { key: 'accountId', value: 'acct_456' }, { key: 'feature', value: 'signup-flow' } ]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/docs/app/`(home)/components/playground/index.tsx around lines 186 - 191, Replace the fake email in the demo contextLines with a non-email generic identifier to avoid implying emails should be logged; locate the object literal that has message: 'User signup' and the contextLines array and change the entry { key: 'email', value: 'ada@example.com' } to something like { key: 'accountId', value: 'acct_123' } (or another non-email key/value) so the demo uses a generic identifier instead of an email address.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@apps/docs/app/`(home)/components/playground/index.tsx:
- Around line 186-191: Replace the fake email in the demo contextLines with a
non-email generic identifier to avoid implying emails should be logged; locate
the object literal that has message: 'User signup' and the contextLines array
and change the entry { key: 'email', value: 'ada@example.com' } to something
like { key: 'accountId', value: 'acct_123' } (or another non-email key/value) so
the demo uses a generic identifier instead of an email address.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d92939ae-324c-470f-a7db-918d2a26ea6c
⛔ Files ignored due to path filters (1)
apps/docs/content/(docs)/preview.pngis excluded by!**/*.png
📒 Files selected for processing (8)
apps/docs/app/(home)/components/demo.tsxapps/docs/app/(home)/components/playground/background.tsxapps/docs/app/(home)/components/playground/index.tsxapps/docs/content/(docs)/api-reference.mdxapps/docs/content/(docs)/configuration.mdxapps/docs/content/(docs)/usage.mdxapps/docs/content/features/formatting.mdxpackages/logixlysia/README.md
✅ Files skipped from review due to trivial changes (3)
- apps/docs/content/(docs)/api-reference.mdx
- apps/docs/content/(docs)/usage.mdx
- apps/docs/app/(home)/components/demo.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: 🏗️ Build
- GitHub Check: agent
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Preferunknownoveranywhen the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions
Files:
apps/docs/app/(home)/components/playground/background.tsxapps/docs/app/(home)/components/playground/index.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{ts,tsx,js,jsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Preferfor...ofloops over.forEach()and indexedforloops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Useconstby default,letonly when reassignment is needed, nevervar
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Removeconsole.log,debugger, andalertstatements from production code
ThrowErrorobjects with descriptive messages, not strings or other values
Usetry-catchblocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Keep functions focused and under reasonable cognitive complexity limits
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Group related code together and separate concerns
Don't useeval()or assign directly todocument.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use proper image components (e.g., Next.js<Image>) over<img>tags
Files:
apps/docs/app/(home)/components/playground/background.tsxapps/docs/app/(home)/components/playground/index.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{tsx,jsx}: Use function components over class components in React
Call hooks at the top level only, never conditionally
Specify all dependencies in hook dependency arrays correctly
Use thekeyprop for elements in iterables (prefer unique IDs over array indices)
Nest children between opening and closing tags instead of passing as props in React
Don't define components inside other components in React
AvoiddangerouslySetInnerHTMLunless absolutely necessary
Use Next.js<Image>component for images
Usenext/heador App Router metadata API for head elements in Next.js
Use Server Components for async data fetching instead of async Client Components in Next.js
Use ref as a prop instead ofReact.forwardRefin React 19+
Files:
apps/docs/app/(home)/components/playground/background.tsxapps/docs/app/(home)/components/playground/index.tsx
**/*.{html,tsx,jsx,vue,svelte,astro}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{html,tsx,jsx,vue,svelte,astro}: Use semantic HTML and ARIA attributes for accessibility: provide meaningful alt text for images, use proper heading hierarchy, add labels for form inputs, include keyboard event handlers alongside mouse events, and use semantic elements
Addrel="noopener"when usingtarget="_blank"on links
Files:
apps/docs/app/(home)/components/playground/background.tsxapps/docs/app/(home)/components/playground/index.tsx
**/index.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Avoid barrel files (index files that re-export everything)
Files:
apps/docs/app/(home)/components/playground/index.tsx
🧠 Learnings (4)
📚 Learning: 2025-12-21T17:02:32.986Z
Learnt from: CR
Repo: PunGrumpy/logixlysia PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-12-21T17:02:32.986Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use proper image components (e.g., Next.js `<Image>`) over `<img>` tags
Applied to files:
apps/docs/app/(home)/components/playground/background.tsx
📚 Learning: 2025-12-21T17:02:32.986Z
Learnt from: CR
Repo: PunGrumpy/logixlysia PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-12-21T17:02:32.986Z
Learning: Applies to **/*.{tsx,jsx} : Use Next.js `<Image>` component for images
Applied to files:
apps/docs/app/(home)/components/playground/background.tsx
📚 Learning: 2025-12-21T17:02:32.986Z
Learnt from: CR
Repo: PunGrumpy/logixlysia PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-12-21T17:02:32.986Z
Learning: Applies to **/*.{html,tsx,jsx,vue,svelte,astro} : Use semantic HTML and ARIA attributes for accessibility: provide meaningful alt text for images, use proper heading hierarchy, add labels for form inputs, include keyboard event handlers alongside mouse events, and use semantic elements
Applied to files:
apps/docs/app/(home)/components/playground/background.tsx
📚 Learning: 2025-12-21T17:02:32.986Z
Learnt from: CR
Repo: PunGrumpy/logixlysia PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-12-21T17:02:32.986Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Remove `console.log`, `debugger`, and `alert` statements from production code
Applied to files:
apps/docs/app/(home)/components/playground/index.tsx
🪛 LanguageTool
apps/docs/content/(docs)/configuration.mdx
[grammar] ~154-~154: Ensure spelling is correct
Context: ...assed to logger helpers is printed as tree lines under the main log line instead...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🔇 Additional comments (11)
apps/docs/app/(home)/components/playground/background.tsx (1)
7-15: LGTM!Good accessibility practices:
aria-hiddenon the decorative container withalt=""on the image correctly marks this as a decorative element that assistive technologies should ignore. Thefilllayout withsizes="100vw"is appropriate for a full-width background.apps/docs/content/(docs)/configuration.mdx (1)
102-173: LGTM!The documented defaults (
slowThreshold: 500,verySlowThreshold: 1000,showContextTree: true,contextDepth: 1) accurately match the implementation inpackages/logixlysia/src/logger/create-logger.ts. The placeholder descriptions are clear and consistent with the logger behavior.packages/logixlysia/README.md (1)
25-36: LGTM!The README example effectively showcases the new logging configuration options. The threshold values (
slowThreshold: 500,verySlowThreshold: 1000) match the documented defaults, andstartupMessageFormat: 'banner'correctly demonstrates the new banner feature.apps/docs/content/features/formatting.mdx (2)
8-37: LGTM!The placeholder documentation is comprehensive and accurately describes the new tokens (
{icon},{speed},{service},{statusText},{context}). The color/TTY behavior notes for{icon}and duration thresholds are helpful for users.
96-121: LGTM!The context tree documentation clearly explains the multi-line rendering behavior, tree branch formatting, and how to disable it with
showContextTree: false. The example output effectively illustrates the expected format.apps/docs/app/(home)/components/playground/index.tsx (6)
69-70: LGTM!The threshold constants (
SLOW_MS = 500,VERY_SLOW_MS = 1000) correctly match the logger defaults defined inpackages/logixlysia/src/logger/create-logger.ts, ensuring the playground accurately visualizes the speed indicators.
80-103: LGTM!The
formatDurationMsfunction handles edge cases well (sub-millisecond precision, smart decimal rounding for seconds). ThedurationClassthreshold logic correctly mirrors the logger's color scheme.
402-427: LGTM!The
ContextTreecomponent correctly renders the tree branch characters (├─and└─) matching the logger's context output format. The composite key usingkey-value-indexis reasonable for this static demo data.
429-486: LGTM!The
LogBlockcomponent cleanly separates the main log line from the context tree, with correct threshold logic for the⚡ slowindicator. The visual hierarchy with the fox chip, method, pathname, status, and duration matches the logger output format well.
511-517: LGTM!The composite key ensures uniqueness across repeated random log generation, which is important for the marquee animation effect.
535-545: LGTM!The terminal header correctly uses
aria-hiddenon the decorative traffic-light dots, keeping them hidden from assistive technologies while maintaining the macOS-style visual appearance.
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. Autofix skipped. No unresolved CodeRabbit review comments with fix instructions found. |
Description
This PR improves HTTP request logging and startup output for
logixlysia, and updates the Elysia demo app to exercise the new options.Logger
formatLogOutputreturning a main line plus optional context tree lines; keepsformatLineas a deprecated compatibility wrapper (main line only).⚡ slowbadge when over threshold), and message.Options.configfields:service,slowThreshold,verySlowThreshold,showContextTree,contextDepth.{icon},{service},{statusText},{speed}(existing tokens like{context}still work; JSON context is inlined when the tree is disabled).Startup banner
Repo hygiene
.changeset/rich-logging-banner.mdfor the nextlogixlysiarelease.format-output.test.tsplus updates tocreate-loggerandstart-servertests.apps/elysiarouter config updated to showcaseservice, thresholds, context tree, and timestamp format.Checklist
Screenshots (if applicable)
Summary by CodeRabbit
New Features
Documentation
Tests