Skip to content

Comments

feat(monitoring): add logger service with log level filtering#710

Open
sahil143 wants to merge 2 commits intokonflux-ci:mainfrom
sahil143:logger-service
Open

feat(monitoring): add logger service with log level filtering#710
sahil143 wants to merge 2 commits intokonflux-ci:mainfrom
sahil143:logger-service

Conversation

@sahil143
Copy link
Member

@sahil143 sahil143 commented Feb 17, 2026

Fixes

Description

Adds a structured logger service to the monitoring module, replacing raw console.* calls with level-aware logging that integrates with the monitoring/error-reporting.

Type of change

  • Feature
  • Bugfix
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Documentation content changes
  • Other (please describe):

Screen shots / Gifs for design review

No UI changes

How to test or reproduce?

Browser conformance:

  • Chrome
  • Firefox
  • Safari
  • Edge

Summary by CodeRabbit

  • New Features

    • Introduced a logger with debug, info, warn, and error levels that automatically filters based on environment settings.
    • Added error reporting integration for automatic error capture and monitoring.
  • Documentation

    • Enhanced development workflow documentation with expanded best practices and procedural guidance.
  • Chores

    • Updated git configuration to exclude auto-generated files.

- Add logger with debug, info, warn, and error methods
- Support log level filtering via LOG_LEVEL env variable
- Default to warn in production, debug otherwise
- Suppress debug console output in production environment
- Integrate error logging with monitoringService
- Extract LogLevel type and LOG_LEVELS constant to src/consts
- Re-export LogLevel from monitoring/types for backward compat
- Add comprehensive unit tests (16 test cases)

Assisted-by: Cursor, Claude
@sahil143 sahil143 requested a review from a team as a code owner February 17, 2026 10:18
@sahil143 sahil143 requested review from JoaoPedroPP and testcara and removed request for a team February 17, 2026 10:18
@snyk-io
Copy link
Contributor

snyk-io bot commented Feb 17, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 17, 2026

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'version', 'include', 'exclude', 'rules', 'limits'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • 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
📝 Walkthrough

Walkthrough

This PR reorganizes and centralizes logging infrastructure by extracting the LogLevel type to a dedicated consts module, creating a new environment-aware logger module with level-based filtering and monitoring service integration, removing the legacy LogLevelValues constant, and adding comprehensive test coverage. Configuration and documentation files are also updated.

Changes

Cohort / File(s) Summary
New Logging Constants
src/consts/log-levels.ts
Introduces LogLevel type alias and LOG_LEVELS mapping with numeric severity values for level-based filtering.
Logger Implementation
src/monitoring/logger.ts
New logger module exporting debug, info, warn, and error methods with environment-aware log level filtering and monitoringService integration for error reporting.
Type Reorganization
src/monitoring/types.ts
Refactors LogLevel type from local definition to import and re-export from ~/consts/log-levels; IMonitoringProvider interface updated to reference external type.
Legacy Constant Removal
src/monitoring/const.ts
Removes exported LogLevelValues constant, replaced by centralized log-levels.ts module.
Logger Test Suite
src/monitoring/__tests__/logger.spec.ts
Comprehensive unit tests covering default log levels, environment-based filtering, monitoringService integration, error handling, and context propagation.
Configuration & Documentation
.gitignore, .cursor/rules/ai-assistant-workflow.mdc
Adds Snyk security extension rules to gitignore; enhances workflow documentation with additional guidelines and examples.

Sequence Diagram

sequenceDiagram
    participant Caller
    participant Logger
    participant Environment
    participant Console
    participant MonitoringService

    Caller->>Logger: call debug/info/warn/error(message, ...)
    Logger->>Environment: read LOG_LEVEL env var
    Logger->>Logger: compute currentLevel & shouldLog
    alt shouldLog returns true
        Logger->>Console: log level-prefixed message
        Note over Console: "[DEBUG]", "[INFO]", "[WARN]", "[ERROR]"
    end
    alt error method called
        Logger->>MonitoringService: captureException(error)
        MonitoringService-->>Logger: ack
    end
    Logger-->>Caller: void
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: introducing a logger service with log level filtering capabilities, which is the primary focus of the changeset.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/monitoring/__tests__/logger.spec.ts (1)

107-162: Environment variable cleanup is not failure-safe inside isolateModules.

If an assertion throws inside the jest.isolateModules callback, the cleanup lines (e.g., process.env.NODE_ENV = 'test' / delete process.env.LOG_LEVEL) won't execute, leaking env state to subsequent tests.

Wrap each block in try/finally to ensure cleanup:

