Add verbose output with tiered logging levels (-v and -vv)#3
Add verbose output with tiered logging levels (-v and -vv)#3jundai-godaddy wants to merge 2 commits intomainfrom
Conversation
Added standard -v and --verbose flags for enabling verbose output, while keeping --debug as an alias. This follows common CLI conventions where -v is the standard flag for verbose logging. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit adds comprehensive verbose output support with two levels of verbosity, along with fixes for ES module compatibility issues. ## New Features ### Tiered Verbosity Levels - **Level 1 (-v, --info)**: Basic output showing HTTP method, URL, status, and duration - **Level 2 (-vv, --debug)**: Full output including headers, request/response bodies with sensitive field redaction ### Automatic HTTP Logging - Introduced `loggedFetch()` wrapper that automatically logs HTTP requests - Extracts logging details from actual requests/responses, eliminating hardcoded duplication - Automatic timing and status code capture - Smart JSON response parsing for level 2 verbosity ### Security - Automatic redaction of `access_token` and `accessToken` fields in logs - Recursive redaction for nested objects - Follows existing redaction patterns for Authorization headers ## Bug Fixes ### ES Module Compatibility - Added `__dirname` and `__filename` shims in require-shim.js for dependencies expecting CommonJS globals - Marked pino-pretty as external dependency to avoid bundling worker thread code that breaks at runtime - Changed from pino transport API to direct stream usage to eliminate worker thread dependency ### User Experience - Added visual indicator when verbose output is enabled - Clear messaging distinguishing between basic and full verbosity levels ## Implementation Details ### CLI Options - `-v, --verbose`: Incrementing flag (use multiple times for higher levels) - `--info`: Alias for level 1 verbosity - `--debug`: Alias for level 2 verbosity ### Code Quality - DRY principle: Single `loggedFetch()` wrapper handles all HTTP logging - No hardcoded method/status values in logging calls - Automatic body parsing based on content-type - Level-aware logging prevents unnecessary work at lower verbosity Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
| logger.debug(`→ ${options.method} ${options.url}`); | ||
| } | ||
| }; | ||
|
|
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 days ago
In general: avoid logging full URLs that may contain sensitive information (query strings, path segments) and avoid logging any token/credential endpoints at low verbosity. Instead, log only high‑level, non‑sensitive details (HTTP method, status code, maybe a truncated or sanitized URL) and reserve detailed information for higher verbosity with explicit redaction.
Best targeted fix here without changing existing behavior more than necessary:
- For
verbosityLevel === 1, stop including the fulloptions.urlin the log messages inlogHttpRequestandlogHttpResponse. We can still log the method and, for responses, the status and duration, which preserves the intent of “basic” verbosity while eliminating the sensitive URL from that path. - For
verbosityLevel >= 2, we already log a structured object includingurl, and that is where advanced debugging is expected; we leave that as‑is since the reported sink is the string interpolation at line 71, not the structured object.
Concretely:
- In
src/services/logger.ts:- Change
logHttpRequestso that the branchverbosityLevel === 1logs only the HTTP method (or a generic message) instead of→ ${options.method} ${options.url}. - Change
logHttpResponseso that the branchverbosityLevel === 1logs only the status, method, and optional duration, but notoptions.url.
- Change
No new imports or helpers are required; we only adjust the log message strings.
| @@ -68,7 +68,8 @@ | ||
| `→ ${options.method} ${options.url}`, | ||
| ); | ||
| } else if (verbosityLevel === 1) { | ||
| logger.debug(`→ ${options.method} ${options.url}`); | ||
| // Avoid logging full URL at basic verbosity to prevent leaking sensitive data | ||
| logger.debug(`→ ${options.method}`); | ||
| } | ||
| }; | ||
|
|
||
| @@ -98,8 +99,9 @@ | ||
| }`, | ||
| ); | ||
| } else if (verbosityLevel === 1) { | ||
| // Avoid logging full URL at basic verbosity to prevent leaking sensitive data | ||
| logger.debug( | ||
| `← ${options.status} ${options.method} ${options.url} ${ | ||
| `← ${options.status} ${options.method} ${ | ||
| options.duration ? `(${options.duration}ms)` : "" | ||
| }`, | ||
| ); |
|
|
||
| if (Array.isArray(obj)) { | ||
| return obj.map(redactSensitiveFields); |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 days ago
In general, to fix clear-text logging of sensitive information you must either (1) avoid logging sensitive values at all, or (2) ensure they are consistently redacted before being written to logs. In this code, the problem arises because logHttpResponse always includes the full options.url in the log message string; for calls like the OAuth token exchange, that URL is considered sensitive by the analysis and should not be logged verbatim.
The minimal, behavior-preserving fix is to treat URLs as potentially sensitive and avoid logging them in the human-readable message string for responses (and, ideally, for requests as well), while still keeping them in the structured log object for high-verbosity, where operators can decide whether such logs are acceptable. Specifically:
- Leave the structured object fields (
url,headers,body, etc.) as-is for verbosity level ≥ 2, since that’s already subject to redaction logic and is clearly marked as debug-level logging. - Change the string passed as the second argument to
logger.debuginlogHttpResponse(both branches:verbosityLevel >= 2andverbosityLevel === 1) so that it no longer includes${options.url}. - Optionally, for symmetry and defense in depth, also remove the URL from the
logHttpRequestmessage string, although CodeQL only flagged the response path.
Concretely, in src/services/logger.ts:
- In
logHttpResponse, replace:- The debug message template at lines 96–98 with one that omits
${options.url}but keeps status, method, and duration. - The debug message template at lines 101–104 similarly.
No new methods or imports are required; we only adjust the formatting strings.
- The debug message template at lines 96–98 with one that omits
| @@ -93,13 +93,13 @@ | ||
| body: options.body, | ||
| duration: options.duration, | ||
| }, | ||
| `← ${options.status} ${options.method} ${options.url} ${ | ||
| `← ${options.status} ${options.method} ${ | ||
| options.duration ? `(${options.duration}ms)` : "" | ||
| }`, | ||
| ); | ||
| } else if (verbosityLevel === 1) { | ||
| logger.debug( | ||
| `← ${options.status} ${options.method} ${options.url} ${ | ||
| `← ${options.status} ${options.method} ${ | ||
| options.duration ? `(${options.duration}ms)` : "" | ||
| }`, | ||
| ); |
Summary
This PR adds comprehensive verbose output support with two levels of verbosity, along with fixes for ES module compatibility issues that were preventing verbose mode from working.
Features Added
Tiered Verbosity Levels
-v,--info): Basic output showing HTTP method, URL, status code, and duration-vv,--debug): Full output including headers, request/response bodies with automatic sensitive field redactionAutomatic HTTP Logging
loggedFetch()wrapper that automatically logs HTTP requestsSecurity Enhancements
access_tokenandaccessTokenfields in response logsBug Fixes
ES Module Compatibility Issues
__dirname is not definederror: Added__dirnameand__filenameshims inrequire-shim.jsfor dependencies expecting CommonJS globalspino-prettyas external dependency to avoid bundling worker thread code that breaks at runtimeThese fixes ensure that verbose mode actually works when the CLI is installed globally.
CLI Options
-v, --verbose: Incrementing flag (can be used multiple times:-vv)--info: Alias for level 1 verbosity (-v)--debug: Alias for level 2 verbosity (-vv)Examples
Implementation Highlights
loggedFetch()wrapper handles all HTTP logging(verbose output enabled)or(verbose output enabled: full details)when enabledTesting
Tested with:
godaddy -v auth login- Basic logging worksgodaddy -vv auth login- Full logging works with redacted tokensgodaddy --info env get- Alias worksgodaddy --debug env get- Alias works🤖 Generated with Claude Code