feat(monitors): implement get_monitor_status from the Monitors Management API#3
Open
akeyx wants to merge 9 commits into
Open
feat(monitors): implement get_monitor_status from the Monitors Management API#3akeyx wants to merge 9 commits into
akeyx wants to merge 9 commits into
Conversation
When search_logs is called without a time_zone, the SearchRequest model sets time_zone=None. This None value gets passed into search_params as timeZone=None. The validator then tries to type-check None as a string, which raises an APIParameterError. The fix skips None values during validation so they are treated as "not provided", allowing the default value (UTC) to be applied in the subsequent defaults loop. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Sumo Logic search jobs API (/api/v1/search/jobs) requires time values as epoch milliseconds, not ISO 8601 strings. Sending ISO format results in: "The 'from' field contains an invalid time." This changes to_sumo_api_format and to_sumo_time_format to output epoch milliseconds, and adds epoch time pattern validation to the API validator so it accepts the format it now produces. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The search results endpoint always fetched /messages, which fails for aggregate queries (count by, sum by, etc.) with "requireRawMessages is false". Aggregate query results are served from /records instead. This changes get_search_results to try /records first, then fall back to /messages. Both endpoints are handled gracefully when empty, so queries that match nothing return an empty result set instead of raising an error. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The tool layer passes filter_type to the API client, but the client method didn't accept it. Add the parameter and filter client-side since the Sumo Logic API doesn't support it as a query param. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Sumo Logic Collector API does not support filter_type as a query parameter. Remove it from the tool schema, tool method, and API client rather than faking it with client-side filtering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two changes to the sumologic-api circuit breaker: 1. resilience.py: reset failure_count to 0 on a success in CLOSED state. Previously failure_count was monotonic in CLOSED state, so any process accumulating ~5 transient errors over its lifetime was guaranteed to trip the breaker eventually — "5 ever" rather than "5 consecutive." That's the wrong semantics for an MCP server doing dozens of small queries per session. 2. api_client.py: narrow expected_exception from bare Exception to the same transient set the retry layer already uses (APIError, RateLimitError, TimeoutError, ConnectionError, OSError, httpx.RequestError). User errors like 4xx-from-bad-query no longer count toward opening the breaker. Updated CircuitBreakerConfig.expected_exception's type annotation to reflect that a tuple is supported (Python's except clause accepts either form at runtime). Validated with three async test cases: - failure_count resets on success in CLOSED state - non-transient exceptions are propagated but don't count - 3 consecutive transient errors still open the breaker (intended behavior preserved) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… API
Previously get_monitor_status called non-existent status endpoints. Derive
status from the Monitors Management API instead:
- Single monitor: read /api/v1/monitors/{id} and normalize its status array.
- All monitors: delegate to list_monitors (folder recursion) and build a
status record per monitor, skipping folder entries.
Add helpers _unwrap_monitor_item, _normalize_monitor_status (maps the raw
status array + isDisabled to Normal/Triggered/Disabled/Unknown with a
severity ranking), and _build_monitor_status_record. Timing fields
(lastTriggered/triggerCount24h/last|nextEvaluation) are reported as
unavailable since the API does not expose live evaluation data.
Also:
- Fix LogRecord 'name' attribute collision in get_monitor logging.
- Remove unreachable dead code in the tool-layer get_monitor_status.
- Add 15 unit tests for the status normalization helpers.
- Track tests/test_*.py despite the broad test_*.py ignore rule.
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the previously stubbed
get_monitor_statustool so it returns real, normalized monitor status data from the Sumo Logic Monitors Management API.Changes
api_client.get_monitor_statusto use real endpoints (/api/v1/monitors/search,/api/v1/monitors/{id}), normalize the status into aMonitorStatusenum (NORMAL,TRIGGERED,DISABLED,UNKNOWN), and surface timing fields (e.g.lastTriggered). The multi-monitor path now delegates tolist_monitorsso folder recursion is reused.LogRecordcollision bug inget_monitor—name/typekeys in the loggingextradict overwrote reservedLogRecordattributes and raised"Attempt to overwrite 'name' in LogRecord". Renamed tomonitor_name/monitor_type(also in_build_monitor_alert_data).get_monitor_status.tests/test_monitor_status.py, 15 passing)..gitignoresotests/test_*.pyfiles are tracked.Test plan
uv run pytest tests/test_monitor_status.py— 15 passingget_monitor_statusreturned normalized statuses for all monitors.get_monitorno longer raises theLogRecordcollision error.Note on stacking
This branch is stacked on top of #2 (the search-API fixes), so until #2 merges this PR will also show those commits. Please merge #2 first; afterwards this diff reduces to the
get_monitor_statuswork above.