Example fix for lines 108-120
     it('should not log debug messages in production environment', () => {
       jest.isolateModules(() => {
-        process.env.NODE_ENV = 'production';
-        process.env.LOG_LEVEL = 'debug';
-        // eslint-disable-next-line `@typescript-eslint/no-var-requires`
-        const prodLogger = require('../logger').logger;
-        prodLogger.debug('should not appear');
-
-        expect(consoleMock.log).not.toHaveBeenCalled();
-        process.env.NODE_ENV = 'test';
-        delete process.env.LOG_LEVEL;
+        try {
+          process.env.NODE_ENV = 'production';
+          process.env.LOG_LEVEL = 'debug';
+          // eslint-disable-next-line `@typescript-eslint/no-var-requires`
+          const prodLogger = require('../logger').logger;
+          prodLogger.debug('should not appear');
+
+          expect(consoleMock.log).not.toHaveBeenCalled();
+        } finally {
+          process.env.NODE_ENV = 'test';
+          delete process.env.LOG_LEVEL;
+        }
       });
     });

Apply the same pattern to all isolateModules blocks that mutate process.env.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/monitoring/__tests__/logger.spec.ts` around lines 107 - 162, The tests
mutate process.env inside jest.isolateModules callbacks without guaranteed
cleanup; wrap the body of each jest.isolateModules callback (in the 'should not
log debug messages in production environment', 'should suppress debug and info
when LOG_LEVEL is warn', and 'should only allow error when LOG_LEVEL is error'
tests) in a try/finally and restore process.env values in finally (e.g., reset
NODE_ENV to 'test' and delete LOG_LEVEL) so environment changes are reverted
even if assertions throw; apply this pattern to every isolateModules block that
sets process.env.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/monitoring/__tests__/logger.spec.ts`:
- Around line 219-235: The test name is misleading: it currently reads 'should
not call monitoringService when error level is suppressed' but the body requires
captureException to be called; update the test to reflect its behavior by
renaming the test description to something like 'should call
monitoringService.captureException when error level is active' (or delete the
test if it's a duplicate of the existing error-level test). Locate the test
within the describe('monitoringService integration') block in
src/monitoring/__tests__/logger.spec.ts and change the it(...) description
string to the new, accurate text (the assertions using mockCaptureException and
errorLogger.error remain unchanged).

In `@src/monitoring/logger.ts`:
- Line 1: The import in logger.ts uses a relative path; change it to the
project's path-alias form by importing LOG_LEVELS and LogLevel from the aliased
module (e.g. replace the relative import with import { LOG_LEVELS, type LogLevel
} from '~/consts/log-levels') so LOG_LEVELS and LogLevel resolve via the
configured ~/ alias and conform to project conventions; no runtime logic changes
required.
- Around line 4-5: The code currently casts process.env.LOG_LEVEL to LogLevel
and assigns it to currentLevel which can be an invalid value and cause
LOG_LEVELS[currentLevel] to be undefined; update the logic around currentLevel
(and related shouldLog/LOG_LEVELS usage) to validate that process.env.LOG_LEVEL
is one of the known keys in LOG_LEVELS, and if not, fall back to the default
computed level (NODE_ENV-based) and emit a warning (e.g., via console.warn or
the module logger) that the provided LOG_LEVEL was invalid; ensure subsequent
checks in shouldLog use the validated level so comparisons against
LOG_LEVELS[currentLevel] never encounter undefined.

---

