Skip to content

feat: add structured winston logging to cloud functionsComp log#366

Merged
roshankumar0036singh merged 1 commit into
roshankumar0036singh:mainfrom
shreyjeetdas:comp-log
Jun 1, 2026
Merged

feat: add structured winston logging to cloud functionsComp log#366
roshankumar0036singh merged 1 commit into
roshankumar0036singh:mainfrom
shreyjeetdas:comp-log

Conversation

@shreyjeetdas
Copy link
Copy Markdown
Contributor

@shreyjeetdas shreyjeetdas commented May 28, 2026

Screenshot (when helpful)

N/A — backend logging implementation, no UI involved.

What this PR does

The cloud functions had no structured logging, making it impossible
to trace requests, debug issues, or monitor function behaviour in
production.

This PR adds a dedicated logger.ts module using winston that
produces structured JSON logs in the format:
{ timestamp, level, service, eventId, userId, message, context, stack }

The logger exposes two functions:

  • logEntry() — logs function entry/exit points with input/output
  • logError() — logs errors with full stack trace

dailyDigest.ts has been updated to use the new logger at all key
points: function start, no-events early return, broadcast start,
push notification sending, error handling, and function completion.

Type of change

  • Bug fix
  • New feature
  • Code refactor
  • Documentation update

Related issue

Fixes #327

More screenshots (optional)

N/A

Checklist

  • I have added screenshots or a recording when they help explain this PR, or noted N/A with a one-line reason.
  • I have filled in the related issue number when there is one.
  • I have tested my changes.
  • I have done a self-review of the code.

Summary by CodeRabbit

  • Refactor

    • Improved notification initialization for more reliable delivery.
  • Chores

    • Added structured JSON logging across the daily digest and push delivery flow, including lifecycle checkpoints, message counts, and captured send errors.
    • Introduced a logging library to support the new structured logs.
  • Stability

    • No changes to public callable interfaces or returned signatures.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a Winston-based structured logger and instruments the sendDailyDigest cloud function: logs function start (with input), the no-events early return, notification dispatch (message count), chunk send errors via logError, and final completion; also adds winston deps.

Changes

Daily Digest Logging

Layer / File(s) Summary
Winston logger and helpers
cloud-functions/src/logger.ts, cloud-functions/package.json
Adds a configured JSON console logger, and exports logEntry and logError helpers that emit structured info/error logs with ISO timestamps, normalized context fields, and error stacks; adds winston and @types/winston deps.
Import, init, and startup log
cloud-functions/src/dailyDigest.ts
Imports logging helpers and switches expo-server-sdk usage to a module-scope ES default import plus new Expo(); emits a startup log entry including callable input.
No-events and dispatch instrumentation
cloud-functions/src/dailyDigest.ts
Logs the "no events today" early-return path; before broadcasting, logs a dispatch entry with message count; wraps chunk sends to report errors via logError (keeps existing console.error) and logs final completion with event count and optional processed counter.

Sequence Diagram

sequenceDiagram
  participant Client
  participant sendDailyDigest
  participant logger
  participant Expo
  Client->>sendDailyDigest: invoke callable with input
  sendDailyDigest->>logger: logEntry("dailyDigest/sendDailyDigest started", input)
  sendDailyDigest->>sendDailyDigest: compute events and count
  alt no events
    sendDailyDigest->>logger: logEntry("no events today")
    sendDailyDigest-->>Client: return success
  else events present
    sendDailyDigest->>logger: logEntry("broadcasting", { count })
    loop per chunk
      sendDailyDigest->>Expo: sendPushNotifications(chunk)
      Expo-->>sendDailyDigest: response / error
      sendDailyDigest->>logger: logError(on chunk send failure)
    end
    sendDailyDigest->>logger: logEntry("completed", { count, processed? })
    sendDailyDigest-->>Client: return success with counts
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • roshankumar0036singh/Uni-Event#261: Both PRs modify cloud-functions/src/dailyDigest.ts to change the expo-server-sdk import from require() to an ES-module default import.

Suggested labels

level:intermediate, quality:clean

Poem

