wip netflow layout (#2668) #2833

Merged
mfreeman451 merged 1 commit from refs/pull/2833/head into chore/agent-analysis 2026-02-02 05:09:17 +00:00
mfreeman451 commented 2026-02-02 05:09:02 +00:00 (Migrated from github.com)
Owner

Imported from GitHub pull request.

Original GitHub pull request: #2670
Original author: @mfreeman451
Original URL: https://github.com/carverauto/serviceradar/pull/2670
Original created: 2026-02-02T05:09:02Z
Original updated: 2026-02-02T05:11:18Z
Original head: carverauto/serviceradar:staging
Original base: chore/agent-analysis
Original merged: 2026-02-02T05:09:17Z by @mfreeman451

User description

IMPORTANT: Please sign the Developer Certificate of Origin

Thank you for your contribution to ServiceRadar. Please note, when contributing, the developer must include
a DCO sign-off statement indicating the DCO acceptance in one commit message. Here
is an example DCO Signed-off-by line in a commit message:

Signed-off-by: J. Doe <j.doe@domain.com>

Describe your changes

Code checklist before requesting a review

  • I have signed the DCO?
  • The build completes without errors?
  • All tests are passing when running make test?

PR Type

Enhancement


Description

  • Consolidate NetFlow, Events, and Alerts into unified Observability page

  • Add tabbed interface for NetFlow, Events, Alerts alongside Logs, Traces, Metrics

  • Implement summary cards and data tables for each new observability entity

  • Remove standalone NetFlow page and route to LogLive.Index instead

  • Add SRQL catalog entry for NetFlow flows with filtering support


Diagram Walkthrough

flowchart LR
  A["Standalone Pages<br/>NetFlow/Events/Alerts"] -->|Consolidate| B["Unified Observability<br/>LogLive.Index"]
  B -->|Tabs| C["Logs"]
  B -->|Tabs| D["Traces"]
  B -->|Tabs| E["Metrics"]
  B -->|Tabs| F["Events"]
  B -->|Tabs| G["Alerts"]
  B -->|Tabs| H["NetFlow"]
  F -->|Summary| I["Event Severity Stats"]
  G -->|Summary| J["Alert Status Overview"]
  H -->|Summary| K["NetFlow Protocol/Version Stats"]

File Walkthrough

Relevant files
Formatting
layouts.ex
Refactor layouts and consolidate sidebar navigation           

web-ng/lib/serviceradar_web_ng_web/components/layouts.ex

  • Convert embed_templates and attr/slot declarations to function call
    syntax with parentheses
  • Remove individual sidebar links for NetFlow, Events, and Alerts
  • Consolidate navigation into single Observability link with expanded
    active state logic
  • Observability link now includes paths for /netflows, /events, /alerts
    alongside existing paths
+23/-38 
Enhancement
index.ex
Add Events, Alerts, and NetFlow tabs to Observability page

web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex

  • Add constants for Events, Alerts, and NetFlow pagination limits
  • Initialize empty lists and summaries for events, alerts, and netflows
    in mount
  • Add tab support for "events", "alerts", and "netflows" with dynamic
    limit handling
  • Implement event_summary, alert_summary, and netflow_summary components
    with severity/status breakdowns
  • Add events_table, alerts_table, and netflows_table components with
    full data display
  • Add helper functions for event/alert/netflow data extraction,
    formatting, and badge rendering
  • Add netflow_presets component with quick filter buttons for common
    NetFlow queries
  • Update observability_tabs to include Events, Alerts, and NetFlow tabs
  • Add computation functions for event, alert, and netflow summaries
  • Update panel_result_count, tab_entity, tab_limits, and
    apply_tab_assigns to handle new tabs
+1073/-56
index.ex
Remove standalone NetFlow page module                                       

web-ng/lib/serviceradar_web_ng_web/live/netflow_live/index.ex

  • Delete entire standalone NetFlow LiveView module (366 lines)
  • Functionality migrated to LogLive.Index as a tab within unified
    Observability page
+0/-366 
catalog.ex
Add NetFlow flows to SRQL catalog                                               

web-ng/lib/serviceradar_web_ng_web/srql/catalog.ex

  • Add new SRQL catalog entry for "flows" entity with NetFlow-specific
    configuration
  • Define filter fields for NetFlow queries: IP addresses, ports,
    protocol, sampler address
  • Set default time window to "last_24h" and default sort to "time:desc"
  • Enable NetFlow searches to route to /observability page
+19/-0   
Configuration changes
router.ex
Route NetFlow to unified Observability page                           

web-ng/lib/serviceradar_web_ng_web/router.ex

  • Change /netflows route from NetflowLive.Index to LogLive.Index
  • NetFlow is now accessed as a tab within the Observability page
+1/-1     

Imported from GitHub pull request. Original GitHub pull request: #2670 Original author: @mfreeman451 Original URL: https://github.com/carverauto/serviceradar/pull/2670 Original created: 2026-02-02T05:09:02Z Original updated: 2026-02-02T05:11:18Z Original head: carverauto/serviceradar:staging Original base: chore/agent-analysis Original merged: 2026-02-02T05:09:17Z by @mfreeman451 --- ### **User description** ## IMPORTANT: Please sign the Developer Certificate of Origin Thank you for your contribution to ServiceRadar. Please note, when contributing, the developer must include a [DCO sign-off statement]( https://developercertificate.org/) indicating the DCO acceptance in one commit message. Here is an example DCO Signed-off-by line in a commit message: ``` Signed-off-by: J. Doe <j.doe@domain.com> ``` ## Describe your changes ## Issue ticket number and link ## Code checklist before requesting a review - [ ] I have signed the DCO? - [ ] The build completes without errors? - [ ] All tests are passing when running make test? ___ ### **PR Type** Enhancement ___ ### **Description** - Consolidate NetFlow, Events, and Alerts into unified Observability page - Add tabbed interface for NetFlow, Events, Alerts alongside Logs, Traces, Metrics - Implement summary cards and data tables for each new observability entity - Remove standalone NetFlow page and route to LogLive.Index instead - Add SRQL catalog entry for NetFlow flows with filtering support ___ ### Diagram Walkthrough ```mermaid flowchart LR A["Standalone Pages<br/>NetFlow/Events/Alerts"] -->|Consolidate| B["Unified Observability<br/>LogLive.Index"] B -->|Tabs| C["Logs"] B -->|Tabs| D["Traces"] B -->|Tabs| E["Metrics"] B -->|Tabs| F["Events"] B -->|Tabs| G["Alerts"] B -->|Tabs| H["NetFlow"] F -->|Summary| I["Event Severity Stats"] G -->|Summary| J["Alert Status Overview"] H -->|Summary| K["NetFlow Protocol/Version Stats"] ``` <details><summary><h3>File Walkthrough</h3></summary> <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Formatting</strong></td><td><table> <tr> <td> <details> <summary><strong>layouts.ex</strong><dd><code>Refactor layouts and consolidate sidebar navigation</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> web-ng/lib/serviceradar_web_ng_web/components/layouts.ex <ul><li>Convert <code>embed_templates</code> and <code>attr</code>/<code>slot</code> declarations to function call <br>syntax with parentheses<br> <li> Remove individual sidebar links for NetFlow, Events, and Alerts<br> <li> Consolidate navigation into single Observability link with expanded <br>active state logic<br> <li> Observability link now includes paths for <code>/netflows</code>, <code>/events</code>, <code>/alerts</code> <br>alongside existing paths</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2670/files#diff-75eaced063e3e7325588594e742492bab789a979319a34f2f623f6d161cfffd2">+23/-38</a>&nbsp; </td> </tr> </table></td></tr><tr><td><strong>Enhancement</strong></td><td><table> <tr> <td> <details> <summary><strong>index.ex</strong><dd><code>Add Events, Alerts, and NetFlow tabs to Observability page</code></dd></summary> <hr> web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex <ul><li>Add constants for Events, Alerts, and NetFlow pagination limits<br> <li> Initialize empty lists and summaries for events, alerts, and netflows <br>in mount<br> <li> Add tab support for "events", "alerts", and "netflows" with dynamic <br>limit handling<br> <li> Implement <code>event_summary</code>, <code>alert_summary</code>, and <code>netflow_summary</code> components <br>with severity/status breakdowns<br> <li> Add <code>events_table</code>, <code>alerts_table</code>, and <code>netflows_table</code> components with <br>full data display<br> <li> Add helper functions for event/alert/netflow data extraction, <br>formatting, and badge rendering<br> <li> Add <code>netflow_presets</code> component with quick filter buttons for common <br>NetFlow queries<br> <li> Update <code>observability_tabs</code> to include Events, Alerts, and NetFlow tabs<br> <li> Add computation functions for event, alert, and netflow summaries<br> <li> Update <code>panel_result_count</code>, <code>tab_entity</code>, <code>tab_limits</code>, and <br><code>apply_tab_assigns</code> to handle new tabs</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2670/files#diff-5c469994d989d04955c9b8a31536ed518a182b3f46819ecee9c3c22f651a4321">+1073/-56</a></td> </tr> <tr> <td> <details> <summary><strong>index.ex</strong><dd><code>Remove standalone NetFlow page module</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> web-ng/lib/serviceradar_web_ng_web/live/netflow_live/index.ex <ul><li>Delete entire standalone NetFlow LiveView module (366 lines)<br> <li> Functionality migrated to LogLive.Index as a tab within unified <br>Observability page</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2670/files#diff-7ec566a3a20e36d101f72bb9ee19620be76b397c1d88a1edc6d9a88e8da6909e">+0/-366</a>&nbsp; </td> </tr> <tr> <td> <details> <summary><strong>catalog.ex</strong><dd><code>Add NetFlow flows to SRQL catalog</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> web-ng/lib/serviceradar_web_ng_web/srql/catalog.ex <ul><li>Add new SRQL catalog entry for "flows" entity with NetFlow-specific <br>configuration<br> <li> Define filter fields for NetFlow queries: IP addresses, ports, <br>protocol, sampler address<br> <li> Set default time window to "last_24h" and default sort to "time:desc"<br> <li> Enable NetFlow searches to route to <code>/observability</code> page</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2670/files#diff-80c07c25c17e48bf86860ec91db10256b7700a863d5371798e1893e741dc0e15">+19/-0</a>&nbsp; &nbsp; </td> </tr> </table></td></tr><tr><td><strong>Configuration changes</strong></td><td><table> <tr> <td> <details> <summary><strong>router.ex</strong><dd><code>Route NetFlow to unified Observability page</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> web-ng/lib/serviceradar_web_ng_web/router.ex <ul><li>Change <code>/netflows</code> route from <code>NetflowLive.Index</code> to <code>LogLive.Index</code><br> <li> NetFlow is now accessed as a tab within the Observability page</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2670/files#diff-df516cd33165cd85914c1ccb3ff6511d3fe688d4a66498b99807958998c5d07c">+1/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></td></tr></tbody></table> </details> ___
qodo-code-review[bot] commented 2026-02-02 05:09:45 +00:00 (Migrated from github.com)
Author
Owner

Imported GitHub PR comment.

Original author: @qodo-code-review[bot]
Original URL: https://github.com/carverauto/serviceradar/pull/2670#issuecomment-3832939119
Original created: 2026-02-02T05:09:45Z

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Nil arithmetic risk: compute_netflow_summary/1 adds bytes into :total_bytes and may crash if to_int/1 can
return nil for missing/invalid flow byte values.

Referred Code
defp compute_netflow_summary(flows) when is_list(flows) do
  Enum.reduce(
    flows,
    %{total: 0, tcp: 0, udp: 0, other: 0, total_bytes: 0, v5: 0, v9: 0, ipfix: 0},
    fn flow, acc ->
      protocol = flow |> netflow_protocol_num() |> to_int()
      bytes = flow |> netflow_bytes() |> to_int()
      flow_type = netflow_flow_type(flow)

      updated =
        case protocol do
          6 -> Map.update!(acc, :tcp, &(&1 + 1))
          17 -> Map.update!(acc, :udp, &(&1 + 1))
          _ -> Map.update!(acc, :other, &(&1 + 1))
        end

      updated =
        case flow_type do
          "NETFLOW_V5" -> Map.update!(updated, :v5, &(&1 + 1))
          "NETFLOW_V9" -> Map.update!(updated, :v9, &(&1 + 1))
          "IPFIX" -> Map.update!(updated, :ipfix, &(&1 + 1))


 ... (clipped 7 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
- Requires Further Human Verification
🏷️ - Compliance label
Imported GitHub PR comment. Original author: @qodo-code-review[bot] Original URL: https://github.com/carverauto/serviceradar/pull/2670#issuecomment-3832939119 Original created: 2026-02-02T05:09:45Z --- ## PR Compliance Guide 🔍 <!-- https://github.com/carverauto/serviceradar/commit/5aea325faeddbf8c8867fe91ef344b0086f756ea --> Below is a summary of compliance checks for this PR:<br> <table><tbody><tr><td colspan='2'><strong>Security Compliance</strong></td></tr> <tr><td>🟢</td><td><details><summary><strong>No security concerns identified</strong></summary> No security vulnerabilities detected by AI analysis. Human verification advised for critical code. </details></td></tr> <tr><td colspan='2'><strong>Ticket Compliance</strong></td></tr> <tr><td>⚪</td><td><details><summary>🎫 <strong>No ticket provided </strong></summary> - [ ] Create ticket/issue <!-- /create_ticket --create_ticket=true --> </details></td></tr> <tr><td colspan='2'><strong>Codebase Duplication Compliance</strong></td></tr> <tr><td>⚪</td><td><details><summary><strong>Codebase context is not defined </strong></summary> Follow the <a href='https://qodo-merge-docs.qodo.ai/core-abilities/rag_context_enrichment/'>guide</a> to enable codebase context checks. </details></td></tr> <tr><td colspan='2'><strong>Custom Compliance</strong></td></tr> <tr><td rowspan=5>🟢</td><td> <details><summary><strong>Generic: Comprehensive Audit Trails</strong></summary><br> **Objective:** To create a detailed and reliable record of critical system actions for security analysis <br>and compliance.<br> **Status:** Passed<br> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td> <details><summary><strong>Generic: Meaningful Naming and Self-Documenting Code</strong></summary><br> **Objective:** Ensure all identifiers clearly express their purpose and intent, making code <br>self-documenting<br> **Status:** Passed<br> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td> <details><summary><strong>Generic: Secure Error Handling</strong></summary><br> **Objective:** To prevent the leakage of sensitive system information through error messages while <br>providing sufficient detail for internal debugging.<br> **Status:** Passed<br> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td> <details><summary><strong>Generic: Secure Logging Practices</strong></summary><br> **Objective:** To ensure logs are useful for debugging and auditing without exposing sensitive <br>information like PII, PHI, or cardholder data.<br> **Status:** Passed<br> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td> <details><summary><strong>Generic: Security-First Input Validation and Data Handling</strong></summary><br> **Objective:** Ensure all data inputs are validated, sanitized, and handled securely to prevent <br>vulnerabilities<br> **Status:** Passed<br> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td rowspan=1>⚪</td> <td><details> <summary><strong>Generic: Robust Error Handling and Edge Case Management</strong></summary><br> **Objective:** Ensure comprehensive error handling that provides meaningful context and graceful <br>degradation<br> **Status:** <br><a href='https://github.com/carverauto/serviceradar/pull/2670/files#diff-5c469994d989d04955c9b8a31536ed518a182b3f46819ecee9c3c22f651a4321R2605-R2632'><strong>Nil arithmetic risk</strong></a>: <code>compute_netflow_summary/1</code> adds <code>bytes</code> into <code>:total_bytes</code> and may crash if <code>to_int/1</code> can <br>return <code>nil</code> for missing/invalid flow byte values.<br> <details open><summary>Referred Code</summary> ```elixir defp compute_netflow_summary(flows) when is_list(flows) do Enum.reduce( flows, %{total: 0, tcp: 0, udp: 0, other: 0, total_bytes: 0, v5: 0, v9: 0, ipfix: 0}, fn flow, acc -> protocol = flow |> netflow_protocol_num() |> to_int() bytes = flow |> netflow_bytes() |> to_int() flow_type = netflow_flow_type(flow) updated = case protocol do 6 -> Map.update!(acc, :tcp, &(&1 + 1)) 17 -> Map.update!(acc, :udp, &(&1 + 1)) _ -> Map.update!(acc, :other, &(&1 + 1)) end updated = case flow_type do "NETFLOW_V5" -> Map.update!(updated, :v5, &(&1 + 1)) "NETFLOW_V9" -> Map.update!(updated, :v9, &(&1 + 1)) "IPFIX" -> Map.update!(updated, :ipfix, &(&1 + 1)) ... (clipped 7 lines) ``` </details> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td align="center" colspan="2"> <!-- placeholder --> <!-- /compliance --update_compliance=true --> </td></tr></tbody></table> <details><summary>Compliance status legend</summary> 🟢 - Fully Compliant<br> 🟡 - Partial Compliant<br> 🔴 - Not Compliant<br> ⚪ - Requires Further Human Verification<br> 🏷️ - Compliance label<br> </details>
qodo-code-review[bot] commented 2026-02-02 05:11:18 +00:00 (Migrated from github.com)
Author
Owner

Imported GitHub PR comment.

Original author: @qodo-code-review[bot]
Original URL: https://github.com/carverauto/serviceradar/pull/2670#issuecomment-3832942506
Original created: 2026-02-02T05:11:18Z

PR Code Suggestions

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Refactor the monolithic LiveView into components

The LogLive.Index module has become a large, monolithic LiveView by adding logic
for Events, Alerts, and NetFlows. This should be refactored by moving the logic
and rendering for each tab into its own dedicated LiveComponent.

Examples:

web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex [1-3219]
defmodule ServiceRadarWebNGWeb.LogLive.Index do
  use ServiceRadarWebNGWeb, :live_view

  import Ecto.Query
  import ServiceRadarWebNGWeb.UIComponents

  alias Phoenix.LiveView.JS
  alias ServiceRadarWebNG.Repo
  alias ServiceRadarWebNGWeb.SRQL.Page, as: SRQLPage
  alias ServiceRadarWebNGWeb.Stats

 ... (clipped 3209 lines)

Solution Walkthrough:

Before:

```elixir
# web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex

defmodule ServiceRadarWebNGWeb.LogLive.Index do
  use ServiceRadarWebNGWeb, :live_view

  def render(assigns) do
    ~H"""
    ...
    <.observability_tabs active={@active_tab} />

    <.log_summary :if={@active_tab == "logs"} ... />
    <.event_summary :if={@active_tab == "events"} ... />
    <.alert_summary :if={@active_tab == "alerts"} ... />
    <.netflow_summary :if={@active_tab == "netflows"} ... />
    ...
    <.logs_table :if={@active_tab == "logs"} ... />
    <.events_table :if={@active_tab == "events"} ... />
    <.alerts_table :if={@active_tab == "alerts"} ... />
    <.netflows_table :if={@active_tab == "netflows"} ... />
    ...
    """
  end

  # ... (many functions for all tabs in one file)
  defp events_table(assigns), do: ...
  defp alerts_table(assigns), do: ...
  defp compute_event_summary(events), do: ...
end



#### After:
```elixir
```elixir
# web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex
defmodule ServiceRadarWebNGWeb.LogLive.Index do
  use ServiceRadarWebNGWeb, :live_view

  def render(assigns) do
    ~H"""
    ...
    <.observability_tabs active={@active_tab} />

    <.live_component
      module={tab_component_module(@active_tab)}
      id={@active_tab}
      data={assigns[String.to_atom(@active_tab)]}
      ...
    />
    ...
    """
  end
end

# web-ng/lib/serviceradar_web_ng_web/live/log_live/events_component.ex
defmodule ServiceRadarWebNGWeb.LogLive.EventsComponent do
  use ServiceRadarWebNGWeb, :live_component

  def render(assigns) do
    ~H"""
    <.event_summary summary={@summary} />
    <.events_table events={@events} />
    """
  end
  # ... component-specific logic
end




<details><summary>Suggestion importance[1-10]: 9</summary>

__

Why: The suggestion correctly identifies that the PR creates a monolithic LiveView in `LogLive.Index`, and proposing to use LiveComponents is a valid and significant architectural improvement for modularity and maintainability.


</details></details></td><td align=center>High

</td></tr><tr><td rowspan=4>General</td>
<td>



<details><summary>Initialize limit in mount</summary>

___

**Initialize the <code>:limit</code> assign in the <code>mount/3</code> function to prevent a <code>nil</code> error <br>during the initial render of the LiveView. The templates for filters and presets <br>depend on <code>@limit</code> being set.**

[web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex [25-44]](https://github.com/carverauto/serviceradar/pull/2670/files#diff-5c469994d989d04955c9b8a31536ed518a182b3f46819ecee9c3c22f651a4321R25-R44)

```diff
 def mount(_params, _session, socket) do
   {:ok,
    socket
    |> assign(:page_title, "Observability")
    |> assign(:active_tab, "logs")
+   |> assign(:limit, @default_limit)
    |> assign(:logs, [])
    |> assign(:traces, [])
    |> assign(:metrics, [])
    |> assign(:events, [])
    |> assign(:alerts, [])
    |> assign(:netflows, [])
    |> assign(:sparklines, %{})
    |> assign(:summary, %{total: 0, fatal: 0, error: 0, warning: 0, info: 0, debug: 0})
    |> assign(:event_summary, empty_event_summary())
    |> assign(:alert_summary, empty_alert_summary())
    |> assign(:netflow_summary, empty_netflow_summary())
    |> assign(:trace_stats, %{total: 0, error_traces: 0, slow_traces: 0})
    |> assign(:trace_latency, %{avg_duration_ms: 0.0, p95_duration_ms: 0.0, sample_size: 0})
   }
 end

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 9

__

Why: This suggestion correctly identifies a critical bug that would cause a runtime error on the initial render of the LiveView. Initializing @limit in mount/3 is the correct fix to prevent this error.

High
Simplify nested case statement logic

Simplify the nested case statement in the netflow_protocol_badge/1 function to
improve readability and remove redundant logic. The current implementation
contains a fallback that is unlikely to be executed as intended.

web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex [1641-1675]

 defp netflow_protocol_badge(assigns) do
-  protocol = assigns.protocol
+  protocol_num = to_int(assigns.protocol)
   name = assigns.name
-  protocol_num = to_int(protocol)
 
   {label, variant} =
     case protocol_num do
       6 ->
         {"TCP", "success"}
-
       17 ->
         {"UDP", "info"}
-
       1 ->
         {"ICMP", "ghost"}
-
       _ ->
         case name do
           value when is_binary(value) and value != "" ->
             {String.upcase(value), "ghost"}
-
           _ ->
-            case protocol do
-              value when is_binary(value) and value != "" -> {value, "ghost"}
-              _ -> {"Unknown", "ghost"}
-            end
+            {"Unknown", "ghost"}
         end
     end
 
   assigns = assign(assigns, label: label, variant: variant)
 
   ~H"""
   <.ui_badge variant={@variant}>{@label}</.ui_badge>
   """
 end
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies a convoluted and potentially buggy nested case statement. The proposed simplification improves code readability and removes redundant logic, making the function's behavior clearer and more robust.

Low
Refactor source lookup using Enum

Refactor the event_source/1 function to use Enum.find_value/3 instead of a chain
of || operators. This will make the source lookup logic more concise, readable,
and easier to maintain.

web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex [1398-1412]

 defp event_source(event) do
+  keys = ["host", "source", "uid", "device_id", "subject"]
+
   source =
-    Map.get(event, "host") ||
-      Map.get(event, "source") ||
-      Map.get(event, "uid") ||
-      Map.get(event, "device_id") ||
-      Map.get(event, "subject")
+    Enum.find_value(keys, fn key ->
+      case Map.get(event, key) do
+        nil -> nil
+        "" -> nil
+        value -> value
+      end
+    end)
 
   case source do
     nil -> "—"
-    "" -> "—"
     v when is_binary(v) -> v
     v -> to_string(v)
   end
 end
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion proposes a valid refactoring that improves code readability and maintainability by replacing a chain of || operators with Enum.find_value/3. This is a good practice, especially as the list of keys to check might grow.

Low
Refactor message lookup using Enum

Refactor the event_message/1 function to use Enum.find_value/3 instead of a
chain of || operators. This will make the message lookup logic more concise,
readable, and easier to maintain.

web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex [1414-1427]

 defp event_message(event) do
+  keys = ["short_message", "message", "subject", "description"]
+
   message =
-    Map.get(event, "short_message") ||
-      Map.get(event, "message") ||
-      Map.get(event, "subject") ||
-      Map.get(event, "description")
+    Enum.find_value(keys, fn key ->
+      case Map.get(event, key) do
+        nil -> nil
+        "" -> nil
+        value -> value
+      end
+    end)
 
   case message do
     nil -> "—"
-    "" -> "—"
     v when is_binary(v) -> String.slice(v, 0, 200)
     v -> v |> to_string() |> String.slice(0, 200)
   end
 end
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion proposes a valid refactoring that improves code readability and maintainability by replacing a chain of || operators with Enum.find_value/3. This is a good practice, especially as the list of keys to check might grow.

Low
  • More
Imported GitHub PR comment. Original author: @qodo-code-review[bot] Original URL: https://github.com/carverauto/serviceradar/pull/2670#issuecomment-3832942506 Original created: 2026-02-02T05:11:18Z --- ## PR Code Suggestions ✨ <!-- 5aea325 --> Explore these optional code suggestions: <table><thead><tr><td><strong>Category</strong></td><td align=left><strong>Suggestion&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </strong></td><td align=center><strong>Impact</strong></td></tr><tbody><tr><td rowspan=1>High-level</td> <td> <details><summary>Refactor the monolithic LiveView into components</summary> ___ **The <code>LogLive.Index</code> module has become a large, monolithic LiveView by adding logic <br>for Events, Alerts, and NetFlows. This should be refactored by moving the logic <br>and rendering for each tab into its own dedicated LiveComponent.** ### Examples: <details> <summary> <a href="https://github.com/carverauto/serviceradar/pull/2670/files#diff-5c469994d989d04955c9b8a31536ed518a182b3f46819ecee9c3c22f651a4321R1-R3219">web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex [1-3219]</a> </summary> ```elixir defmodule ServiceRadarWebNGWeb.LogLive.Index do use ServiceRadarWebNGWeb, :live_view import Ecto.Query import ServiceRadarWebNGWeb.UIComponents alias Phoenix.LiveView.JS alias ServiceRadarWebNG.Repo alias ServiceRadarWebNGWeb.SRQL.Page, as: SRQLPage alias ServiceRadarWebNGWeb.Stats ... (clipped 3209 lines) ``` </details> ### Solution Walkthrough: #### Before: ```elixir ```elixir # web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex defmodule ServiceRadarWebNGWeb.LogLive.Index do use ServiceRadarWebNGWeb, :live_view def render(assigns) do ~H""" ... <.observability_tabs active={@active_tab} /> <.log_summary :if={@active_tab == "logs"} ... /> <.event_summary :if={@active_tab == "events"} ... /> <.alert_summary :if={@active_tab == "alerts"} ... /> <.netflow_summary :if={@active_tab == "netflows"} ... /> ... <.logs_table :if={@active_tab == "logs"} ... /> <.events_table :if={@active_tab == "events"} ... /> <.alerts_table :if={@active_tab == "alerts"} ... /> <.netflows_table :if={@active_tab == "netflows"} ... /> ... """ end # ... (many functions for all tabs in one file) defp events_table(assigns), do: ... defp alerts_table(assigns), do: ... defp compute_event_summary(events), do: ... end ``` ``` #### After: ```elixir ```elixir # web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex defmodule ServiceRadarWebNGWeb.LogLive.Index do use ServiceRadarWebNGWeb, :live_view def render(assigns) do ~H""" ... <.observability_tabs active={@active_tab} /> <.live_component module={tab_component_module(@active_tab)} id={@active_tab} data={assigns[String.to_atom(@active_tab)]} ... /> ... """ end end # web-ng/lib/serviceradar_web_ng_web/live/log_live/events_component.ex defmodule ServiceRadarWebNGWeb.LogLive.EventsComponent do use ServiceRadarWebNGWeb, :live_component def render(assigns) do ~H""" <.event_summary summary={@summary} /> <.events_table events={@events} /> """ end # ... component-specific logic end ``` ``` <details><summary>Suggestion importance[1-10]: 9</summary> __ Why: The suggestion correctly identifies that the PR creates a monolithic LiveView in `LogLive.Index`, and proposing to use LiveComponents is a valid and significant architectural improvement for modularity and maintainability. </details></details></td><td align=center>High </td></tr><tr><td rowspan=4>General</td> <td> <details><summary>Initialize limit in mount</summary> ___ **Initialize the <code>:limit</code> assign in the <code>mount/3</code> function to prevent a <code>nil</code> error <br>during the initial render of the LiveView. The templates for filters and presets <br>depend on <code>@limit</code> being set.** [web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex [25-44]](https://github.com/carverauto/serviceradar/pull/2670/files#diff-5c469994d989d04955c9b8a31536ed518a182b3f46819ecee9c3c22f651a4321R25-R44) ```diff def mount(_params, _session, socket) do {:ok, socket |> assign(:page_title, "Observability") |> assign(:active_tab, "logs") + |> assign(:limit, @default_limit) |> assign(:logs, []) |> assign(:traces, []) |> assign(:metrics, []) |> assign(:events, []) |> assign(:alerts, []) |> assign(:netflows, []) |> assign(:sparklines, %{}) |> assign(:summary, %{total: 0, fatal: 0, error: 0, warning: 0, info: 0, debug: 0}) |> assign(:event_summary, empty_event_summary()) |> assign(:alert_summary, empty_alert_summary()) |> assign(:netflow_summary, empty_netflow_summary()) |> assign(:trace_stats, %{total: 0, error_traces: 0, slow_traces: 0}) |> assign(:trace_latency, %{avg_duration_ms: 0.0, p95_duration_ms: 0.0, sample_size: 0}) } end ``` `[To ensure code accuracy, apply this suggestion manually]` <details><summary>Suggestion importance[1-10]: 9</summary> __ Why: This suggestion correctly identifies a critical bug that would cause a runtime error on the initial render of the LiveView. Initializing `@limit` in `mount/3` is the correct fix to prevent this error. </details></details></td><td align=center>High </td></tr><tr><td> <details><summary>Simplify nested case statement logic</summary> ___ **Simplify the nested <code>case</code> statement in the <code>netflow_protocol_badge/1</code> function to <br>improve readability and remove redundant logic. The current implementation <br>contains a fallback that is unlikely to be executed as intended.** [web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex [1641-1675]](https://github.com/carverauto/serviceradar/pull/2670/files#diff-5c469994d989d04955c9b8a31536ed518a182b3f46819ecee9c3c22f651a4321R1641-R1675) ```diff defp netflow_protocol_badge(assigns) do - protocol = assigns.protocol + protocol_num = to_int(assigns.protocol) name = assigns.name - protocol_num = to_int(protocol) {label, variant} = case protocol_num do 6 -> {"TCP", "success"} - 17 -> {"UDP", "info"} - 1 -> {"ICMP", "ghost"} - _ -> case name do value when is_binary(value) and value != "" -> {String.upcase(value), "ghost"} - _ -> - case protocol do - value when is_binary(value) and value != "" -> {value, "ghost"} - _ -> {"Unknown", "ghost"} - end + {"Unknown", "ghost"} end end assigns = assign(assigns, label: label, variant: variant) ~H""" <.ui_badge variant={@variant}>{@label}</.ui_badge> """ end ``` - [ ] **Apply / Chat** <!-- /improve --apply_suggestion=2 --> <details><summary>Suggestion importance[1-10]: 6</summary> __ Why: The suggestion correctly identifies a convoluted and potentially buggy nested `case` statement. The proposed simplification improves code readability and removes redundant logic, making the function's behavior clearer and more robust. </details></details></td><td align=center>Low </td></tr><tr><td> <details><summary>Refactor source lookup using Enum</summary> ___ **Refactor the <code>event_source/1</code> function to use <code>Enum.find_value/3</code> instead of a chain <br>of <code>||</code> operators. This will make the source lookup logic more concise, readable, <br>and easier to maintain.** [web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex [1398-1412]](https://github.com/carverauto/serviceradar/pull/2670/files#diff-5c469994d989d04955c9b8a31536ed518a182b3f46819ecee9c3c22f651a4321R1398-R1412) ```diff defp event_source(event) do + keys = ["host", "source", "uid", "device_id", "subject"] + source = - Map.get(event, "host") || - Map.get(event, "source") || - Map.get(event, "uid") || - Map.get(event, "device_id") || - Map.get(event, "subject") + Enum.find_value(keys, fn key -> + case Map.get(event, key) do + nil -> nil + "" -> nil + value -> value + end + end) case source do nil -> "—" - "" -> "—" v when is_binary(v) -> v v -> to_string(v) end end ``` - [ ] **Apply / Chat** <!-- /improve --apply_suggestion=3 --> <details><summary>Suggestion importance[1-10]: 5</summary> __ Why: The suggestion proposes a valid refactoring that improves code readability and maintainability by replacing a chain of `||` operators with `Enum.find_value/3`. This is a good practice, especially as the list of keys to check might grow. </details></details></td><td align=center>Low </td></tr><tr><td> <details><summary>Refactor message lookup using Enum</summary> ___ **Refactor the <code>event_message/1</code> function to use <code>Enum.find_value/3</code> instead of a <br>chain of <code>||</code> operators. This will make the message lookup logic more concise, <br>readable, and easier to maintain.** [web-ng/lib/serviceradar_web_ng_web/live/log_live/index.ex [1414-1427]](https://github.com/carverauto/serviceradar/pull/2670/files#diff-5c469994d989d04955c9b8a31536ed518a182b3f46819ecee9c3c22f651a4321R1414-R1427) ```diff defp event_message(event) do + keys = ["short_message", "message", "subject", "description"] + message = - Map.get(event, "short_message") || - Map.get(event, "message") || - Map.get(event, "subject") || - Map.get(event, "description") + Enum.find_value(keys, fn key -> + case Map.get(event, key) do + nil -> nil + "" -> nil + value -> value + end + end) case message do nil -> "—" - "" -> "—" v when is_binary(v) -> String.slice(v, 0, 200) v -> v |> to_string() |> String.slice(0, 200) end end ``` - [ ] **Apply / Chat** <!-- /improve --apply_suggestion=4 --> <details><summary>Suggestion importance[1-10]: 5</summary> __ Why: The suggestion proposes a valid refactoring that improves code readability and maintainability by replacing a chain of `||` operators with `Enum.find_value/3`. This is a good practice, especially as the list of keys to check might grow. </details></details></td><td align=center>Low </td></tr> <tr><td align="center" colspan="2"> - [ ] More <!-- /improve --more_suggestions=true --> </td><td></td></tr></tbody></table>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
carverauto/serviceradar!2833
No description provided.