Skip to content

Conversation

davemarco
Copy link
Contributor

@davemarco davemarco commented Apr 29, 2025

Description

Adds a table which holds search results. Data is currently dummy data.

Syntax highlighting is provided by both react-syntax-highlighter and highlighter.js.

react-syntax-highligher is a react wrapper of highlighter.js. However it dosent have all the themes from highlighter.js, so
I imported highlighter as well to get intelli-light theme.

Reminders for when server implemented:

fancier features like server side filtering are not yet implemented. This will have to wait until server is working.

I took a look at table rendering code in old webui, and there is a fancy sensor to load more results. While its cute, I think we can drop this in new webui as it there are max 1000 results anyways, so I assume the sensor probably has little performance benefit. I also looked at another observability tool as well, and it appears they dont use a sensor to request more results.

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

Table looks okay.

Summary by CodeRabbit

  • New Features
    • Introduced a search results table displaying log search results with sortable columns and syntax-highlighted messages.
    • Added clickable links in search results to open files in an external log viewer.
  • Style
    • Updated styles for the search page layout and search controls for improved appearance and spacing.
    • Added custom styles for syntax highlighting and icon spacing in search results.
  • Chores
    • Added new dependencies to support syntax highlighting in log messages.

@davemarco davemarco requested a review from a team as a code owner April 29, 2025 19:11
Copy link
Contributor

coderabbitai bot commented Apr 29, 2025

Walkthrough

This update introduces a search results table to the log viewer web UI client. New components and supporting files are added for rendering search results with syntax-highlighted messages and links to an external log viewer. The table is currently populated with dummy data and uses Ant Design components for layout and styling. Supporting CSS modules and utility files are included for custom styling. The main search page is updated to visually group the search controls and the new results table. Dependency updates add syntax highlighting libraries and their type definitions to the client application.

Changes

File(s) Change Summary
components/log-viewer-webui/client/package.json Added dependencies: highlight.js, react-syntax-highlighter; added devDependency: @types/react-syntax-highlighter.
components/log-viewer-webui/client/src/pages/SearchPage/SearchControls/index.module.css Removed margin-top and padding from .searchControlsContainer.
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/LogViewerLink.tsx Added new LogViewerLink React component for rendering an external log viewer link with tooltip and icon.
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/index.module.css Added new CSS module with .linkIcon class for icon spacing.
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/index.tsx Added new Message React component for displaying syntax-highlighted messages and a log viewer link.
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/utils.ts Added utility file exporting highlighterCustomStyles for syntax highlighter styling.
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/index.tsx Added new SearchResultsTable React component rendering a table of search results with dummy data.
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/typings.tsx Added typings for search results and table columns, including column configuration for Ant Design Table.
components/log-viewer-webui/client/src/pages/SearchPage/index.module.css Added new CSS module with .searchPageContainer for page layout.
components/log-viewer-webui/client/src/pages/SearchPage/index.tsx Updated SearchPage to wrap content in a new container and include the new SearchResultsTable component.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SearchPage
    participant SearchControls
    participant SearchResultsTable
    participant Message
    participant LogViewerLink

    User->>SearchPage: Loads Search Page
    SearchPage->>SearchControls: Render search controls
    SearchPage->>SearchResultsTable: Render table with dummy results
    SearchResultsTable->>Message: Render each message (with syntax highlighting)
    Message->>LogViewerLink: Render link to external log viewer
    User->>LogViewerLink: Clicks link
    LogViewerLink->>External Log Viewer: Opens file in new tab
Loading
✨ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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.

@davemarco davemarco requested a review from junhaoliao April 29, 2025 19:12
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 (5)
components/log-viewer-webui/client/src/pages/SearchPage/index.tsx (1)

13-16: Component structure looks good

Consider using dot notation instead of bracket notation for accessing the CSS module class for better readability.

-        <div className={styles["searchPageContainer"]}>
+        <div className={styles.searchPageContainer}>
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/typings.tsx (1)