🐰 I hopped into logs at break of day,
JSON carrots lined up in a row,
ES imports snug, stacks shown with care,
Counts and errors all in tow,
The digest sang — and I did glow!

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding structured Winston logging to cloud functions.
Linked Issues check ✅ Passed The PR implements all requirements from issue #327: uses winston for structured logging with required schema, logs function entry/exit points, includes request/event ID support, and enables Cloud Logging export.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing structured logging as specified in issue #327; no unrelated modifications were introduced.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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
Copy Markdown
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cloud-functions/src/dailyDigest.ts`:
- Line 5: The file logger.ts is empty so logEntry/logError have no
implementation and dailyDigest.ts still uses console.error in the push-send
failure path; implement and export structured logging functions in
cloud-functions/src/logger.ts (export logEntry and logError with signatures that
accept message, context object, and optional Error), then update
cloud-functions/src/dailyDigest.ts to replace the console.error(...) call in the
push-send failure block with logError(errorMessage, { event:
'dailyDigest.pushSend', payload: pushPayload, response: sendResponse }, err) (or
similar) so errors are emitted in structured JSON; ensure imports remain {
logEntry, logError } and that logError includes both the error object and
contextual fields for observability.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 36423a42-6184-49a1-bad2-32435ead3fac

📥 Commits

Reviewing files that changed from the base of the PR and between d6df931 and e1665f9.

📒 Files selected for processing (2)
  • cloud-functions/src/dailyDigest.ts
  • cloud-functions/src/logger.ts

Comment thread cloud-functions/src/dailyDigest.ts Outdated
Copy link
Copy Markdown
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cloud-functions/src/logger.ts`:
- Around line 43-61: The logError function assumes error is an Error and reads
error.stack directly; defend it so logging never throws: inside logError
validate the runtime value (use instanceof Error or typeof checks) and derive
safe values for stack and error message—e.g., if error is an Error use
error.stack and error.message; if it's a string use that string as message and
null stack; if it's an object JSON.stringify it for message and stack=null; if
null/undefined set message to a default like "unknown error" and stack to
null—then pass those safe values into logger.error along with existing fields.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ff72ed3f-eff5-4fba-88fe-87b6fb10e916

📥 Commits

Reviewing files that changed from the base of the PR and between e1665f9 and 0d056da.

📒 Files selected for processing (2)
  • cloud-functions/src/dailyDigest.ts
  • cloud-functions/src/logger.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • cloud-functions/src/dailyDigest.ts

Comment thread cloud-functions/src/logger.ts
@roshankumar0036singh
Copy link
Copy Markdown
Owner

@shreyjeetdas handle the coderabbity suggestion

Copy link
Copy Markdown
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: 2

Caution

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

⚠️ Outside diff range comments (1)
cloud-functions/src/dailyDigest.ts (1)

3-4: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the named Expo export here.

Line 3 uses a default import, but the upstream expo-server-sdk examples use Expo as a named export for ESM and { Expo } destructuring for CommonJS. This import is brittle under stricter TS/module settings and can fail at type-check or runtime. (github.com)