Nitpick comments:
In `@src/monitoring/__tests__/logger.spec.ts`:
- Around line 107-162: The tests mutate process.env inside jest.isolateModules
callbacks without guaranteed cleanup; wrap the body of each jest.isolateModules
callback (in the 'should not log debug messages in production environment',
'should suppress debug and info when LOG_LEVEL is warn', and 'should only allow
error when LOG_LEVEL is error' tests) in a try/finally and restore process.env
values in finally (e.g., reset NODE_ENV to 'test' and delete LOG_LEVEL) so
environment changes are reverted even if assertions throw; apply this pattern to
every isolateModules block that sets process.env.

Comment on lines +219 to +235
describe('monitoringService integration', () => {
it('should not call monitoringService when error level is suppressed', () => {
jest.isolateModules(() => {
// There's no level higher than error that would suppress it,
// but we can verify it IS called when error level is active
process.env.LOG_LEVEL = 'error';
process.env.NODE_ENV = 'test';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const errorLogger = require('../logger').logger;

errorLogger.error('critical', new Error('fail'));

expect(mockCaptureException).toHaveBeenCalledWith(new Error('fail'), undefined);

delete process.env.LOG_LEVEL;
});
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Misleading test name — it verifies the opposite of what it describes.

The test is named 'should not call monitoringService when error level is suppressed' but actually asserts that captureException is called. The inline comment (lines 222-223) acknowledges there's no level above error to suppress it, making this test effectively a duplicate of the error-level integration test.

Consider renaming to something like 'should call monitoringService.captureException when error level is active' or removing it if redundant with the existing error tests.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/monitoring/__tests__/logger.spec.ts` around lines 219 - 235, The test
name is misleading: it currently reads 'should not call monitoringService when
error level is suppressed' but the body requires captureException to be called;
update the test to reflect its behavior by renaming the test description to
something like 'should call monitoringService.captureException when error level
is active' (or delete the test if it's a duplicate of the existing error-level
test). Locate the test within the describe('monitoringService integration')
block in src/monitoring/__tests__/logger.spec.ts and change the it(...)
description string to the new, accurate text (the assertions using
mockCaptureException and errorLogger.error remain unchanged).

@@ -0,0 +1,38 @@
import { LOG_LEVELS, type LogLevel } from '../consts/log-levels';
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Use absolute path alias for the import.

Per project conventions, imports from src/ should use the configured ~/ alias.

Suggested fix
-import { LOG_LEVELS, type LogLevel } from '../consts/log-levels';
+import { LOG_LEVELS, type LogLevel } from '~/consts/log-levels';

As per coding guidelines: "Use absolute imports with configured path aliases: ~/components, ~/types, ~/k8s, ~/utils, ~/models, @routes".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { LOG_LEVELS, type LogLevel } from '../consts/log-levels';
import { LOG_LEVELS, type LogLevel } from '~/consts/log-levels';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/monitoring/logger.ts` at line 1, The import in logger.ts uses a relative
path; change it to the project's path-alias form by importing LOG_LEVELS and
LogLevel from the aliased module (e.g. replace the relative import with import {
LOG_LEVELS, type LogLevel } from '~/consts/log-levels') so LOG_LEVELS and
LogLevel resolve via the configured ~/ alias and conform to project conventions;
no runtime logic changes required.

Comment on lines +4 to +5
const currentLevel: LogLevel =
(process.env.LOG_LEVEL as LogLevel) || (process.env.NODE_ENV === 'production' ? 'warn' : 'debug');
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Invalid LOG_LEVEL values silently suppress all logging.

If process.env.LOG_LEVEL is set to an unrecognized value (e.g., 'verbose'), the cast as LogLevel won't fail at runtime. LOG_LEVELS[currentLevel] will return undefined, causing shouldLog to evaluate number >= undefinedfalse for every level, silently dropping all logs with no indication of misconfiguration.

Consider validating or falling back:

Suggested fix
-const currentLevel: LogLevel =
-  (process.env.LOG_LEVEL as LogLevel) || (process.env.NODE_ENV === 'production' ? 'warn' : 'debug');
+const defaultLevel: LogLevel = process.env.NODE_ENV === 'production' ? 'warn' : 'debug';
+const envLevel = process.env.LOG_LEVEL as string | undefined;
+const currentLevel: LogLevel =
+  envLevel && envLevel in LOG_LEVELS ? (envLevel as LogLevel) : defaultLevel;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const currentLevel: LogLevel =
(process.env.LOG_LEVEL as LogLevel) || (process.env.NODE_ENV === 'production' ? 'warn' : 'debug');
const defaultLevel: LogLevel = process.env.NODE_ENV === 'production' ? 'warn' : 'debug';
const envLevel = process.env.LOG_LEVEL as string | undefined;
const currentLevel: LogLevel =
envLevel && envLevel in LOG_LEVELS ? (envLevel as LogLevel) : defaultLevel;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/monitoring/logger.ts` around lines 4 - 5, The code currently casts
process.env.LOG_LEVEL to LogLevel and assigns it to currentLevel which can be an
invalid value and cause LOG_LEVELS[currentLevel] to be undefined; update the
logic around currentLevel (and related shouldLog/LOG_LEVELS usage) to validate
that process.env.LOG_LEVEL is one of the known keys in LOG_LEVELS, and if not,
fall back to the default computed level (NODE_ENV-based) and emit a warning
(e.g., via console.warn or the module logger) that the provided LOG_LEVEL was
invalid; ensure subsequent checks in shouldLog use the validated level so
comparisons against LOG_LEVELS[currentLevel] never encounter undefined.

@codecov
Copy link

codecov bot commented Feb 17, 2026

Codecov Report

❌ Patch coverage is 95.91837% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.66%. Comparing base (6ee0ec7) to head (a5f860e).

Files with missing lines Patch % Lines
src/monitoring/types.ts 0.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #710      +/-   ##
==========================================
+ Coverage   86.63%   86.66%   +0.02%     
==========================================
  Files         764      765       +1     
  Lines       58225    58264      +39     
  Branches     5658     6891    +1233     
==========================================
+ Hits        50441    50492      +51     
+ Misses       7603     7556      -47     
- Partials      181      216      +35     
Flag Coverage Δ
e2e 42.99% <ø> (-0.33%) ⬇️
unittests 85.82% <95.91%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/consts/log-levels.ts 100.00% <100.00%> (ø)
src/monitoring/logger.ts 100.00% <100.00%> (ø)
src/monitoring/types.ts 0.00% <0.00%> (ø)

... and 80 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6ee0ec7...a5f860e. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant