Skip to content

JCN-520: Omit props from arrays in logs#8

Merged
manuelvilche merged 5 commits into
masterfrom
JCN-520-omit-props-in-arrays-from-logs
Aug 12, 2025
Merged

JCN-520: Omit props from arrays in logs#8
manuelvilche merged 5 commits into
masterfrom
JCN-520-omit-props-in-arrays-from-logs

Conversation

@lautaro-echeverria

@lautaro-echeverria lautaro-echeverria commented Jul 21, 2025

Copy link
Copy Markdown
Contributor

Historia de usuario

https://janiscommerce.atlassian.net/browse/JCN-519

Sub-tarea

https://janiscommerce.atlassian.net/browse/JCN-520

Descripcion del requerimiento

Actualmente el paquete @janiscommerce/api no permite omitir de los logs propiedades que estan dentro de arrays. Por ende, se muestran dichas propiedades con informacion sensible de seguridad lo cual no es adecuado ni seguro.

Es necesario modificar los getters excludeFieldsLogRequestData y excludeFieldsLogResponseBody para que dichas propiedades puedan ser removidas de los logs en caso de ser especificado.

Descripcion de la solucion

Al recibir los arrays excludeFieldsLogRequestData o excludeFieldsLogResponseBody, se llama a un metodo omitRecursive el cual fue modificado para lograr el requerimiento. Ahora, en vez de pasar solo nombres de propiedades, se puede hacer lo siguiente:

  • Pasar un nombre de una propiedad (funciona igual que antes, la borra recursivamente de todo el log)
  • Pasar un path especifico a una propiedad (borra la propiedad solo en ese path)

Para la opcion del path, en caso de no saber el nombre root del log, se puede usar una wildcard * y luego la propiedad a eliminar. Tambien, para los casos donde la propiedad esta dentro un array de objeto, se debe usar la wildcard * para que recorra cada objeto del array.

Summary by CodeRabbit

  • Documentation

    • Expanded documentation to clarify how to specify fields and paths for excluding data from logs, including detailed wildcard usage and warnings about exclusion patterns.
  • Bug Fixes

    • Improved handling of undefined or empty exclusion lists to prevent errors during logging.
  • New Features

    • Enhanced exclusion logic to support complex nested field paths and wildcards when omitting data from logs.
  • Tests

    • Added comprehensive tests for field exclusion patterns in logs, including nested fields and wildcards.
  • Chores

    • Removed an unused dependency to streamline the package.
    • Updated GitHub Actions workflows to use Node.js version 18 for build, test, coverage, and publish jobs.

@coderabbitai

coderabbitai Bot commented Jul 21, 2025

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The updates introduce a deep, pattern-based field exclusion mechanism for logging request and response data, supporting nested paths and wildcards. Documentation is expanded to clarify usage, and related tests are added to verify correct exclusion behavior. Dependencies are updated to remove lodash.omit in favor of lodash.clonedeep. GitHub workflows are updated to use Node.js 18.

Changes

File(s) Change Summary
Documentation
README.md
Expanded documentation for field exclusion in logging, including wildcards, path patterns, and warnings.
Logging Helpers
lib/helpers/log.js
Added default empty array fallbacks for exclusion fields when calling omitRecursive.
Utility Functions
lib/utils.js
Rewrote omitRecursive for deep recursive exclusion using path patterns and wildcards; removed lodash.omit.
Package Configuration
package.json
Removed lodash.omit dependency.
Tests
tests/dispatcher-test.js
Added and updated tests for field exclusion logic, covering nested/wildcard patterns and edge cases.
GitHub Workflows
.github/workflows/build-status.yml, .github/workflows/coverage-status.yml, .github/workflows/npm-publish.yml
Updated Node.js version from 14.x to 18.x and upgraded GitHub actions versions in build, coverage, and publish workflows.

Sequence Diagram(s)

sequenceDiagram
    participant API
    participant Logger
    participant Utils

    API->>Logger: Log request/response data (with exclusion fields)
    Logger->>Utils: Call omitRecursive(data, exclusionPatterns)
    Utils->>Utils: Deep clone data
    Utils->>Utils: Recursively remove fields matching patterns (supports *, **)
    Utils-->>Logger: Return filtered data
    Logger-->>API: Log filtered data
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

In the burrow, deep and neat,
A clever bunny skips repeat—
Now logs are clean, with fields removed,
Wildcards and paths smartly approved.
Tests abound to check each case,
Hopping through the code with grace.
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 832fdef and 0535ae7.

📒 Files selected for processing (1)
  • lib/utils.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js

⚙️ CodeRabbit Configuration File

Never report errors of the following categories lint/suspicious/noRedundantUseStrict, lint/complexity/noThisInStatic, lint/complexity/noStaticOnlyClass, reported by Biome.

Files:

  • lib/utils.js
🔇 Additional comments (4)
lib/utils.js (4)

22-56: Pattern matching logic looks solid, but consider edge case handling.

The isPathMatch function correctly implements wildcard pattern matching with support for both * (single segment) and ** (multi-segment) wildcards. The recursive approach and the special case for single-segment patterns are well-designed.


65-97: Address performance concerns raised in previous reviews.

The recurse function implementation addresses most of the performance feedback from previous reviews:

  • ✅ Uses for...of instead of forEach (line 71, 80)
  • ✅ Uses Object.keys() instead of Object.entries() (line 80)
  • ✅ Implements path tracking with push/pop pattern to avoid array recreation (lines 72-74, 83, 94)

However, there's still the performance concern about ** wildcard support mentioned in previous reviews. The current implementation may impact performance across all microservices.

Consider monitoring performance impact of the ** wildcard feature since it was flagged as potentially expensive in previous reviews.


106-122: Great improvement using structuredClone and addressing feedback.

The refactored omitRecursive function successfully:

  • ✅ Uses structuredClone instead of lodash.cloneDeep as suggested in previous reviews
  • ✅ Converts to for...of loop (line 111-112) as suggested
  • ✅ Maintains the same external API while supporting the new pattern-based exclusion

The implementation is clean and follows the feedback from previous reviews.


129-136: Nice consistency improvement in iteration style.

Good update to use for...of with Object.keys() instead of other iteration methods, maintaining consistency with the performance improvements made throughout the file.


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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot added enhancement New feature or request documentation labels Jul 21, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
README.md (1)

58-71: Clear documentation of the enhanced field exclusion feature.

The documentation effectively explains the wildcard patterns and their usage. Consider adding examples to illustrate the patterns more clearly.

Consider adding examples after the warnings to clarify usage:

 ⚠️ **Warning**:  
 - When using the wildcard `*` alone in the field path of the `excludeFieldsLogRequestData` or `excludeFieldsLogResponseBody` static getter, it will exclude all the fields in the log.
 - In case the field path is incorrect, it will not exclude any field.
+
+**Examples**:
+- `'password'` - Excludes all 'password' fields recursively
+- `'user.*.email'` - Excludes 'email' field from all array elements in 'user'
+- `'data.**.secret'` - Excludes 'secret' fields at any depth under 'data'
+- `'*'` - Excludes all fields (use with caution)
lib/utils.js (1)

35-46: Consider performance implications of the ** wildcard.

The current implementation tries every possible position when matching **, which could be expensive for deeply nested objects. For a path of length n, it makes n+1 recursive calls.

Consider adding a depth limit or warning in documentation about performance implications when using ** on deeply nested structures.

Also, verify that edge cases with empty segments are handled correctly:

#!/bin/bash
# Description: Check if there are any patterns with consecutive dots or leading/trailing dots in tests

# Search for test cases with edge case patterns
rg "excludeFields.*=.*\[.*[\'\"]\.+.*[\'\"].*\]" tests/ -A5 -B5

# Check if empty string patterns are tested
rg "excludeFields.*=.*\[.*[\'\"][\'\"].*\]" tests/
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c041b74 and fb3f2be.

📒 Files selected for processing (5)
  • README.md (1 hunks)
  • lib/helpers/log.js (1 hunks)
  • lib/utils.js (2 hunks)
  • package.json (1 hunks)
  • tests/dispatcher-test.js (26 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js

Instructions used from:

Sources:
⚙️ CodeRabbit Configuration File

🧬 Code Graph Analysis (1)
lib/helpers/log.js (1)
lib/utils.js (1)
  • omitRecursive (99-112)
🪛 Biome (1.9.4)
lib/helpers/log.js

[error] 35-35: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🪛 GitHub Actions: Coverage Status
tests/dispatcher-test.js

[error] 1-1: Test coverage thresholds not met: lines (10.4%), functions (0%), branches (0%), statements (10.23%) below required 100%.

🔇 Additional comments (5)
package.json (1)

41-46: LGTM! Dependency cleanup aligns with implementation changes.

The removal of lodash.omit is appropriate since the omitRecursive function now uses lodash.clonedeep for deep cloning instead.

lib/helpers/log.js (1)

34-34: Good defensive programming with empty array fallbacks.

Adding || [] prevents potential runtime errors when excludeFieldsLogRequestData or excludeFieldsLogResponseBody are undefined.

Also applies to: 40-40

tests/dispatcher-test.js (1)

782-1255: Comprehensive test coverage for the field exclusion feature.

The tests thoroughly cover various scenarios including:

  • Simple and nested field exclusion
  • Wildcard patterns (* and **)
  • Multiple exclusion patterns
  • Edge cases (empty arrays, non-matching patterns)
  • Deep nested structures

Well done on the thorough testing approach!

lib/utils.js (2)

67-90: Well-implemented recursive traversal and property removal.

The function correctly:

  • Handles both arrays and objects
  • Builds the path incrementally
  • Checks patterns before recursing deeper
  • Safely deletes matching properties

27-28: Fix incorrect single-segment pattern matching logic.

The current implementation only checks if the pattern matches the last segment of the path, which is incorrect. A single-segment pattern should match if it appears anywhere in the path as the final segment.

For example, with pattern ['password']:

  • Path ['user', 'password'] should match ✓
  • Path ['password'] should match ✓
  • Path ['data', 'user', 'info', 'password'] should match ✓
  • But path ['password', 'hash'] should NOT match ✗

The current logic would incorrectly reject valid matches and accept invalid ones. Consider this fix:

-	// Special case: if pattern has only one segment, check if it matches the last path segment or is a wildcard
-	if(pattern.length === 1)
-		return path[path.length - 1] === pattern[0] || pattern[0] === '*';
+	// Special case: if pattern has only one segment
+	if(pattern.length === 1) {
+		// If it's a wildcard, it matches any single-segment path
+		if(pattern[0] === '*')
+			return path.length === 1;
+		// Otherwise, check if the pattern matches the entire path (for root-level fields)
+		return path.length === 1 && path[0] === pattern[0];
+	}

However, based on the tests and use cases, it seems the intention might be to match the pattern as a leaf node anywhere in the object. In that case, this logic should be removed entirely and let the general recursive logic handle it.

Likely an incorrect or invalid review comment.

Comment thread lib/utils.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fb3f2be and 70564fd.

📒 Files selected for processing (3)
  • .github/workflows/build-status.yml (1 hunks)
  • .github/workflows/coverage-status.yml (1 hunks)
  • .github/workflows/npm-publish.yml (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • .github/workflows/npm-publish.yml
  • .github/workflows/build-status.yml
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/coverage-status.yml

15-15: the runner of "actions/setup-node@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

Comment thread .github/workflows/coverage-status.yml
@victor1808 victor1808 requested a review from mdanelutti July 22, 2025 18:07

@mdanelutti mdanelutti left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Te dejo para ajustar

Comment thread lib/utils.js Outdated
'use strict';

const omit = require('lodash.omit');
const cloneDeep = require('lodash.clonedeep');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

siendo que mudaste todo a node 18 ya no necesitamos lodash.cloneDeep para esto es ir por structuredClone

Comment thread lib/utils.js
recurse(patterns, value, newPath);
}
}
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no se si viene de copy paste de otro lado o es nuevo pero me parece bastante nefasto en performance dar soporte al ** ya que hicimos eso por lo menos a nivel código intentaría atajarlo

  1. forEach en esto es un rotundamente no... todos los MS van a pasar por acá eso es lento -> for ... of
  2. este ya es un poco mas fino pero estamos recreando e iterando los array y además recursivo, para esto se puede evitar con .push() y .pop(), de esa forma solo vamos actualizando por iteración sin importar la profundidad, con push antes de entrar y pop al salir para mantener el array
  3. el Object.entries() se recontra tiene que ir, es Object.keys(), de esa forma evitamos la doble iteración de entries para "accder lindo" con value a fin de cuenta lo único que cambia es el llamado a recurse del final

Comment thread lib/utils.js Outdated

object = { ...object }; // Avoid original object modification
// Convert dot-notation path patterns into arrays of path segments.
const patterns = pathPatterns.map(p => p.split('.'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

este ya solo para joderte jajajaja pero ya que estamos en borrar todo acá metes un for...of en vez de map y sigue mejorando

@manuelvilche manuelvilche merged commit c83fbe3 into master Aug 12, 2025
4 checks passed
@manuelvilche manuelvilche deleted the JCN-520-omit-props-in-arrays-from-logs branch August 20, 2025 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants