mirror of
https://github.com/Sea-Haven-Industries/apm-wo-analysis.git
synced 2026-09-30 04:13:13 +00:00
fix(pipeline): page when classifier has no daily invocation
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
This commit is contained in:
parent
1b3259e875
commit
e4fc32599f
4 changed files with 54 additions and 6 deletions
|
|
@ -311,6 +311,27 @@ class PipelineStack(Stack):
|
|||
),
|
||||
)
|
||||
|
||||
# Daily-export freshness. The DLQ-depth alarm stays OK when the
|
||||
# classifier is never invoked. Sum Invocations over 86400s < 1 pages
|
||||
# a silent day. Missing data is the outage (no datapoint = no run),
|
||||
# so BREACHING, not the house-default NOT_BREACHING.
|
||||
self.classifier_fn.metric_invocations(
|
||||
period=Duration.days(1),
|
||||
statistic="Sum",
|
||||
).create_alarm(
|
||||
self,
|
||||
"ClassifierInvocationsAlarm",
|
||||
alarm_name="apm-wo-analysis-classifier-invocations",
|
||||
alarm_description=(
|
||||
"apm-wo-analysis-classifier had fewer than 1 invocation in 24h "
|
||||
"(daily export missing or S3 trigger broken)"
|
||||
),
|
||||
threshold=1,
|
||||
evaluation_periods=1,
|
||||
comparison_operator=cloudwatch.ComparisonOperator.LESS_THAN_THRESHOLD,
|
||||
treat_missing_data=cloudwatch.TreatMissingData.BREACHING,
|
||||
).add_alarm_action(cw_actions.SnsAction(alarm_topic))
|
||||
|
||||
# S3 trigger: any .xlsx/.csv landing under raw/ invokes the classifier.
|
||||
for suffix in (".xlsx", ".csv"):
|
||||
self.exports_bucket.add_event_notification(
|
||||
|
|
|
|||
|
|
@ -18,9 +18,10 @@ alerts) aren't surfaced and the dashboard has no new snapshot. Recoverable by
|
|||
re-processing the export; not permanent data loss.
|
||||
|
||||
### Detection
|
||||
- Alarm **`apm-wo-analysis-classifier-invocations`** (Sum Invocations over 86400 s `< 1`, `treat_missing_data=breaching`) — a silent day, including a missing export.
|
||||
- No **daily summary** in the WO Slack channel by the usual time (or no 3rd-escalation alert on a day one's expected).
|
||||
- **Grafana** shows no `dt = today` in the Snapshot Date dropdown / panels empty for today.
|
||||
- **Messages in `apm-wo-analysis-classifier-dlq`** (SQS) — strongest signal the classifier failed.
|
||||
- **Messages in `apm-wo-analysis-classifier-dlq`** (SQS) — strongest signal the classifier failed after it *did* run.
|
||||
- CloudWatch errors in `/aws/lambda/apm-wo-analysis-classifier` or `-slack-post`.
|
||||
|
||||
### Context
|
||||
|
|
@ -83,7 +84,7 @@ The curated daily APM filter-view export (~350 WOs, `.xlsx`/`.csv`) reaches S3 b
|
|||
**Verify the agent:**
|
||||
```bash
|
||||
launchctl list | grep apm-wo-uploader # present + last exit 0
|
||||
tail -f ~/apm-wo-drop/uploader.log # per-run logging (TBD: confirm log path)
|
||||
tail -f ~/.local/log/apm-wo-uploader.log # per-run logging (outside WatchPaths)
|
||||
```
|
||||
**Common upstream issues:** agent unloaded (`launchctl load -w …plist`); script
|
||||
moved back into `~/Documents` (TCC blocks it — `LastExitStatus=32256`); `apm-wo-drop`
|
||||
|
|
|
|||
|
|
@ -14,15 +14,19 @@ set -euo pipefail
|
|||
|
||||
DROP_DIR="$HOME/apm-wo-drop"
|
||||
UPLOADED_DIR="$DROP_DIR/uploaded"
|
||||
LOG_FILE="$DROP_DIR/.upload.log"
|
||||
# Log and lock MUST sit outside WatchPaths (~/apm-wo-drop). Writing them
|
||||
# inside the drop folder retriggers launchd on every log line and lock
|
||||
# mkdir/rmdir, which is what ballooned .upload.log to tens of MB.
|
||||
STATE_DIR="$HOME/.local/log"
|
||||
LOG_FILE="$STATE_DIR/apm-wo-uploader.log"
|
||||
LOCK_DIR="$STATE_DIR/apm-wo-uploader.lock"
|
||||
BUCKET="apm-wo-analysis-exports-328440206208"
|
||||
PROFILE="${APM_WO_AWS_PROFILE:-apm-wo-drop}"
|
||||
|
||||
mkdir -p "$UPLOADED_DIR"
|
||||
mkdir -p "$UPLOADED_DIR" "$STATE_DIR"
|
||||
exec >> "$LOG_FILE" 2>&1
|
||||
|
||||
# Single-flight: WatchPaths can fire several times for one save.
|
||||
LOCK_DIR="$DROP_DIR/.upload.lock"
|
||||
if ! mkdir "$LOCK_DIR" 2>/dev/null; then
|
||||
echo "$(date '+%Y-%m-%dT%H:%M:%S') skipping — another run holds the lock"
|
||||
exit 0
|
||||
|
|
@ -50,7 +54,7 @@ for f in "$DROP_DIR"/*.xlsx "$DROP_DIR"/*.csv; do
|
|||
else
|
||||
echo "$(date '+%Y-%m-%dT%H:%M:%S') FAIL $name"
|
||||
failed_count=$((failed_count + 1))
|
||||
osascript -e "display notification \"Failed to upload $name — see .upload.log\" with title \"APM WO Uploader\" sound name \"Basso\"" 2>/dev/null || true
|
||||
osascript -e "display notification \"Failed to upload $name — see $LOG_FILE\" with title \"APM WO Uploader\" sound name \"Basso\"" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
|
|
|
|||
|
|
@ -165,6 +165,28 @@ def test_classifier_has_dlq():
|
|||
)
|
||||
|
||||
|
||||
def test_classifier_daily_invocation_alarm_treats_missing_as_breaching():
|
||||
# A silent day publishes no Invocations datapoint. NOT_BREACHING would
|
||||
# hide the outage; BREACHING is the page. Dimension Value is a Ref to the
|
||||
# function (function_name is set, but CDK still Refs the resource).
|
||||
_template().has_resource_properties(
|
||||
"AWS::CloudWatch::Alarm",
|
||||
Match.object_like(
|
||||
{
|
||||
"AlarmName": "apm-wo-analysis-classifier-invocations",
|
||||
"Namespace": "AWS/Lambda",
|
||||
"MetricName": "Invocations",
|
||||
"Statistic": "Sum",
|
||||
"Period": 86400,
|
||||
"Threshold": 1,
|
||||
"ComparisonOperator": "LessThanThreshold",
|
||||
"EvaluationPeriods": 1,
|
||||
"TreatMissingData": "breaching",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def test_interactions_stage_is_throttled():
|
||||
# The public Slack interactions endpoint caps rate/burst.
|
||||
_template().has_resource_properties(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue