Skip to content

Conversation

AVMatthews
Copy link
Contributor

@AVMatthews AVMatthews commented Feb 21, 2025

Description

Added a field to the settings dialog which allows users to enter a format for the timestamp using DayJS. Used the entered string to format the timestamp displayed in the message.

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

Tested using different format strings and some sample logs to see that the timestamp was correctly formatted.

Summary by CodeRabbit

  • New Features
    • Introduced a new configuration option that lets users specify a Day.js timestamp format for unstructured log timestamps.
    • Added a dedicated input field in the Settings tab with helper text to guide users in setting their preferred timestamp format.
    • Enhanced configuration management to validate, store, and retrieve the specified format consistently.
    • Updated timestamp formatting in log outputs to use the configurable format string.

Copy link

coderabbitai bot commented Feb 21, 2025

## Walkthrough

This pull request introduces enhancements for timestamp formatting in log decoding and configuration management. In the `ClpIrDecoder` class, a new private property and method are added to format timestamps using the dayjs library. Configuration interfaces, enums, and default settings are updated to include the new `timestampFormatString` property. Additionally, a new form field for specifying the timestamp format is incorporated into the settings panel, and tests are adjusted to validate the new functionality.

## Changes

| File(s)                                              | Change Summary                                                                                                                          |
|-----------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| `src/services/decoders/ClpIrDecoder/index.ts`       | Added private property `#timestampFormatString` and new instance method `#formatUnstructuredResults` to format timestamps using dayjs. Updated `decodeRange` to use the new instance method instead of the removed static method. |
| `src/typings/config.ts`, `src/typings/decoders.ts` | Added `DECODER_OPTIONS_TIMESTAMP_FORMAT_STRING` enum entry and `timestampFormatString` property in `DecoderOptions` interface.          |
| `src/utils/config.ts`, `test/utils/config.test.ts`  | Added `timestampFormatString` to default config, validation, local storage get/set operations, and updated tests to include validation error and storage assertion. |
| `src/components/CentralContainer/Sidebar/SidebarTabs/SettingsTabPanel/index.tsx` | Added new form field for timestamp format string with helper text, initial value, unique local storage key, and updated form submission to include this property in configuration. |

## Possibly related PRs

- **y-scope/yscope-log-viewer#209:** Refactored `ClpIrDecoder` timestamp formatting method from static to instance and introduced configurable timestamp format string.

## Suggested reviewers

- kirkrodrigues

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm warn config production Use --omit=dev instead.
npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-05-28T15_59_03_588Z-debug-0.log


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7ec7a3c and abececb.

📒 Files selected for processing (1)
  • src/services/decoders/ClpIrDecoder/index.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • src/services/decoders/ClpIrDecoder/index.ts
🧬 Code Graph Analysis (1)
src/services/decoders/ClpIrDecoder/index.ts (3)
src/typings/decoders.ts (1)
  • DecodeResult (108-108)
src/typings/common.ts (1)
  • Nullable (10-10)
src/services/decoders/JsonlDecoder/utils.ts (1)
  • convertToDayjsTimestamp (81-81)
🔇 Additional comments (3)
src/services/decoders/ClpIrDecoder/index.ts (3)

40-40: LGTM!

The private property declaration follows TypeScript conventions and integrates well with the class structure.


54-54: LGTM!

The constructor properly initializes the timestamp format string from decoder options, maintaining consistency with the existing initialization pattern.


145-145: LGTM!

The change from static method call to instance method call is correct and allows the method to access the instance-specific timestamp format string.

✨ Finishing Touches
  • 📝 Generate Docstrings

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 docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in 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.

@AVMatthews AVMatthews marked this pull request as ready for review March 6, 2025 17:40
@AVMatthews AVMatthews requested a review from a team as a code owner March 6, 2025 17:40
Copy link

@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

🧹 Nitpick comments (1)
src/components/modals/SettingsModal/SettingsDialog.tsx (1)

79-85: Type inconsistency with other form fields

The type property is set to "string", while other similar form fields in this component use "text". Consider changing to "text" for consistency.

-        type: "string",
+        type: "text",

Additionally, consider enhancing the helper text with a link to Day.js documentation, similar to how the format string field includes documentation links.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0418be7 and fa00493.

📒 Files selected for processing (5)
  • src/components/modals/SettingsModal/SettingsDialog.tsx (2 hunks)
  • src/services/decoders/ClpIrDecoder/index.ts (5 hunks)
  • src/typings/config.ts (1 hunks)
  • src/typings/decoders.ts (1 hunks)
  • src/utils/config.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ...

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • src/typings/decoders.ts
  • src/typings/config.ts
  • src/utils/config.ts
  • src/components/modals/SettingsModal/SettingsDialog.tsx
  • src/services/decoders/ClpIrDecoder/index.ts
🧠 Learnings (1)
src/services/decoders/ClpIrDecoder/index.ts (1)
Learnt from: davemarco
PR: y-scope/yscope-log-viewer#123
File: src/services/decoders/ClpIrDecoder.ts:90-90
Timestamp: 2024-11-18T01:35:37.012Z
Learning: Within `ClpIrDecoder.ts`, in the `setFormatterOptions` method, `options.formatString` is already typed as a string, so explicit casting to string is unnecessary.
🔇 Additional comments (13)
src/typings/decoders.ts (1)

19-19: Looks good - Clean interface extension.

This addition to the DecoderOptions interface properly aligns with the existing properties and enables the new timestamp formatting functionality.

src/typings/config.ts (1)

23-23: Enum addition follows consistent naming pattern.

The new storage key follows the established pattern and properly uses template literals to combine the base key with the specific property name.

src/services/decoders/ClpIrDecoder/index.ts (4)

5-5: Appropriate import for the new functionality.

The dayjs import is necessary for the new timestamp formatting feature.


40-40: Private field follows class style conventions.

The private field declaration uses the modern private field syntax with the # prefix, consistent with other class members.


53-53: Property initialization is clean and straightforward.

The timestamp format string is properly initialized from the decoder options.


147-147: Method call correctly added to return path.

The formatResults method is now properly called when no formatter is set, ensuring consistent timestamp formatting.

src/utils/config.ts (4)

31-31: Good default timestamp format choice.

The ISO 8601 format "YYYY-MM-DDTHH:mm:ssZ" is a sensible default for timestamp formatting.


55-56: Appropriate validation for required field.

The validation ensures that the timestamp format string is not empty, which is important for proper functionality.


108-111: Storage implementation follows established pattern.

The implementation for storing the timestamp format string in local storage follows the same pattern as other configuration properties.


154-156: Retrieval implementation follows established pattern.

The implementation for retrieving the timestamp format string from local storage follows the same pattern as other configuration properties.

src/components/modals/SettingsModal/SettingsDialog.tsx (3)

123-125: Looks good - correct extraction of the new timestamp format

The implementation correctly extracts the timestamp format string from the form data.


131-131: Looks good - proper configuration update

The code correctly includes the new timestampFormatString in the configuration object.


138-138: Consider using Yoda condition style

Based on coding guidelines, prefer false == <expression> rather than !<expression>. In this case, consider changing null !== error to null !== error.

Oh wait, this is already using the preferred style! This code follows the guidelines correctly.

Comment on lines 113 to 124
formatResults (results: DecodeResult[]): Nullable<DecodeResult[]> {
for (const r of results) {
const [
message, timestamp,
] = r;

const formattedTimestamp = dayjs(timestamp).format(this.#timestampFormatString);
r[0] = formattedTimestamp + message;
}

return results;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Potential issue with timestamp duplication in formatted messages.

The current implementation prepends the formatted timestamp to the message without checking if the message already includes a timestamp. This could lead to duplicate timestamps in the output.

Additionally, the method directly mutates the input array, which might cause unexpected side effects if the caller expects the original array to remain unchanged.

Consider this alternative implementation:

formatResults (results: DecodeResult[]): Nullable<DecodeResult[]> {
-    for (const r of results) {
-        const [
-            message, timestamp,
-        ] = r;
-
-        const formattedTimestamp = dayjs(timestamp).format(this.#timestampFormatString);
-        r[0] = formattedTimestamp + message;
-    }
-
-    return results;
+    // Create a shallow copy to avoid mutating the input array
+    const formattedResults = [...results];
+    
+    for (const r of formattedResults) {
+        const [message, timestamp] = r;
+        const formattedTimestamp = dayjs(timestamp).format(this.#timestampFormatString);
+        
+        // Replace the message with the timestamp-formatted message
+        r[0] = formattedTimestamp + ' ' + message;
+    }
+    
+    return formattedResults;
}
📝 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
formatResults (results: DecodeResult[]): Nullable<DecodeResult[]> {
for (const r of results) {
const [
message, timestamp,
] = r;
const formattedTimestamp = dayjs(timestamp).format(this.#timestampFormatString);
r[0] = formattedTimestamp + message;
}
return results;
}
formatResults (results: DecodeResult[]): Nullable<DecodeResult[]> {
// Create a shallow copy to avoid mutating the input array
const formattedResults = [...results];
for (const r of formattedResults) {
const [message, timestamp] = r;
const formattedTimestamp = dayjs(timestamp).format(this.#timestampFormatString);
// Replace the message with the timestamp-formatted message
r[0] = formattedTimestamp + ' ' + message;
}
return formattedResults;
}

Copy link

@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: 0

🧹 Nitpick comments (1)
test/utils/config.test.ts (1)

154-158: Code style inconsistency with other assertions

The formatting of this localStorage assertion spans multiple lines, while the previous assertions on lines 145-153 use a single line format. Consider keeping the same style for consistency.

-        expect(localStorage.getItem(
-            LOCAL_STORAGE_KEY.DECODER_OPTIONS_TIMESTAMP_FORMAT_STRING
-        )).toBe(
-            VALID_DECODER_OPTIONS.timestampFormatString
-        );
+        expect(localStorage.getItem(LOCAL_STORAGE_KEY.DECODER_OPTIONS_TIMESTAMP_FORMAT_STRING)).toBe(
+            VALID_DECODER_OPTIONS.timestampFormatString
+        );
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fa00493 and 7217fb9.

📒 Files selected for processing (1)
  • test/utils/config.test.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ...

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • test/utils/config.test.ts
🔇 Additional comments (2)
test/utils/config.test.ts (2)

30-30: LGTM: New configuration property added correctly

The addition of the timestampFormatString property to VALID_DECODER_OPTIONS properly supports the new feature for custom timestamp rendering using DayJS.


61-61: LGTM: Appropriate validation error message added

The error message for empty timestamp format string is consistent with the validation pattern for other configuration properties.

Copy link
Member

@junhaoliao junhaoliao left a comment

Choose a reason for hiding this comment

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

mostly just nit-picking

will be great if we can get some insights for the settings UI text from @LinZhihao-723 / @kirkrodrigues

type: "text",
},
{
helperText: "Day.js format string for timestamp",
Copy link
Member

Choose a reason for hiding this comment

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

how about

Suggested change
helperText: "Day.js format string for timestamp",
helperText: "[Unstructured-IR] Format string for timestamps in CLP unstructured IR logs, in Day.js format.",

Copy link
Member

Choose a reason for hiding this comment

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

@LinZhihao-723 / @kirkrodrigues any thoughts?

@junhaoliao
Copy link
Member

junhaoliao commented Mar 10, 2025

for the PR title, how about:

feat!: Support custom timestamp formatting for Unstructured IR logs (fixes #201).

I consider this as a breaking change because now we format the logs in the user browser's timezone, instead of UTC as previously done. Until #207 is implemented, there is no way to format timestamps in UTC.

@AVMatthews AVMatthews changed the title feat(settings): enable custom timestamp rendering using days feat!: Support custom timestamp formatting for Unstructured IR logs (fixes #201). Mar 14, 2025
@junhaoliao
Copy link
Member

@AVMatthews let me know when this is ready for review. in case you haven't already, let's merge main into your branch and resolve the conflicts

@AVMatthews AVMatthews requested a review from junhaoliao March 17, 2025 22:48
Copy link
Member

@junhaoliao junhaoliao left a comment

Choose a reason for hiding this comment

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

almost good

@junhaoliao
Copy link
Member

As the web development team discussed offline, we may want to separate the settings into different tabs. I created a feature request to track this: #215 and we can implement that in a separate PR.

@AVMatthews AVMatthews requested a review from junhaoliao March 20, 2025 16:46
Copy link

@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

♻️ Duplicate comments (1)
src/services/decoders/ClpIrDecoder/index.ts (1)

182-196: 🛠️ Refactor suggestion

Address input mutation and formatting spacing.

The current implementation has two concerns:

  1. Input mutation: The method directly modifies the input array, which could cause unexpected side effects if the caller expects the original array to remain unchanged.
  2. Missing separator: The formatted timestamp is concatenated directly with the message without a space separator, which may make the output less readable.

Consider this improved implementation:

 #formatUnstructuredResults (logEvents: DecodeResult[]): Nullable<DecodeResult[]> {
+    // Create a shallow copy to avoid mutating the input array
+    const formattedResults = [...logEvents];
+    
-    for (const r of logEvents) {
+    for (const r of formattedResults) {
         const [
             message, timestamp,
         ] = r;

         const formattedTimestamp = convertToDayjsTimestamp(timestamp).format(
             this.#timestampFormatString
         );

-        r[0] = formattedTimestamp + message;
+        r[0] = formattedTimestamp + " " + message;
     }

-    return logEvents;
+    return formattedResults;
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a77c9e3 and 7ec7a3c.

📒 Files selected for processing (3)
  • src/components/CentralContainer/Sidebar/SidebarTabs/SettingsTabPanel/index.tsx (2 hunks)
  • src/services/decoders/ClpIrDecoder/index.ts (4 hunks)
  • src/utils/config.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • src/services/decoders/ClpIrDecoder/index.ts
  • src/components/CentralContainer/Sidebar/SidebarTabs/SettingsTabPanel/index.tsx
  • src/utils/config.ts
🧬 Code Graph Analysis (2)
src/services/decoders/ClpIrDecoder/index.ts (3)
src/typings/decoders.ts (1)
  • DecodeResult (108-108)
src/typings/common.ts (1)
  • Nullable (10-10)
src/services/decoders/JsonlDecoder/utils.ts (1)
  • convertToDayjsTimestamp (81-81)
src/components/CentralContainer/Sidebar/SidebarTabs/SettingsTabPanel/index.tsx (3)
src/utils/config.ts (2)
  • getConfig (192-192)
  • setConfig (195-195)
src/typings/config.ts (2)
  • CONFIG_KEY (45-45)
  • LOCAL_STORAGE_KEY (46-46)
src/typings/common.ts (1)
  • Nullable (10-10)
🔇 Additional comments (6)
src/utils/config.ts (3)

30-30: Good default timestamp format string choice.

The default format "YYYY-MM-DDTHH:mm:ss.SSSZ" follows ISO 8601 standard with milliseconds and timezone, which is appropriate for log timestamps.


53-56: Validation logic is consistent and well-placed.

The validation for timestampFormatString follows the same pattern as other configuration validations and maintains alphabetical order in the validation checks.


104-107: Local storage operations follow established patterns.

The implementation correctly handles persistence and retrieval of the timestamp format string, maintaining consistency with other decoder options.

Also applies to: 151-153

src/services/decoders/ClpIrDecoder/index.ts (1)

40-40: Good integration of timestamp format configuration.

The private property is properly initialized from decoder options, following the established pattern for configuration injection.

Also applies to: 54-54

src/components/CentralContainer/Sidebar/SidebarTabs/SettingsTabPanel/index.tsx (2)

112-118: Well-structured form field addition.

The new timestamp format string field follows the established pattern and includes helpful context in the helper text about Day.js format and its specific application to unstructured IR logs.


154-156: Proper integration with form submission logic.

The form data extraction and configuration update correctly includes the new timestamp format string field, maintaining consistency with the existing configuration management pattern.

Also applies to: 163-163

Copy link
Member

@junhaoliao junhaoliao left a comment

Choose a reason for hiding this comment

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

please fix one nit before i approve

@junhaoliao
Copy link
Member

For the PR title, how about removing the !? i.e.,

feat: Support custom timestamp formatting for Unstructured IR logs (fixes #201).

The new config option value, retrieved from a newly added key in localStorage, is not necessarily incompatible with previous deployments, so we may not need to mark this change as BREAKING

@AVMatthews AVMatthews changed the title feat!: Support custom timestamp formatting for Unstructured IR logs (fixes #201). feat: Support custom timestamp formatting for Unstructured IR logs (fixes #201). May 28, 2025
@AVMatthews AVMatthews requested a review from junhaoliao May 28, 2025 15:59
@AVMatthews AVMatthews merged commit 4a75581 into y-scope:main May 28, 2025
4 checks passed
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.

2 participants