Skip to content

Comments

Fix/console logger leakage#1191

Open
monu808 wants to merge 7 commits intoAOSSIE-Org:mainfrom
monu808:fix/console-logger-leakage
Open

Fix/console logger leakage#1191
monu808 wants to merge 7 commits intoAOSSIE-Org:mainfrom
monu808:fix/console-logger-leakage

Conversation

@monu808
Copy link
Contributor

@monu808 monu808 commented Feb 22, 2026

Fixes: #1091
@rahulharpal1603
Issue - The core issue was dumping the full image object (file paths, metadata, favourite status) into the browser devtools in production.

Steps to reproduce:
1 Open PictoPy and navigate to Home page
2 Open browser developer console (F12)
3 Hover over any image and click the heart icon (favorite)
4 Result: Image data is logged to console (privacy concern)

Solution Implemented:

  • Integrated [tauri-plugin-log] - logs now route through Tauri's native logging system (written to log files on disk, not exposed in the browser console).

To view the logs live in the terminal use the below command:

  • Get-Content "C:\Users\<username>\AppData\Local\org.aossie.pictopy\logs\PictoPy.log" -Wait -Tail 50

@aurthitaacharya-afk I also tried contacting you, look into this pr and if you have a better approach do let me know!

Summary by CodeRabbit

  • New Features

    • Native desktop logging enabled to capture app diagnostics.
  • Chores

    • Centralized logger added and used across the app, replacing console logs.
    • Native logging plugin and desktop capability permissions integrated.
    • Update/download flow initializes download state more robustly (progress/reset handling).
    • Minor UI prop added to folder picker to support cache deletion handling.

@github-actions github-actions bot added CI/CD enhancement New feature or request labels Feb 22, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 22, 2026

No actionable comments were generated in the recent review. 🎉


Walkthrough

Adds a centralized frontend logger and integrates Tauri's native logging plugin; replaces scattered console.* calls across UI, hooks, and slices with the new logger; exposes logger API; updates Tauri permissions and initializes the tauri-plugin-log in the Rust main.

Changes

Cohort / File(s) Summary
Tauri deps & init
frontend/package.json, frontend/src-tauri/Cargo.toml, frontend/src-tauri/capabilities/desktop.json, frontend/src-tauri/src/main.rs
Adds @tauri-apps/plugin-log (npm) and tauri-plugin-log / log (Rust), grants log:default capability, and registers/initializes the tauri log plugin in main.rs.
Logger utility
frontend/src/utils/logger.ts
New centralized logger that safe-stringifies args and routes logs to Tauri native logging when available or falls back to console. Exposes trace/debug/info/warn/error/log.
UI components
frontend/src/components/.../AITaggingFolderPicker.tsx, frontend/src/components/Media/ImageCard.tsx, frontend/src/components/Media/MediaInfoPanel.tsx, frontend/src/components/Media/MediaView.tsx, frontend/src/components/Memories/MemoryDetail.tsx, frontend/src/components/Memories/MemoryViewer.tsx, frontend/src/components/Timeline/TimelineScrollbar.tsx
Replaced console.* with logger.* calls; removed stray console.log instances. No control-flow or behavior changes beyond logging.
State slices
frontend/src/features/imageSlice.ts, frontend/src/features/onboardingSlice.ts
Replaced console.warn with logger.warn in validation/error paths; no API or behavior changes.
Hooks & services
frontend/src/hooks/UseVideos.ts, frontend/src/hooks/folderService.ts, frontend/src/hooks/selectFile.ts, frontend/src/hooks/useFolder.ts, frontend/src/hooks/useFolderOperations.tsx, frontend/src/hooks/useUpdater.ts
Replaced console.* with logger.*. useUpdater.ts also initializes download state (downloading/progress/errors) when a download starts; otherwise no behavioral changes.
Prop addition
frontend/src/components/FolderPicker/AITaggingFolderPicker.tsx
FolderPickerProps gained optional handleDeleteCache?: () => void.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as Frontend App
  participant Logger as utils/logger
  participant Tauri as Tauri Runtime
  participant Console as Browser Console

  App->>Logger: logger.error("message", obj)
  alt isTauriEnvironment() == true
    Logger->>Tauri: emit log via tauri-plugin-log (formatted payload)
    Tauri->>Tauri: write to native/OS log
  else
    Logger->>Console: console.error(formatted payload)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