16-38: File path column is missing.

The columns configuration only includes "Timestamp" and "Message" columns, but the SearchResult interface and dummy data both have a filePath field. While the file path is included within the Message component, consider whether users would expect to see and sort by file path as a separate column.

const searchResultsTableColumns: NonNullable<TableProps<SearchResult>["columns"]> = [
    {
        dataIndex: "timestamp",
        key: "timestamp",
        sorter: true,
        title: "Timestamp",
        width: 15,
    },
    {
        dataIndex: "message",
        key: "message",
        render: (_, record) => (
            <Message
                filePath={record.filePath}
                message={record.message}/>
        ),
        title: "Message",
        width: 85,
    },
+    {
+        dataIndex: "filePath",
+        key: "filePath",
+        title: "File Path",
+        width: 20,
+        sorter: true,
+    },
];

If adding this column, you'll need to adjust the width percentages to ensure they total 100.

components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/LogViewerLink.tsx (2)

12-15: Consider making log viewer URL configurable.

The hardcoded URL will need to be updated once the log viewer setup is complete. Consider making this a configurable environment variable or importing from a central configuration.

-// eslint-disable-next-line no-warning-comments
-// TODO: Fix link to connect to package log viewer when log viewer setup finished. Also pass
-// proper args to package log viewer.
-const LOG_VIEWER_URL = "https://y-scope.github.io/yscope-log-viewer/";
+import { LOG_VIEWER_URL } from "src/config/urls";

35-35: Simplify CSS class assignment.

The current implementation uses bracket notation with a fallback to an empty string, which is unnecessarily complex.

-            <LinkOutlined className={styles["linkIcon"] || ""}/>
+            <LinkOutlined className={styles.linkIcon}/>
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/index.tsx (1)

26-41: Consider implementing a dark mode variant.

The current implementation uses a light theme for syntax highlighting (intellij-light). Consider supporting dark mode for better user experience in different environments.

 import SyntaxHighlighter from "react-syntax-highlighter";
 
 import {Typography} from "antd";
+import {useTheme} from 'antd/es/theme/internal';
 
 import LogViewerLink from "./LogViewerLink";
 import {highlighterCustomStyles} from "./utils";
 
 import "highlight.js/styles/intellij-light.css";
+import "highlight.js/styles/atom-one-dark.css";
 
 
 const {Text} = Typography;
 
 interface MessageProps {
     message: string;
     filePath: string;
 }
 
 /**
  * Renders a message with syntax highlighting and a file path link.
  *
  * @param props
  * @param props.message
  * @param props.filePath
  * @return
  */
 const Message = ({message, filePath}: MessageProps) => {
+    const { theme } = useTheme();
+    const isDarkMode = theme.isDark;
     return (
         <>
             {/* Parent `Text` component allows syntax highlighter to inherit AntD fonts. */}
             <Text>
                 <SyntaxHighlighter
                     customStyle={highlighterCustomStyles}
                     language={"armasm"}
-                    useInlineStyles={false}
+                    useInlineStyles={false}
+                    className={isDarkMode ? 'hljs-dark' : 'hljs-light'}
                 >

You would also need to add CSS classes to differentiate between light and dark themes.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 329eb7f and f194823.

⛔ Files ignored due to path filters (1)
  • components/log-viewer-webui/client/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • components/log-viewer-webui/client/package.json (1 hunks)
  • components/log-viewer-webui/client/src/pages/SearchPage/SearchControls/index.module.css (0 hunks)
  • components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/LogViewerLink.tsx (1 hunks)
  • components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/index.module.css (1 hunks)
  • components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/index.tsx (1 hunks)
  • components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/utils.ts (1 hunks)
  • components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/index.tsx (1 hunks)
  • components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/typings.tsx (1 hunks)
  • components/log-viewer-webui/client/src/pages/SearchPage/index.module.css (1 hunks)
  • components/log-viewer-webui/client/src/pages/SearchPage/index.tsx (2 hunks)
💤 Files with no reviewable changes (1)
  • components/log-viewer-webui/client/src/pages/SearchPage/SearchControls/index.module.css
🧰 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>.

  • components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/LogViewerLink.tsx
  • components/log-viewer-webui/client/src/pages/SearchPage/index.tsx
  • components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/utils.ts
  • components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/index.tsx
  • components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/index.tsx
  • components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/typings.tsx
🧬 Code Graph Analysis (2)
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/index.tsx (1)
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/utils.ts (1)
  • highlighterCustomStyles (5-11)
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/index.tsx (2)
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/typings.tsx (2)
  • SearchResult (40-40)
  • searchResultsTableColumns (41-41)
components/webui/imports/ui/SearchView/SearchResults/SearchResultsTable/index.jsx (1)
  • SearchResultsTable (63-186)
🔇 Additional comments (7)
components/log-viewer-webui/client/package.json (1)

23-23: Dependencies added correctly for syntax highlighting

The added dependencies support the syntax highlighting feature mentioned in the PR objectives, with appropriate version specifications.

Also applies to: 27-27, 33-33

components/log-viewer-webui/client/src/pages/SearchPage/index.module.css (1)

1-6: Layout styles look good

The flex container with appropriate spacing and padding creates a clean vertical layout for the search page components.

components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/utils.ts (1)

1-11: Well-documented style overrides

The custom styles for the syntax highlighter are appropriately documented with clear reasoning for why they're needed instead of using CSS modules directly.

components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/index.module.css (1)

1-3: Simple and focused styling

The link icon spacing is appropriate for creating visual separation between the icon and adjacent text.

components/log-viewer-webui/client/src/pages/SearchPage/index.tsx (1)

1-1: Imports look good

The necessary CSS module and new component are properly imported.

Also applies to: 3-3

components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/index.tsx (1)

1-6: Clean import statements.

The imports look good and properly organized. I like the use of named imports for specific components from the typings module.

components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/typings.tsx (1)

1-15: SearchResult interface is well defined.

The interface properly defines the structure of search results with appropriate types.

Comment on lines +9 to +36
// eslint-disable-next-line no-warning-comments
// TODO: Replace with values from database once api implemented.
const DUMMY_RESULTS: SearchResult[] = [
{
id: 1,
timestamp: "2023-01-01 12:00:00",
message: "INFO: User login successful for user 'john.doe'.",
filePath: "/var/logs/auth.log",
},
{
id: 2,
timestamp: "2023-01-01 12:01:00",
message: "ERROR: Failed to connect to database 'logs_db'.",
filePath: "/var/logs/db.log",
},
{
id: 3,
timestamp: "2023-01-01 12:02:00",
message: "WARN: Disk space running low on volume '/var/logs'.",
filePath: "/var/logs/system.log",
},
{
id: 4,
timestamp: "2023-01-01 12:03:00",
message: "DEBUG: Processing request ID 12345.",
filePath: "/var/logs/app.log",
},
];
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Add pagination controls for future implementation.

The dummy data is well structured and provides a good representation of expected search results. While the TODO comment correctly indicates these will be replaced with database values, consider planning for server-side pagination in the component design.


🌐 Web query:

What are the best practices for implementing server-side pagination with Ant Design Table components?

💡 Result:

Best Practices for Implementing Server-Side Pagination with Ant Design Table

Implementing server-side pagination in Ant Design's Table component ensures efficiency and scalability, especially when working with large datasets. Here are the best practices supported by recent examples and the official Ant Design approach:

1. Maintain Pagination State in React

  • Use React's useState to keep track of pagination details such as current, pageSize, and total.
  • Store the loaded data and loading state in separate state variables for clarity and performance[5][8].

2. Fetch Data Based on Table Pagination Events

  • Use the Table's onChange event to trigger API calls when the user changes the page, page size, or interacts with sorting/filtering features.
  • Pass current page and page size to the backend as query parameters.
  • Update the data and total count when new data is fetched from the server[4][5][8].

3. Configure the Table's Pagination Prop Properly

  • Pass the pagination state to the Table's pagination prop:
    <Table
      columns={columns}
      dataSource={data}
      pagination={{
        current: pagination.current,
        pageSize: pagination.pageSize,
        total: pagination.total,
        showSizeChanger: true
      }}
      loading={loading}
      onChange={handleTableChange}
    />
  • Enable showSizeChanger for user control over page size options[5][8].

4. Efficient Data Fetching and Loading Feedback

  • Show a spinner or loading indicator while data is being fetched by toggling the loading prop of the Table[2][5][8].
  • Optionally, debounce or throttle API calls if pagination changes rapidly.

5. Always Update the Total Count

  • Ensure the total record count (total) is updated in your pagination state after each data fetch. This keeps the page count correct and the pagination UI in sync[5][8].

6. Handle Sorting and Filtering

  • When using server-side sorting or filtering, capture the additional parameters in onChange and pass them to your API.
  • Backend should handle sorting/filtering and return the paginated, sorted, and/or filtered data[4][10].

7. Robust Error Handling

  • Manage and display errors from API failures gracefully, making sure loading states are reset and users are informed if something goes wrong[5][7].

Example Pattern

const [data, setData] = useState([]);
const [pagination, setPagination] = useState({
  current: 1,
  pageSize: 10,
  total: 0
});
const [loading, setLoading] = useState(false);

const fetchData = async (params) => {
  setLoading(true);
  const response = await api.get('/items', {
    params: {
      page: params.pagination.current,
      size: params.pagination.pageSize
    }
  });
  setData(response.data.items);
  setPagination({
    ...params.pagination,
    total: response.data.totalCount
  });
  setLoading(false);
};

useEffect(() => {
  fetchData({ pagination });
}, []);

const handleTableChange = (newPagination, filters, sorter) => {
  fetchData({
    pagination: newPagination,
    filters,
    sorter,
  });
};

<Table
  columns={columns}
  dataSource={data}
  pagination={pagination}
  loading={loading}
  onChange={handleTableChange}
/>

[5][8]

Summary Table: Key Practices

Practice Why It Matters
State management for pagination Keeps UI and data in sync
onChange triggers data fetch Fetches only needed data per page
Show loading during fetch Improves user experience
API returns paginated, total data Ensures pagination UI is correct
Error & empty state handling Prevents UI glitches, informs users
Support for dynamic page sizes Enhances flexibility for users
Pass sorting/filtering to backend Ensures accurate results

By following these best practices, you can efficiently implement server-side pagination in Ant Design Table components, resulting in responsive UIs and scalable performance for large data sets[5][8][4].

Citations:


Plan for server-side pagination in SearchResultsTable

Once the real API is in place, extend the component to support server-side pagination by:

  • Maintaining pagination state (current, pageSize, total) alongside data and loading via useState.
  • Configuring the Ant Design <Table>’s pagination prop with your pagination state and showSizeChanger.
  • Implementing an onChange handler that:
    • Receives pagination, filters, sorter
    • Calls your API with page, size, plus any sorting/filtering params
    • Updates data, total, and resets loading
  • Toggling the Table’s loading prop during fetches for clear feedback.
  • Ensuring the API returns both paginated items and a totalCount.
  • Handling API errors gracefully (reset loading, display a message).

File to update:
• components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/index.tsx (around the DUMMY_RESULTS/TODO block)

Comment on lines +38 to +52
/**
* Renders search results in a table.
*
* @return
*/
const SearchResultsTable = () => {
return (
<Table<SearchResult>
columns={searchResultsTableColumns}
dataSource={DUMMY_RESULTS}
pagination={false}
rowKey={(record) => record.id.toString()}
virtual={true}/>
);
};
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

Enhance component flexibility with props.

The component is currently hardcoded to use dummy data. Consider enhancing it with props to make it more flexible and reusable:

-const SearchResultsTable = () => {
+interface SearchResultsTableProps {
+    dataSource?: SearchResult[];
+    loading?: boolean;
+    onSortChange?: (field: string, order: 'ascend' | 'descend' | undefined) => void;
+}
+
+const SearchResultsTable = ({
+    dataSource = DUMMY_RESULTS,
+    loading = false,
+    onSortChange,
+}: SearchResultsTableProps) => {
     return (
         <Table<SearchResult>
             columns={searchResultsTableColumns}
-            dataSource={DUMMY_RESULTS}
+            dataSource={dataSource}
+            loading={loading}
+            onChange={(pagination, filters, sorter) => {
+                if (onSortChange && !Array.isArray(sorter)) {
+                    onSortChange(sorter.field as string, sorter.order);
+                }
+            }}
             pagination={false}
             rowKey={(record) => record.id.toString()}
             virtual={true}/>
     );
 };
📝 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
/**
* Renders search results in a table.
*
* @return
*/
const SearchResultsTable = () => {
return (
<Table<SearchResult>
columns={searchResultsTableColumns}
dataSource={DUMMY_RESULTS}
pagination={false}
rowKey={(record) => record.id.toString()}
virtual={true}/>
);
};
/**
* Renders search results in a table.
*
* @return
*/
interface SearchResultsTableProps {
dataSource?: SearchResult[];
loading?: boolean;
onSortChange?: (field: string, order: 'ascend' | 'descend' | undefined) => void;
}
const SearchResultsTable = ({
dataSource = DUMMY_RESULTS,
loading = false,
onSortChange,
}: SearchResultsTableProps) => {
return (
<Table<SearchResult>
columns={searchResultsTableColumns}
dataSource={dataSource}
loading={loading}
onChange={(pagination, filters, sorter) => {
if (onSortChange && !Array.isArray(sorter)) {
onSortChange(sorter.field as string, sorter.order);
}
}}
pagination={false}
rowKey={(record) => record.id.toString()}
virtual={true}
/>
);
};

<Text>
<SyntaxHighlighter
customStyle={highlighterCustomStyles}
language={"armasm"}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider using more appropriate language for log syntax highlighting.

The current implementation uses "armasm" as the language for syntax highlighting, which seems unusual for log messages. Consider using a more appropriate language like "log", "text" or "plaintext".

-                    language={"armasm"}
+                    language={"log"}

🌐 Web query:

What's the best syntax highlighting language to use for log files in react-syntax-highlighter?

💡 Result:

React Syntax Highlighter offers a wide range of language support for syntax highlighting in React applications, but there isn't a specific language explicitly designed for log files. However, several options can be effective for highlighting log files depending on your specific log format.

Best Options for Log File Syntax Highlighting

For log files in react-syntax-highlighter, these languages work particularly well:

Plain Text
The simplest approach is to use "text" as your language option, which will render your logs in monospaced font without specific highlighting[1][7]. This works well for simple logs where you don't need complex syntax highlighting.

<SyntaxHighlighter language="text" style={solarizedlight}>
  {logFileContent}
</SyntaxHighlighter>

Shell/Bash
For command-line or terminal-style logs, the "shell" or "bash" language options provide useful highlighting that can make timestamps, errors, and command outputs more distinguishable[10]. These languages highlight typical patterns found in terminal outputs.

HTTP
If your logs contain HTTP requests and responses, the "http" language option can be particularly useful as it will highlight status codes, headers, and request methods[10].

JavaScript Console
For logs that originate from browser consoles or JavaScript applications, using "javascript" as the language can provide good highlighting for objects, errors, and various data types[5][6].

Customization Options

Regardless of which language you choose, react-syntax-highlighter offers several customization features that can enhance log file readability:

Line Numbers
Adding line numbers helps with referencing specific parts of lengthy logs[5]:

<SyntaxHighlighter 
  language="text" 
  style={solarizedlight}
  showLineNumbers>
  {logFileContent}
</SyntaxHighlighter>

Highlighting Specific Lines
You can highlight important lines (like errors) in your logs using the wrapLines and lineProps options[5]:

const lineProps = (lineNumber) => {
  let style = { display: 'block' };
  if (lineNumber === 2) { // Highlight line containing error
    style.backgroundColor = '#ffdd57';
  }
  return { style };
};

<SyntaxHighlighter
  language="text"
  style={solarizedlight}
  wrapLines
  lineProps={lineProps}>
  {logFileContent}
</SyntaxHighlighter>

Custom Styling
You can further customize the appearance using the customStyle prop to match your application's theme[1][5].

If your log files have a specific format or structure, you might need to experiment with different language options to find the one that best highlights the important parts of your logs. In some cases, you might even consider creating a custom language definition if your logs have a very specific structure that isn't well-served by the existing options.

Citations:


Switch to Plain Text Highlighting for Logs

To improve readability of log output, use the plain text highlighter instead of “armasm”. For example:

• File:
components/log-viewer-webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Message/index.tsx
Line: 33

-                    language={"armasm"}
+                    language="text"

If your logs include shell commands, HTTP messages or JavaScript console output, consider using "bash", "http" or "javascript" respectively.

📝 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
language={"armasm"}
language="text"

@junhaoliao junhaoliao requested a review from hoophalab April 30, 2025 21:29
Copy link
Contributor

@hoophalab hoophalab left a comment

Choose a reason for hiding this comment

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

Code-wise, everything looks good. The syntax highlighting works nicely!

Sorting doesn’t seem to work as expected. See the comments below.

{
dataIndex: "timestamp",
key: "timestamp",
sorter: true,
Copy link
Contributor

@hoophalab hoophalab May 1, 2025

Choose a reason for hiding this comment

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

I might be missing something, sorting doesn't seem to work. According to the docs, it looks like sorter is expected to be a function.

Copy link
Contributor Author

@davemarco davemarco May 1, 2025

Choose a reason for hiding this comment

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

The sorter will be server side, like it will need to launch a new query to the backend, so this is just a dummy sorter until database api is implemented

Copy link
Member

Choose a reason for hiding this comment

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

The sorter will be server side

It makes sense to set the sorter as true. I believe we will need to register a onChange handler on the Table to detect if any sorter changes (i.e., user requests a different sorting order on a column), right?

(I haven't run the code locally yet. Do the sorting indicators (asc / desc) change as we click the table headers?)

We can register the handler and print a log if the sorter changes, though this will be just boilerplate code until we submit the API integration PR. @davemarco I'll let you decide whether you want to add the handler in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

make sense

(I haven't run the code locally yet. Do the sorting indicators (asc / desc) change as we click the table headers?)

The indicator changes.

{message}
</SyntaxHighlighter>
</Text>
<LogViewerLink filePath={filePath}/>
Copy link
Contributor

Choose a reason for hiding this comment

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

Aesthetics: it might look cleaner to display the file link in a separate column. Users could also filter or sort based on the file name.

If horizontal space is a concern, we could consider adding buttons to show/hide columns later.

(I don't have full context of the PR, so feel push back)

Copy link
Contributor Author

@davemarco davemarco May 1, 2025

Choose a reason for hiding this comment

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

For context, this is what the old webui did. I do agree the columns are better, but I think this will be later once we setup dynamic columns for all fields in the query results(clp-s only). for now i think better/simpler to match old ui.

Copy link
Member

Choose a reason for hiding this comment

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

In the future, I believe we can add a right pop-up panel (a.k.a. a "drawer") for displaying metadata of a specific log event when selected.

For now, since we intend to make the log viewer links visible (as a feature highlight), it makes sense to leave the links directly in the table. Adding an extra column for file name display would work, but as you mention we could be leaving a lot of gap in the log viewer link cells when the message is too long - it could be a waste of space.

Therefore, for now I believe it is fine to leave the links at the bottom of the message cells.

@junhaoliao
Copy link
Member

@hoophalab can i start reviewing this, or do you want to take a further look?

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.

3 participants