Skip to content

Add mute intervals feature to suppress notifications during date ranges#2024

Open
aantn wants to merge 5 commits intomasterfrom
claude/add-mute-intervals-config-aa1kI
Open

Add mute intervals feature to suppress notifications during date ranges#2024
aantn wants to merge 5 commits intomasterfrom
claude/add-mute-intervals-config-aa1kI

Conversation

@aantn
Copy link
Copy Markdown
Collaborator

@aantn aantn commented Mar 4, 2026

Summary

This PR adds a new mute intervals feature that allows users to suppress all notifications from a sink during specified date/time ranges. This is useful for silencing alerts during maintenance windows, holidays, or other planned periods.

Key Changes

  • New MuteDateInterval class (timing.py): Implements date/time range checking with timezone support. Parses date strings in YYYY-MM-DD HH:MM format and determines if the current time falls within a muted period.

  • New MuteInterval model (sink_base_params.py): Pydantic model for mute interval configuration with validation for date/time format and timezone names. Includes a regex validator (check_date_time_format) to enforce the expected format.

  • Updated SinkBaseParams (sink_base_params.py): Added optional mute_intervals field to allow configuration of mute periods per sink.

  • Enhanced SinkBase (sink_base.py):

    • Added mute_date_intervals attribute initialized from sink parameters
    • New _build_mute_intervals_from_params() method to construct MuteDateInterval objects from configuration
    • Updated accepts() method to return False if any mute interval is currently active, preventing notifications from being processed
  • Comprehensive test coverage (test_sink_timing.py):

    • TestMuteDateInterval class with tests for timezone validation, various date range scenarios (past, future, spanning boundaries), and timezone conversions
    • Updated TestSinkBase with tests verifying that muted intervals block notifications while non-active intervals allow normal processing
  • Documentation (values.yaml): Added example configuration showing how to use mute intervals with multiple sinks and timezones.

Implementation Details

  • Mute intervals are checked before activity time slices, providing a higher-priority suppression mechanism
  • Timezone support allows mute intervals to be specified in any pytz-supported timezone
  • Date/time comparison uses tuple comparison for simplicity: (year, month, day, hour, minute)
  • Validation occurs at configuration time, preventing invalid mute intervals from being created

https://claude.ai/code/session_01FGiv1N3QcFMWAPT4e1pu93

claude added 3 commits March 4, 2026 10:50
Adds a new `mute_intervals` field parallel to `activity` in sink config.
Users can specify date/time ranges (MM-DD HH:MM format, no year) during
which all notifications to a sink are muted. Supports timezone config
and year-boundary wrapping (e.g. Dec 24 to Jan 2).

https://claude.ai/code/session_01FGiv1N3QcFMWAPT4e1pu93
Switches from MM-DD HH:MM (yearless) to YYYY-MM-DD HH:MM format.
This simplifies the logic (no year-boundary wrapping needed) and
gives users precise control over mute windows.

https://claude.ai/code/session_01FGiv1N3QcFMWAPT4e1pu93
…ch interval

mute_intervals is now a direct list of intervals instead of a nested
object with timezone + intervals. Each interval carries its own timezone.

https://claude.ai/code/session_01FGiv1N3QcFMWAPT4e1pu93
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 82c1f5a9-2af7-449e-8a88-3bcfd9576323

📥 Commits

Reviewing files that changed from the base of the PR and between ed34127 and 8948fc8.

📒 Files selected for processing (1)
  • helm/robusta/values.yaml
✅ Files skipped from review due to trivial changes (1)
  • helm/robusta/values.yaml

Walkthrough

Introduces mute intervals for sinks to suppress notifications during specified date/time ranges. Adds Pydantic models and validators, a timezone-aware MuteDateInterval timing utility, wiring into SinkBase to short-circuit accepts() when an interval is active, plus documentation and tests.

Changes

Cohort / File(s) Summary
Documentation
docs/notification-routing/routing-by-time.rst, helm/robusta/values.yaml
Added docs and Helm comment examples describing mute_intervals for sinks, format (YYYY‑MM‑DD HH:MM), timezone behavior, and YAML samples.
Validation & Config Models
src/robusta/core/sinks/sink_base_params.py
Added DATE_TIME_RE and check_date_time_format; new MuteInterval Pydantic model (start_date, end_date, timezone) with validators; added mute_intervals field to SinkBaseParams.
Timing Utility
src/robusta/core/sinks/timing.py
Added MuteDateInterval class to parse date strings (YYYY‑MM‑DD HH:MM), validate timezone, and determine if current time is within the interval (is_muted_now).
Sink Integration
src/robusta/core/sinks/sink_base.py
Added _build_mute_intervals_from_params() and stored mute date intervals; modified accepts() to return False when any mute interval is currently active (pre-check before existing activity/time-slice logic).
Tests
tests/test_sink_timing.py
Added TestMuteDateInterval tests (timezone validation and is_muted_now scenarios) and tests verifying accepts() behavior when sink mute intervals are active or not.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Finder as Finder/Alert
participant Sink as SinkBase
participant Params as SinkBaseParams
participant Mute as MuteDateInterval
participant TimeSlice as TimeSliceChecker

Finder->>Sink: send finding
Sink->>Params: read sink params (activity, mute_intervals)
Sink->>Mute: for each mute_interval -> is_muted_now()
alt any mute active
    Mute-->>Sink: muted=True
    Sink-->>Finder: rejects finding (muted)
else none active
    Sink->>TimeSlice: check activity time slices
    alt active per timeslice
        TimeSlice-->>Sink: active=True
        Sink-->>Finder: accepts finding
    else inactive
        TimeSlice-->>Sink: active=False
        Sink-->>Finder: rejects finding (inactive)
    end
end

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main feature being added: mute intervals that suppress notifications during specified date ranges.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, providing clear context about the mute intervals feature, implementation details, and all modified files.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/add-mute-intervals-config-aa1kI

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

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 4, 2026

Docker image ready for 6c608b0 (built in 3m 21s)

⚠️ Warning: does not support ARM (ARM images are built on release only - not on every PR)

Use this tag to pull the image for testing.

📋 Copy commands

⚠️ Temporary images are deleted after 30 days. Copy to a permanent registry before using them:

gcloud auth configure-docker us-central1-docker.pkg.dev
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/robusta-runner:6c608b0
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/robusta-runner:6c608b0 me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:6c608b0
docker push me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:6c608b0

Patch Helm values in one line:

helm upgrade --install robusta robusta/robusta \
  --reuse-values \
  --set runner.image=me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:6c608b0

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
tests/test_sink_timing.py (1)

85-87: Return an empty list from the test stub to keep SinkBase contract explicit.

Using pass returns None; returning [] keeps test setup safer if a future test forgets to assign sink.mute_date_intervals manually.

Proposed test-stub adjustment
     def _build_mute_intervals_from_params(self, params):
         # We'll construct mute_date_intervals explicitly below
-        pass
+        return []
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_sink_timing.py` around lines 85 - 87, The test stub
_build_mute_intervals_from_params currently uses pass which returns None and can
violate the SinkBase contract; change it to explicitly return an empty list ([])
so tests that rely on sink.mute_date_intervals get a safe default; update the
function _build_mute_intervals_from_params to return [] rather than using pass
to make the test setup explicit and robust.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/robusta/core/sinks/sink_base_params.py`:
- Around line 63-78: The function check_date_time_format currently uses
DATE_TIME_RE and manual numeric bounds checks that allow invalid calendar dates;
replace the manual parsing with a strict parse using datetime.strptime(value,
"%Y-%m-%d %H:%M") after the regex check (or remove the regex if you prefer) to
validate real calendar dates, catch and rethrow a ValueError with a clear
message if strptime fails, and return the original value on success; update
references to DATE_TIME_RE and the check_date_time_format function accordingly.
- Around line 81-94: MuteInterval currently validates formats for start_date and
end_date but does not check their relative order, so intervals where start_date
is after end_date silently disable muting; add a cross-field validator (e.g., a
`@root_validator` on the MuteInterval class) that parses start_date and end_date
(using the same check_date_time_format logic or datetime parsing with the
provided timezone) and raises ValueError if start >= end, referencing the
existing fields start_date, end_date and the MuteInterval class so the model
enforces correct interval ordering at instantiation.

---

Nitpick comments:
In `@tests/test_sink_timing.py`:
- Around line 85-87: The test stub _build_mute_intervals_from_params currently
uses pass which returns None and can violate the SinkBase contract; change it to
explicitly return an empty list ([]) so tests that rely on
sink.mute_date_intervals get a safe default; update the function
_build_mute_intervals_from_params to return [] rather than using pass to make
the test setup explicit and robust.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 550bedb7-c6c1-4b0f-a98b-d18e2f2909a5

📥 Commits

Reviewing files that changed from the base of the PR and between eae833b and ed34127.

📒 Files selected for processing (6)
  • docs/notification-routing/routing-by-time.rst
  • helm/robusta/values.yaml
  • src/robusta/core/sinks/sink_base.py
  • src/robusta/core/sinks/sink_base_params.py
  • src/robusta/core/sinks/timing.py
  • tests/test_sink_timing.py

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