TypeScript/JavaScript, Rust

Poem

🐰
I hopped through lines and hushed the din,
Swapped scattered logs for tidy tin,
Now whispers go to native ears,
The console quiets, calm appears,
A little rabbit nibbles joy — 🥕

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix/console logger leakage' directly addresses the main change: replacing console logging with a centralized logger to prevent sensitive data exposure in the browser console.
Linked Issues check ✅ Passed The PR fully addresses issue #1091 by integrating tauri-plugin-log, creating a centralized logger utility, and replacing all console logging with logger calls across the codebase.
Out of Scope Changes check ✅ Passed All changes are directly related to resolving the console logger leakage issue. The addition of logging dependencies, logger utility, and replacement of console calls throughout the codebase are all in scope.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/features/imageSlice.ts (1)

29-33: ⚠️ Potential issue | 🟡 Minor

Async side effect in Redux reducer (logger calls unhandled Promise from Tauri)

@tauri-apps/plugin-log's warn() function returns Promise<void>. The logger utility (@/utils/logger.ts line 55) calls tauriWarn() without await or error handling, creating an unhandled Promise whenever logger.warn() is invoked in a Tauri environment. Redux reducers must be pure and synchronous; calling code that initiates async operations violates this constraint.

The floating Promise risk is low here (error path, rarely hit), but should still be addressed. The suggested fix of adding void before logger.warn() is ineffective since logger.warn() already returns void. Instead:

  1. Preferred: Add error handling in the logger utility itself:

    // In logger.ts line 55
    tauriWarn(stringify(...args)).catch((err) => {
      console.error('Logger error:', err);
    });
  2. Alternative: Extract this warning to middleware or a separate action handler outside the reducer.

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

In `@frontend/src/features/imageSlice.ts` around lines 29 - 33, The reducer in
imageSlice calls logger.warn which delegates to tauriWarn (an async function)
and can create an unhandled Promise; to fix this, modify the logger
implementation (the tauriWarn invocation used by logger.warn) to attach a .catch
handler that logs to console or swallow the error so the call remains
synchronous from the reducer's perspective, e.g., ensure
tauriWarn(...).catch(err => console.error('Logger error:', err)); do not
introduce awaits or async calls inside the reducer—alternatively move the
warning out of the reducer into middleware or an action handler if you want
async handling centralized.
🧹 Nitpick comments (8)
frontend/src/utils/logger.ts (3)

28-73: Cache isTauriEnvironment() at module level — it's stable for the lifetime of the app

isTauriEnvironment() reads three window properties on every single log call. The result never changes at runtime, so evaluating it repeatedly is unnecessary overhead.