Suggested fix
-import Expo from 'expo-server-sdk';
+import { Expo } from 'expo-server-sdk';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cloud-functions/src/dailyDigest.ts` around lines 3 - 4, The import uses a
default import for Expo which can break under strict module/TS settings; replace
the default import with the named export (use the named Expo import from
'expo-server-sdk') so that the existing instantiation (const expo = new Expo())
uses the correct named symbol; update the import statement accordingly to import
{ Expo } and leave the rest of the code unchanged.
🧹 Nitpick comments (1)
cloud-functions/package.json (1)

45-45: ⚡ Quick win

Remove the deprecated @types/winston stub.

Line 45 adds a package that Winston no longer needs: the @types/winston package is deprecated, and the winston package already ships its own TypeScript declarations. Keeping both increases the chance of type-version skew between the runtime and the editor/compiler. (npmjs.com)

Suggested fix
-  "`@types/winston`": "^2.4.4",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cloud-functions/package.json` at line 45, Remove the deprecated dependency
entry "`@types/winston`" from package.json; Winston ships its own TypeScript types
so delete the "`@types/winston`" line from the dependencies/devDependencies, run
npm/yarn install to update lockfile, and commit the updated package.json and
lockfile so the project no longer references the deprecated stub.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cloud-functions/package.json`:
- Around line 56-57: The package.json file has a missing comma before the
"private" property which makes the JSON invalid; open the cloud-functions
package.json, locate the trailing brace before the "private" key and insert the
missing comma so the object entries are properly separated (ensure the property
name "private" remains unchanged and the file parses as valid JSON so npm ci
succeeds).

In `@cloud-functions/src/dailyDigest.ts`:
- Around line 34-39: Remove all Git conflict markers (<<<<<<<, =======, >>>>>>>)
and merge the two conflicting branches by combining structured logging and
pagination/response fields: inside the dailyDigest function keep the
logEntry('dailyDigest', ...) call and return the expanded structured result {
success: true, message: "No events today.", count: 0, processed: 0 } so both
behaviors remain; repeat this approach for the other conflict blocks (around the
pagination logic in the middle of the file and the structured logging at the
end) by merging pagination handling with the existing logging/response shape
rather than choosing one side.

---

Outside diff comments:
In `@cloud-functions/src/dailyDigest.ts`:
- Around line 3-4: The import uses a default import for Expo which can break
under strict module/TS settings; replace the default import with the named
export (use the named Expo import from 'expo-server-sdk') so that the existing
instantiation (const expo = new Expo()) uses the correct named symbol; update
the import statement accordingly to import { Expo } and leave the rest of the
code unchanged.

---

Nitpick comments:
In `@cloud-functions/package.json`:
- Line 45: Remove the deprecated dependency entry "`@types/winston`" from
package.json; Winston ships its own TypeScript types so delete the
"`@types/winston`" line from the dependencies/devDependencies, run npm/yarn
install to update lockfile, and commit the updated package.json and lockfile so
the project no longer references the deprecated stub.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8be1ea05-3c8f-4693-af3f-57afab149f69

📥 Commits

Reviewing files that changed from the base of the PR and between 6e6d74c and 868452c.

📒 Files selected for processing (2)
  • cloud-functions/package.json
  • cloud-functions/src/dailyDigest.ts

Comment thread cloud-functions/package.json Outdated
Comment thread cloud-functions/src/dailyDigest.ts Outdated
@roshankumar0036singh
Copy link
Copy Markdown
Owner

@shreyjeetdas check the coderabbit sugesstion for npm ci failing

@shreyjeetdas
Copy link
Copy Markdown
Contributor Author

This is already handled in the current implementation — logError accepts error: unknown and covers all cases: Error instances (extracts message and stack), strings, objects (JSON stringified), and null/undefined (defaults to 'unknown error'). No changes needed.

@roshankumar0036singh
Copy link
Copy Markdown
Owner

@shreyjeetdas you missed soem dependecies

@shreyjeetdas
Copy link
Copy Markdown
Contributor Author

I've added winston as a structured logging dependency in package.json. The package-lock.json needs to be updated by running npm install in the cloud-functions directory. Since I don't have Node.js installed locally, could you update the lock file or let me know the preferred way to handle new dependencies in this project?

@roshankumar0036singh
Copy link
Copy Markdown
Owner

wait till evening i will accept the pr and update the lockfile from my side

@shreyjeetdas
Copy link
Copy Markdown
Contributor Author

@roshankumar0036singh Hi, the PR is still not merged!

@roshankumar0036singh
Copy link
Copy Markdown
Owner

@shreyjeetdas sorry about that missed it can you solve the conlfict

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 1, 2026

@shreyjeetdas
Copy link
Copy Markdown
Contributor Author

Hi @roshankumar0036singh, I've resolved the merge conflict and force-pushed the updated branch. The changes are now based on the latest upstream version.

@roshankumar0036singh roshankumar0036singh merged commit 5db1e22 into roshankumar0036singh:main Jun 1, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add comprehensive logging with structured format (JSON)

2 participants