Skip to content

normalise timezone-aware log filter comparisons - #33

Open
HrachShah wants to merge 15 commits into
mainfrom
patch/normalise-aware-filter-comparisons
Open

normalise timezone-aware log filter comparisons#33
HrachShah wants to merge 15 commits into
mainfrom
patch/normalise-aware-filter-comparisons

Conversation

@HrachShah

@HrachShah HrachShah commented Aug 3, 2026

Copy link
Copy Markdown
Owner

The direct filter_lines helper compared timezone-aware parsed timestamps with naive filter boundaries, raising TypeError and dropping matching log records. The CLI path already normalises these comparisons.

This brings the helper into line with the CLI for both aware timestamps versus naive bounds and the inverse case, with regression coverage.

Verification: PYTHONPATH=src python -m pytest -q tests/test_utils.py -o addopts="" --disable-warnings; PYTHONPATH=src python -m compileall -q src; git diff --check.

Summary by Sourcery

Normalize timestamp timezone handling in log filtering and JSON parsing, and tighten JSON log record validation with additional edge-case coverage.

New Features:

  • Support parsing timestamps with space-separated timezone offsets in utility timestamp parser.

Bug Fixes:

  • Prevent TypeError by aligning timezone awareness between parsed log timestamps and start/end time boundaries in both CLI and filter_lines helper.
  • Ensure JSON log parser ignores non-object or empty JSON records and skips invalid or out-of-range numeric timestamps without failing.
  • Make JSON timestamp extraction fall back to later timestamp fields when earlier ones are invalid.

Enhancements:

  • Treat numeric JSON timestamps as UTC-aware datetimes and add simple validation for JSON records before parsing.
  • Improve error pattern normalization to recognize UUIDs with uppercase hex digits and replace hex values before generic numeric placeholders.

Tests:

  • Add regression tests for timezone-aware versus naive timestamp comparisons in filter_lines and CLI analyze, including use of JSON timestamps.
  • Add tests verifying JSON parser behavior for non-object records, invalid numeric timestamps, and multiple timestamp fields.
  • Add a test ensuring hex values are normalized as a single placeholder in error patterns.

Summary by CodeRabbit

  • Bug Fixes
    • Improved log filtering across timestamps with and without timezone information.
    • Rejected invalid ranges where the start time is later than the end time.
    • Added support for fractional-second and timezone-offset timestamps in syslog entries.
    • Corrected handling of Unix timestamps, including millisecond and invalid values.
    • Prevented malformed JSON, arrays, primitives, and empty objects from being treated as valid records.
    • Ensured valid fallback timestamps are used when earlier values cannot be parsed.
    • Enhanced hexadecimal and UUID error-pattern normalization.
    • Ensured only successfully parsed entries appear in filtered output.

@sourcery-ai

sourcery-ai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Reviewer's Guide

Normalize timestamp comparisons across CLI and utility helpers to handle timezone-aware and naive datetimes safely, tighten JSON log parsing and timestamp extraction, and improve error pattern normalization and regression coverage.

Sequence diagram for timezone-normalized log filtering

sequenceDiagram
    actor Caller
    participant filter_lines
    participant parse_timestamp
    participant _timestamp_before
    participant _timestamp_after
    participant _align_timestamp_timezone

    Caller->>filter_lines: filter_lines(lines, start_time, end_time)
    loop for each line
        filter_lines->>parse_timestamp: parse_timestamp(line)
        parse_timestamp-->>filter_lines: timestamp
        alt start_time provided
            filter_lines->>_timestamp_before: _timestamp_before(timestamp, start_time)
            _timestamp_before->>_align_timestamp_timezone: _align_timestamp_timezone(timestamp, start_time)
            _align_timestamp_timezone-->>_timestamp_before: timestamp, start_time
            _timestamp_before-->>filter_lines: bool
            alt timestamp before start_time
                filter_lines-->>Caller: skip line
            end
        end
        alt end_time provided
            filter_lines->>_timestamp_after: _timestamp_after(timestamp, end_time)
            _timestamp_after->>_align_timestamp_timezone: _align_timestamp_timezone(timestamp, end_time)
            _align_timestamp_timezone-->>_timestamp_after: timestamp, end_time
            _timestamp_after-->>filter_lines: bool
            alt timestamp after end_time
                filter_lines-->>Caller: skip line
            end
        end
        filter_lines-->>Caller: yield line_num, line, timestamp, level
    end
Loading

File-Level Changes

Change Details Files
Normalize timestamp comparisons so timezone-aware and naive datetimes can be compared without TypeError in both CLI parsing and filter_lines helper.
  • Introduce shared helpers to align timezone info between parsed timestamps and filter boundaries before comparison.
  • Update CLI file parsing to use parser.parse first, then fall back to parse_timestamp and apply timezone-aware before/after helpers when honoring start_time and end_time filters.
  • Update filter_lines to use timezone-aligning helpers when applying start_time and end_time filters instead of direct datetime comparisons.
src/log_analyzer_cli/cli.py
src/log_analyzer_cli/utils.py
Expand timestamp string parsing and add regression tests for timezone normalization and timestamp source selection.
  • Allow parse_timestamp to handle timestamps with a space before timezone offsets.
  • Add tests ensuring filter_lines correctly handles aware timestamps with naive bounds and naive timestamps with aware bounds.
  • Add test confirming the CLI uses JSON record timestamps for time filtering and reports expected parsed_entries and start values.
src/log_analyzer_cli/utils.py
tests/test_utils.py
tests/test_cli.py
Harden JSON log parsing to accept only non-empty objects, handle numeric timestamps as UTC with overflow protection, and prefer the first valid timestamp field.
  • Tighten can_parse to require that JSON lines decode to non-empty dicts instead of any JSON value.
  • Ensure parse returns None for non-dict or empty dict JSON values.
  • Make numeric timestamps produce timezone-aware UTC datetimes and ignore out-of-range values that raise conversion errors.
  • Ensure string timestamps are parsed safely and that later timestamp fields are used when earlier ones are invalid.
  • Add tests covering rejection of non-object JSON records, ignoring out-of-range numeric timestamps, and using a later valid timestamp field when the first is invalid.
src/log_analyzer_cli/parsers/json_log.py
tests/test_parsers.py
Improve error pattern normalization so UUID and hex value replacement is robust and hex placeholders are preserved before number normalization.
  • Update UUID normalization regex to handle uppercase hex characters in IDs.
  • Reorder normalization steps to replace hex values before standalone numbers so hex sequences are not broken into separate placeholders.
  • Add test verifying that hex values are normalized to a single placeholder and not split by numeric normalization.
src/log_analyzer_cli/utils.py
tests/test_utils.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change adds timezone-aware timestamp alignment, improves JSON timestamp extraction and record validation, updates CLI filtering to use parsed timestamps, validates time ranges, fixes per-entry metadata defaults, and adds regression tests.

Changes

Timestamp-aware log filtering

Layer / File(s) Summary
Timestamp utilities and normalization
src/log_analyzer_cli/utils.py, src/log_analyzer_cli/parsers/syslog.py, tests/test_utils.py, tests/test_parsers.py
Timestamp parsing and filtering support mixed naive and timezone-aware values. Syslog parsing accepts fractional seconds and timezone offsets. Error-pattern normalization handles uppercase UUIDs and hexadecimal values.
JSON record and timestamp parsing
src/log_analyzer_cli/parsers/json_log.py, src/log_analyzer_cli/parsers/base.py, tests/test_parsers.py
JSON parsing accepts only non-empty objects. Timestamp extraction skips invalid candidates and supports valid numeric and string fields. ParsedEntry.metadata uses an independent default dictionary per instance.
CLI parsing and time filtering
src/log_analyzer_cli/cli.py, tests/test_cli.py
The CLI rejects reversed time ranges, filters successfully parsed entries by parsed timestamps, and applies timezone-aligned start and end boundaries.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Input as JSONL input
  participant JSONParser as JSON parser
  participant CLI as CLI analyzer
  participant TimeHelpers as timezone comparison helpers
  Input->>JSONParser: parse log line
  JSONParser-->>CLI: parsed entry with timestamp
  CLI->>TimeHelpers: compare timestamp with boundaries
  TimeHelpers-->>CLI: include or exclude entry
  CLI-->>Input: JSON analysis output
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change to timezone-aware log filter comparisons.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch patch/normalise-aware-filter-comparisons

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • The _align_timestamp_timezone / _timestamp_before / _timestamp_after helpers are duplicated in both cli.py and utils.py; consider centralizing them in a shared module to avoid divergence and keep timezone handling consistent.
  • The timezone alignment currently uses replace(tzinfo=...) without converting between zones; if logs and filters may be in different timezones, consider normalizing to a common timezone (e.g., UTC) with astimezone to avoid silent offset errors.
  • JSONLogParser now calls json.loads in both can_parse and parse, and can_parse rejects empty objects; you might want to either cache the parsed data between the two or relax can_parse to avoid redundant parsing and unexpected rejection of valid-but-empty records if that is acceptable input.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `_align_timestamp_timezone` / `_timestamp_before` / `_timestamp_after` helpers are duplicated in both `cli.py` and `utils.py`; consider centralizing them in a shared module to avoid divergence and keep timezone handling consistent.
- The timezone alignment currently uses `replace(tzinfo=...)` without converting between zones; if logs and filters may be in different timezones, consider normalizing to a common timezone (e.g., UTC) with `astimezone` to avoid silent offset errors.
- JSONLogParser now calls `json.loads` in both `can_parse` and `parse`, and `can_parse` rejects empty objects; you might want to either cache the parsed data between the two or relax `can_parse` to avoid redundant parsing and unexpected rejection of valid-but-empty records if that is acceptable input.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

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

Inline comments:
In `@src/log_analyzer_cli/cli.py`:
- Around line 186-201: Move the from datetime import datetime statement from
inside analyze to the module-level imports in cli.py, so the annotations and
helper functions _align_timestamp_timezone, _timestamp_before, and
_timestamp_after resolve datetime at module scope.

In `@src/log_analyzer_cli/parsers/json_log.py`:
- Around line 82-92: Update the numeric timestamp conversion in the JSON log
parser to use an inclusive millisecond threshold, so exactly 1e12 is divided by
1000 before calling datetime.fromtimestamp. Add a regression test covering the
boundary value 1_000_000_000_000 and verifying it produces the expected UTC
datetime.

In `@tests/test_utils.py`:
- Line 11: Fix the Flake8 formatting violations in the tests/test_utils.py
fixture: split the long lines assignment around lines 11 and 30–33 into
compliant formatting, and remove the extra blank line before line 33. Preserve
the existing fixture values and behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7128c2a1-585d-4be7-8277-26393311b383

📥 Commits

Reviewing files that changed from the base of the PR and between f9b40e7 and de0d81b.

📒 Files selected for processing (6)
  • src/log_analyzer_cli/cli.py
  • src/log_analyzer_cli/parsers/json_log.py
  • src/log_analyzer_cli/utils.py
  • tests/test_cli.py
  • tests/test_parsers.py
  • tests/test_utils.py

Comment on lines +186 to +201
def _align_timestamp_timezone(timestamp: datetime, boundary: datetime) -> tuple[datetime, datetime]:
if timestamp.tzinfo is None and boundary.tzinfo is not None:
timestamp = timestamp.replace(tzinfo=boundary.tzinfo)
elif timestamp.tzinfo is not None and boundary.tzinfo is None:
boundary = boundary.replace(tzinfo=timestamp.tzinfo)
return timestamp, boundary


def _timestamp_before(timestamp: datetime, boundary: datetime) -> bool:
timestamp, boundary = _align_timestamp_timezone(timestamp, boundary)
return timestamp < boundary


def _timestamp_after(timestamp: datetime, boundary: datetime) -> bool:
timestamp, boundary = _align_timestamp_timezone(timestamp, boundary)
return timestamp > boundary

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 3 \
  'from datetime import datetime|def _align_timestamp_timezone|def _timestamp_before|def _timestamp_after' \
  src/log_analyzer_cli/cli.py

Repository: HrachShah/log-analyzer-cli

Length of output: 1178


🏁 Script executed:

#!/bin/bash
set -euo pipefail

if command -v ruff >/dev/null 2>&1; then
  ruff check src/log_analyzer_cli/cli.py --select F821
else
  python3 - <<'PY'
from pathlib import Path
text = Path("src/log_analyzer_cli/cli.py").read_text()
print("Ruff not available; inspecting imports")
print([line.strip() for line in text.splitlines() if "datetime" in line])
PY
fi

Repository: HrachShah/log-analyzer-cli

Length of output: 5161


Import datetime at module scope.

datetime is used by annotations at module scope, but it is only imported inside analyze. Move from datetime import datetime to the module imports to clear the undefined-name check.

🧰 Tools
🪛 Ruff (0.16.0)

[error] 186-186: Undefined name datetime

(F821)


[error] 186-186: Undefined name datetime

(F821)


[error] 186-186: Undefined name datetime

(F821)


[error] 186-186: Undefined name datetime

(F821)


[error] 194-194: Undefined name datetime

(F821)


[error] 194-194: Undefined name datetime

(F821)


[error] 199-199: Undefined name datetime

(F821)


[error] 199-199: Undefined name datetime

(F821)

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

In `@src/log_analyzer_cli/cli.py` around lines 186 - 201, Move the from datetime
import datetime statement from inside analyze to the module-level imports in
cli.py, so the annotations and helper functions _align_timestamp_timezone,
_timestamp_before, and _timestamp_after resolve datetime at module scope.

Source: Linters/SAST tools

Comment on lines +82 to +92
if isinstance(value, (int, float)) and not isinstance(value, bool):
try:
if value > 1e12:
return datetime.fromtimestamp(value / 1000, tz=timezone.utc)
return datetime.fromtimestamp(value, tz=timezone.utc)
except (OverflowError, OSError, ValueError):
continue
if isinstance(value, str):
return self._parse_timestamp_string(value)
parsed = self._parse_timestamp_string(value)
if parsed is not None:
return parsed

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Handle the millisecond threshold inclusively.

A timestamp value of 1_000_000_000_000 is a valid millisecond epoch value. The strict comparison treats it as seconds, and datetime.fromtimestamp then rejects it. Use >= and add a boundary regression test.

Proposed fix
-                        if value > 1e12:
+                        if value >= 1e12:
📝 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
if isinstance(value, (int, float)) and not isinstance(value, bool):
try:
if value > 1e12:
return datetime.fromtimestamp(value / 1000, tz=timezone.utc)
return datetime.fromtimestamp(value, tz=timezone.utc)
except (OverflowError, OSError, ValueError):
continue
if isinstance(value, str):
return self._parse_timestamp_string(value)
parsed = self._parse_timestamp_string(value)
if parsed is not None:
return parsed
if isinstance(value, (int, float)) and not isinstance(value, bool):
try:
if value >= 1e12:
return datetime.fromtimestamp(value / 1000, tz=timezone.utc)
return datetime.fromtimestamp(value, tz=timezone.utc)
except (OverflowError, OSError, ValueError):
continue
if isinstance(value, str):
parsed = self._parse_timestamp_string(value)
if parsed is not None:
return parsed
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/log_analyzer_cli/parsers/json_log.py` around lines 82 - 92, Update the
numeric timestamp conversion in the JSON log parser to use an inclusive
millisecond threshold, so exactly 1e12 is divided by 1000 before calling
datetime.fromtimestamp. Add a regression test covering the boundary value
1_000_000_000_000 and verifying it produces the expected UTC datetime.

Comment thread tests/test_utils.py


def test_filter_lines_compares_aware_timestamp_with_naive_bounds():
lines = iter(["2025-03-20T09:00:00+00:00 INFO early\n", "2025-03-20T11:00:00+00:00 INFO late\n"])

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Fix the Flake8 violations.

Split the lines fixture at Line 11. Remove one excess blank line before Line 33. The current file fails CI.

Proposed fix
-    lines = iter(["2025-03-20T09:00:00+00:00 INFO early\n", "2025-03-20T11:00:00+00:00 INFO late\n"])
+    lines = iter(
+        [
+            "2025-03-20T09:00:00+00:00 INFO early\n",
+            "2025-03-20T11:00:00+00:00 INFO late\n",
+        ]
+    )

Also applies to: 30-33

🧰 Tools
🪛 GitHub Actions: CI / 1_test (3.11).txt

[error] 11-33: flake8 command failed: lines exceed 100 characters (E501 at line 11) and too many blank lines (E303 at line 33).

🪛 GitHub Actions: CI / 3_test (3.10).txt

[error] 11-33: Flake8 reported a line exceeding 100 characters (E501) at line 11 and too many blank lines (E303) at line 33.

🪛 GitHub Actions: CI / test (3.10)

[error] 11-33: Flake8 reported lines exceeding the 100-character limit (E501) and too many blank lines (E303).

🪛 GitHub Actions: CI / test (3.11)

[error] 11-33: Flake8 reported lines exceeding 100 characters at line 11 (E501) and too many blank lines at line 33 (E303).

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

In `@tests/test_utils.py` at line 11, Fix the Flake8 formatting violations in the
tests/test_utils.py fixture: split the long lines assignment around lines 11 and
30–33 into compliant formatting, and remove the extra blank line before line 33.
Preserve the existing fixture values and behavior.

Source: Pipeline failures

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In `@src/log_analyzer_cli/parsers/syslog.py`:
- Around line 121-123: Normalize parsed timezone-aware timestamps using the same
timezone-alignment policy as filter_lines before returning them, preserving the
represented instant and ensuring all values are comparable with naive syslog
timestamps during analyzer sorting. Add a regression test covering mixed RFC
5424 offset-aware and naive formats.
- Around line 121-122: Update the syslog ISO timestamp pattern used by the
parser around the fractional formats so it accepts only one through six
fractional digits, matching datetime.strptime’s %f behavior; preserve timezone
and non-fractional parsing, and add a test covering the selected handling of
inputs with more than six fractional digits.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 062a5444-077e-4f67-8d58-8f55f17400a7

📥 Commits

Reviewing files that changed from the base of the PR and between de0d81b and dbf4e86.

📒 Files selected for processing (2)
  • src/log_analyzer_cli/parsers/syslog.py
  • tests/test_parsers.py

Comment on lines +121 to 122
"%Y-%m-%dT%H:%M:%S.%f%z",
"%Y-%m-%dT%H:%M:%S.%f",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

python - <<'PY'
from datetime import datetime

value = "2025-03-20T10:15:32.1234567+01:00"
try:
    datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f%z")
except ValueError as exc:
    print(f"Confirmed: {exc}")
else:
    raise SystemExit("Expected %f to reject more than six fractional digits")
PY

Repository: HrachShah/log-analyzer-cli

Length of output: 268


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and inspect the relevant syslog parser section and tests if present.
fd -a 'syslog\.py|test.*syslog|syslog.*test' . || true
printf '\n--- syslog.py ---\n'
wc -l src/log_analyzer_cli/parsers/syslog.py 2>/dev/null || true
sed -n '1,180p' src/log_analyzer_cli/parsers/syslog.py 2>/dev/null || true

printf '\n--- related date parsing tests/usages ---\n'
rg -n "syslog|strptime|datetime|fractional|timestamp=None|%f" src tests 2>/dev/null || true

Repository: HrachShah/log-analyzer-cli

Length of output: 12788


Make syslog ISO fraction parsing match the ISO timestamp pattern.

The second syslog regex pattern accepts arbitrarily many fractional digits, but datetime.strptime(..., "%f") only accepts six. Inputs like 2025-03-20T10:15:32.1234567+01:00 match the line but return timestamp=None. Limit the regex fraction to one through six digits, or normalize longer fractions before parsing. Add a test for the chosen behavior.

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

In `@src/log_analyzer_cli/parsers/syslog.py` around lines 121 - 122, Update the
syslog ISO timestamp pattern used by the parser around the fractional formats so
it accepts only one through six fractional digits, matching datetime.strptime’s
%f behavior; preserve timezone and non-fractional parsing, and add a test
covering the selected handling of inputs with more than six fractional digits.

Comment on lines +121 to 123
"%Y-%m-%dT%H:%M:%S.%f%z",
"%Y-%m-%dT%H:%M:%S.%f",
"%Y-%m-%dT%H:%M:%S%z",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Normalize timestamps before downstream sorting.

This format returns timezone-aware datetimes for RFC 5424 records with offsets. Other syslog formats still return naive datetimes. The supplied src/log_analyzer_cli/analyzer.py:63-111 code sorts these values directly, which raises TypeError when a log contains both formats.

Apply the same timezone-alignment policy used by filter_lines before returning or sorting timestamps. Preserve the instant when converting aware values. Add a mixed-format regression test.

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

In `@src/log_analyzer_cli/parsers/syslog.py` around lines 121 - 123, Normalize
parsed timezone-aware timestamps using the same timezone-alignment policy as
filter_lines before returning them, preserving the represented instant and
ensuring all values are comparable with naive syslog timestamps during analyzer
sorting. Add a regression test covering mixed RFC 5424 offset-aware and naive
formats.

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.

1 participant