♻️ Proposed refactor
+const IS_TAURI = isTauriEnvironment();
+
 const logger = {
   trace(...args: unknown[]) {
-    if (isTauriEnvironment()) {
+    if (IS_TAURI) {
       tauriTrace(stringify(...args));
     } else {
       console.debug('[TRACE]', ...args);
     }
   },

   debug(...args: unknown[]) {
-    if (isTauriEnvironment()) {
+    if (IS_TAURI) {
       tauriDebug(stringify(...args));
     } else {
       console.debug(...args);
     }
   },
   // ... repeat for info, warn, error
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/utils/logger.ts` around lines 28 - 73, isTauriEnvironment() is
being called on every logger method call (trace, debug, info, warn, error, log)
which is unnecessary because its result is constant for the app lifetime; cache
its boolean result at module init (e.g., const IS_TAURI = isTauriEnvironment())
and update each method in the logger object to use that cached IS_TAURI instead
of calling isTauriEnvironment() repeatedly, leaving stringify and
tauriTrace/tauriDebug/tauriInfo/tauriWarn/tauriError intact and keeping
logger.log as an alias to logger.info.

70-72: this.info binding breaks if log is destructured

const { log } = logger;
log('msg'); // TypeError: this is undefined (strict mode)

Use an explicit call or an arrow function to avoid the implicit this dependency.

♻️ Proposed fix
-  log(...args: unknown[]) {
-    this.info(...args);
-  },
+  log(...args: unknown[]) {
+    logger.info(...args);
+  },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/utils/logger.ts` around lines 70 - 72, The log method relies on
implicit this (log(...args) { this.info(...args) }) which breaks when
destructured; change log to not depend on call-site this by either making it an
arrow function (e.g., define log = (...args) => this.info(...args)) or
explicitly forwarding to info using a bound call (e.g., call/apply this.info
with the instance), updating the Logger class/instance where the methods are
defined so destructured const { log } = logger; log('msg') still works.

1-75: No tests for the new centralized logger utility

logger.ts is now a critical cross-cutting utility used by a large number of components and hooks throughout the codebase. It contains conditional branching (Tauri vs. browser), custom serialization logic, and an environment detection dependency — all of which are testable in isolation. There are currently no unit tests covering any of these paths.

Consider adding tests for at least:

  • stringify() with primitives, Error objects, circular references, and null
  • Logger routing to console.* in the non-Tauri branch (mockable via jest.spyOn)
  • Logger routing to Tauri functions in the Tauri branch (mock isTauriEnvironment())
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/utils/logger.ts` around lines 1 - 75, Add unit tests that
exercise stringify and the logger branches: test stringify(...) with primitives,
null, an Error instance (ensuring message and stack are included), and a
circular reference (assert it doesn't throw and returns a string); test
non-Tauri routing by mocking isTauriEnvironment to return false and using
jest.spyOn on console.debug/info/warn/error to verify
logger.debug/info/warn/error/log call the corresponding console methods with
expected args; test Tauri routing by mocking isTauriEnvironment to return true
and replacing tauriDebug/tauriInfo/tauriWarn/tauriError/tauriTrace with
jest.fn() to assert they are called with the stringify(...) output when invoking
logger.trace/debug/info/warn/error; import the exported stringify and default
logger to locate and run these tests.
frontend/src-tauri/Cargo.toml (1)

40-40: Loose version specifier inconsistent with other plugin dependencies

Every other plugin in this file is pinned to a full major.minor.patch version (e.g., tauri-plugin-shell = "2.3.3"). Using "2" for tauri-plugin-log accepts any 2.x.y release, making builds less reproducible and potentially pulling in breaking minor-version changes on a clean cargo update.

-tauri-plugin-log = "2"
+tauri-plugin-log = "2.2.3"  # pin to the resolved version from Cargo.lock
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src-tauri/Cargo.toml` at line 40, The dependency for
tauri-plugin-log uses a loose specifier ("2") which is inconsistent with other
plugin entries; update tauri-plugin-log to a full semantic version pin
(major.minor.patch) to match the format used by other plugins (for example, use
the same full version as tauri-plugin-shell) so builds remain reproducible and
avoid unintentional upgrades.
frontend/src/hooks/selectFile.ts (2)

3-4: Missing blank line between the last import and the interface declaration

✏️ Proposed fix
 import logger from '@/utils/logger';
+
 interface UseFolderPickerOptions {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/hooks/selectFile.ts` around lines 3 - 4, Add a blank line after
the last import to separate imports from type declarations: insert a single
empty line between "import logger from '@/utils/logger';" and the "interface
UseFolderPickerOptions" declaration to follow code-style conventions and improve
readability.

34-34: Capitalization inconsistency in the log message

"Error picking File:" capitalizes File unlike every other log message in this PR ("Error fetching videos:", "Error reading or parsing folder paths from localStorage:", etc.).

✏️ Proposed fix
-      logger.error('Error picking File:', error);
+      logger.error('Error picking file:', error);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/hooks/selectFile.ts` at line 34, The log message in selectFile
uses inconsistent capitalization ("Error picking File:"); update the
logger.error call inside the selectFile hook (the logger.error(...) invocation)
to use consistent lowercase for "file" (e.g., "Error picking file:") so it
matches other messages like "Error fetching videos:" and maintain existing error
argument passing.
frontend/src/hooks/useUpdater.ts (1)

48-50: update.body (release notes) can produce large/multiline log entries.

Consider logging update.version and update.date separately and omitting or truncating update.body, which is often multi-paragraph Markdown.

♻️ Suggested refactor
-      logger.info(
-        `Found update ${update.version} from ${update.date} with notes ${update.body}`,
-      );
+      logger.info(`Found update ${update.version} from ${update.date}`);
+      logger.debug(`Update notes: ${update.body}`);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/hooks/useUpdater.ts` around lines 48 - 50, The current
logger.info call in useUpdater.ts inserts the full update.body which can be
large/multiline; change the logging in the useUpdater logic to log
update.version and update.date as separate fields and either omit update.body
entirely or replace it with a truncated/sanitized summary (e.g., first N chars
or single-line excerpt) before passing to logger.info; update the call site that
uses logger.info(...) so it references update.version and update.date explicitly
and uses a shortSummary variable instead of update.body.
frontend/src/hooks/useFolder.ts (1)

19-36: Destructure the error field from usePictoMutation and include it in error logs for better debugging context.

addFolderError is only the boolean flag (isError). The actual error object is available from usePictoMutation via the UseMutationResult spread and should be passed to logger.error(), matching the pattern used at line 52 with pickSingleFolder.

♻️ Suggested refactor
  const {
    mutate: addFolderMutate,
    isSuccess: addFolderSuccess,
    isError: addFolderError,
    isPending: addFolderPending,
+   error: addFolderErrorObj,
  } = usePictoMutation({
    mutationFn: async (folder_path: string) => addFolder({ folder_path }),
    autoInvalidateTags: ['folders'],
  });

  useEffect(() => {
    if (addFolderPending) {
      logger.info('Adding folder...');
    } else if (addFolderSuccess) {
      logger.info('Folder added successfully');
    } else if (addFolderError) {
-     logger.error('Error adding folder');
+     logger.error('Error adding folder', addFolderErrorObj);
    }
  }, [addFolderSuccess, addFolderError, addFolderPending, addFolderErrorObj]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/hooks/useFolder.ts` around lines 19 - 36, Destructure the error
object from usePictoMutation alongside mutate/isSuccess/isError/isPending (e.g.,
const { mutate: addFolderMutate, isSuccess: addFolderSuccess, isError:
addFolderError, isPending: addFolderPending, error: addFolderErrorObj } =
usePictoMutation(...)) and pass that error into the logger.error call inside the
effect (replace logger.error('Error adding folder') with logger.error('Error
adding folder', addFolderErrorObj)) so the actual error details from
usePictoMutation (used for addFolder) are logged; follow the same pattern used
for pickSingleFolder.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src-tauri/src/main.rs`:
- Line 193: The tauri_plugin_log plugin is currently initialized with
tauri_plugin_log::Builder::new().build() which leaves the logger with default
(too-verbose) levels and default KeepOne rotation; update the Builder
configuration before build() to set a sensible minimum log level (e.g., Info or
Warn), set a maximum file size cap, and choose an explicit rotation strategy
(e.g., Rotate or KeepAll as appropriate) so production builds don’t write
trace/debug logs to disk or silently discard history; locate the plugin
initialization call (tauri_plugin_log::Builder::new().build()) and chain the
appropriate methods on Builder to set level, file_size, and rotation before
calling build().

In `@frontend/src/components/Media/ImageCard.tsx`:
- Around line 81-85: The logger.debug call is executed unconditionally in the
onClick handler and can emit "Toggling favourite for image: undefined"; move the
logging into the existing guard inside handleToggleFavourite so it only runs
when image?.id is truthy. Specifically, remove the logger.debug from the onClick
lambda and add logger.debug('Toggling favourite for image:', image.id)
immediately inside the if (image?.id) block in handleToggleFavourite (which then
calls toggleFavourite(image.id)); ensure the useCallback dependencies for
handleToggleFavourite still include image and toggleFavourite.

In `@frontend/src/components/Memories/MemoryViewer.tsx`:
- Line 62: The current stringify implementation in logger.ts doesn't serialize
Error objects (they become {}), so update the stringify function to detect when
an argument is an Error and return a JSON string containing its name, message,
and stack; for other objects use JSON.stringify(arg, null, 2) and for primitives
use String(arg). Ensure this change affects all logging methods that call
stringify (e.g., logger.error used in MemoryViewer.tsx) so disk logs capture
useful error details.

In `@frontend/src/utils/logger.ts`:
- Around line 20-26: The stringify function currently loses Error details and
throws on circular structures; update stringify to detect Error instances and
return a stable representation including name, message, and stack (e.g., { name,
message, stack, ...enumerableProps }), and implement a circular-safe serializer:
use a replacer that tracks seen objects in a WeakSet and replaces circular
references with "[Circular]" (or fall back to String(obj) if serialization still
fails); keep non-object values as String(arg). Make these changes inside the
existing stringify(...) function so calls like logger.error(..., someError)
produce a useful string and the serializer no longer throws on circular
references.

---

Outside diff comments:
In `@frontend/src/features/imageSlice.ts`:
- Around line 29-33: The reducer in imageSlice calls logger.warn which delegates
to tauriWarn (an async function) and can create an unhandled Promise; to fix
this, modify the logger implementation (the tauriWarn invocation used by
logger.warn) to attach a .catch handler that logs to console or swallow the
error so the call remains synchronous from the reducer's perspective, e.g.,
ensure tauriWarn(...).catch(err => console.error('Logger error:', err)); do not
introduce awaits or async calls inside the reducer—alternatively move the
warning out of the reducer into middleware or an action handler if you want
async handling centralized.

---

Nitpick comments:
In `@frontend/src-tauri/Cargo.toml`:
- Line 40: The dependency for tauri-plugin-log uses a loose specifier ("2")
which is inconsistent with other plugin entries; update tauri-plugin-log to a
full semantic version pin (major.minor.patch) to match the format used by other
plugins (for example, use the same full version as tauri-plugin-shell) so builds
remain reproducible and avoid unintentional upgrades.

In `@frontend/src/hooks/selectFile.ts`:
- Around line 3-4: Add a blank line after the last import to separate imports
from type declarations: insert a single empty line between "import logger from
'@/utils/logger';" and the "interface UseFolderPickerOptions" declaration to
follow code-style conventions and improve readability.
- Line 34: The log message in selectFile uses inconsistent capitalization
("Error picking File:"); update the logger.error call inside the selectFile hook
(the logger.error(...) invocation) to use consistent lowercase for "file" (e.g.,
"Error picking file:") so it matches other messages like "Error fetching
videos:" and maintain existing error argument passing.

In `@frontend/src/hooks/useFolder.ts`:
- Around line 19-36: Destructure the error object from usePictoMutation
alongside mutate/isSuccess/isError/isPending (e.g., const { mutate:
addFolderMutate, isSuccess: addFolderSuccess, isError: addFolderError,
isPending: addFolderPending, error: addFolderErrorObj } = usePictoMutation(...))
and pass that error into the logger.error call inside the effect (replace
logger.error('Error adding folder') with logger.error('Error adding folder',
addFolderErrorObj)) so the actual error details from usePictoMutation (used for
addFolder) are logged; follow the same pattern used for pickSingleFolder.

In `@frontend/src/hooks/useUpdater.ts`:
- Around line 48-50: The current logger.info call in useUpdater.ts inserts the
full update.body which can be large/multiline; change the logging in the
useUpdater logic to log update.version and update.date as separate fields and
either omit update.body entirely or replace it with a truncated/sanitized
summary (e.g., first N chars or single-line excerpt) before passing to
logger.info; update the call site that uses logger.info(...) so it references
update.version and update.date explicitly and uses a shortSummary variable
instead of update.body.

In `@frontend/src/utils/logger.ts`:
- Around line 28-73: isTauriEnvironment() is being called on every logger method
call (trace, debug, info, warn, error, log) which is unnecessary because its
result is constant for the app lifetime; cache its boolean result at module init
(e.g., const IS_TAURI = isTauriEnvironment()) and update each method in the
logger object to use that cached IS_TAURI instead of calling
isTauriEnvironment() repeatedly, leaving stringify and
tauriTrace/tauriDebug/tauriInfo/tauriWarn/tauriError intact and keeping
logger.log as an alias to logger.info.
- Around line 70-72: The log method relies on implicit this (log(...args) {
this.info(...args) }) which breaks when destructured; change log to not depend
on call-site this by either making it an arrow function (e.g., define log =
(...args) => this.info(...args)) or explicitly forwarding to info using a bound
call (e.g., call/apply this.info with the instance), updating the Logger
class/instance where the methods are defined so destructured const { log } =
logger; log('msg') still works.
- Around line 1-75: Add unit tests that exercise stringify and the logger
branches: test stringify(...) with primitives, null, an Error instance (ensuring
message and stack are included), and a circular reference (assert it doesn't
throw and returns a string); test non-Tauri routing by mocking
isTauriEnvironment to return false and using jest.spyOn on
console.debug/info/warn/error to verify logger.debug/info/warn/error/log call
the corresponding console methods with expected args; test Tauri routing by
mocking isTauriEnvironment to return true and replacing
tauriDebug/tauriInfo/tauriWarn/tauriError/tauriTrace with jest.fn() to assert
they are called with the stringify(...) output when invoking
logger.trace/debug/info/warn/error; import the exported stringify and default
logger to locate and run these tests.

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.

🧹 Nitpick comments (1)
frontend/src/hooks/useFolderOperations.tsx (1)

79-89: Redundant dual-log for a single error event.

Both logger.error (line 80) and logger.warn (line 83) fire unconditionally together whenever taggingStatusQuery.isError is true, producing two log entries for one failure. The warn's errorMessage is derived from the same error already captured by the error call, so it adds little value while mixing severity semantics (error + warn for the same condition). Consolidate into a single logger.error call:

♻️ Proposed consolidation
  useEffect(() => {
    if (taggingStatusQuery.isError) {
-     logger.error('Failed to fetch tagging status:', taggingStatusQuery.error);
-
-     const errorMessage = taggingStatusQuery.errorMessage || 'Unknown error';
-     logger.warn(`Tagging status query failed: ${errorMessage}`);
+     const errorMessage = taggingStatusQuery.errorMessage || 'Unknown error';
+     logger.error(`Failed to fetch tagging status: ${errorMessage}`, taggingStatusQuery.error);
    }
  }, [
    taggingStatusQuery.isError,
    taggingStatusQuery.error,
    taggingStatusQuery.errorMessage,
  ]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/hooks/useFolderOperations.tsx` around lines 79 - 89, The code
logs the same failure twice when taggingStatusQuery.isError is true; consolidate
the two logs into a single error log by removing the redundant logger.warn and
updating the logger.error call (in useFolderOperations.tsx around the
taggingStatusQuery handling) to include the derived errorMessage
(taggingStatusQuery.errorMessage || 'Unknown error') alongside
taggingStatusQuery.error so only one descriptive error-level entry is emitted
for the taggingStatusQuery failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@frontend/src/hooks/useFolderOperations.tsx`:
- Around line 79-89: The code logs the same failure twice when
taggingStatusQuery.isError is true; consolidate the two logs into a single error
log by removing the redundant logger.warn and updating the logger.error call (in
useFolderOperations.tsx around the taggingStatusQuery handling) to include the
derived errorMessage (taggingStatusQuery.errorMessage || 'Unknown error')
alongside taggingStatusQuery.error so only one descriptive error-level entry is
emitted for the taggingStatusQuery failure.

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.

🧹 Nitpick comments (2)
frontend/src/utils/logger.ts (2)

103-106: this.info(...) in log breaks if the method is destructured.

const { log } = logger;
log('hello'); // TypeError: Cannot read properties of undefined (reading 'info')

Since logger is a module-level const, referencing it directly avoids the this binding issue entirely (the method body only runs after logger is fully initialised).

♻️ Proposed fix
-  /** Alias for info — drop-in replacement for console.log */
-  log(...args: unknown[]) {
-    this.info(...args);
-  },
+  /** Alias for info — drop-in replacement for console.log */
+  log(...args: unknown[]) {
+    logger.info(...args);
+  },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/utils/logger.ts` around lines 103 - 106, The log method
currently uses this.info(...args) which fails when the method is destructured;
change the implementation of the log method to call the module-level logger
directly (use logger.info(...args)) so it doesn't rely on this binding—update
the log(...) method in the logger object to reference the top-level logger const
and call its info method.

62-101: Cache isTauriEnvironment() at module scope instead of calling it on every log invocation.

isTauriEnvironment() involves a try/catch plus two 'in window' guard checks and is invoked once per log call across all five methods. Since the runtime environment is static for the app's lifetime, re-evaluating this on every logger.* call is unnecessary overhead.

♻️ Proposed refactor
+const IS_TAURI = isTauriEnvironment();
+
 const logger = {
   trace(...args: unknown[]) {
-    if (isTauriEnvironment()) {
+    if (IS_TAURI) {
       tauriTrace(stringify(...args));
     } else {
       console.debug('[TRACE]', ...args);
     }
   },

   debug(...args: unknown[]) {
-    if (isTauriEnvironment()) {
+    if (IS_TAURI) {
       tauriDebug(stringify(...args));
     } else {
       console.debug(...args);
     }
   },

   info(...args: unknown[]) {
-    if (isTauriEnvironment()) {
+    if (IS_TAURI) {
       tauriInfo(stringify(...args));
     } else {
       console.info(...args);
     }
   },

   warn(...args: unknown[]) {
-    if (isTauriEnvironment()) {
+    if (IS_TAURI) {
       tauriWarn(stringify(...args));
     } else {
       console.warn(...args);
     }
   },

   error(...args: unknown[]) {
-    if (isTauriEnvironment()) {
+    if (IS_TAURI) {
       tauriError(stringify(...args));
     } else {
       console.error(...args);
     }
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/utils/logger.ts` around lines 62 - 101, Cache the result of
isTauriEnvironment() in a module-level constant (e.g., const IS_TAURI =
isTauriEnvironment()) and use that constant inside logger.trace, logger.debug,
logger.info, logger.warn, and logger.error instead of calling
isTauriEnvironment() on every invocation; update each method to branch on the
cached IS_TAURI value while leaving
tauriTrace/tauriDebug/tauriInfo/tauriWarn/tauriError and stringify usage
unchanged so the runtime environment is evaluated once at module load.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@frontend/src/utils/logger.ts`:
- Around line 103-106: The log method currently uses this.info(...args) which
fails when the method is destructured; change the implementation of the log
method to call the module-level logger directly (use logger.info(...args)) so it
doesn't rely on this binding—update the log(...) method in the logger object to
reference the top-level logger const and call its info method.
- Around line 62-101: Cache the result of isTauriEnvironment() in a module-level
constant (e.g., const IS_TAURI = isTauriEnvironment()) and use that constant
inside logger.trace, logger.debug, logger.info, logger.warn, and logger.error
instead of calling isTauriEnvironment() on every invocation; update each method
to branch on the cached IS_TAURI value while leaving
tauriTrace/tauriDebug/tauriInfo/tauriWarn/tauriError and stringify usage
unchanged so the runtime environment is evaluated once at module load.

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

Labels

CI/CD enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG:Console.log in Production

1 participant