Show transactional email volume by purpose

This commit is contained in:
SimpleTest 2026-08-12 20:18:22 +03:00
parent 6c1fe594f6
commit 49a188023a
4 changed files with 59 additions and 2 deletions

View File

@ -1198,6 +1198,21 @@ destinations, production availability, and measured alert policies remain
deployment decisions. In Kubernetes, put the metrics token in deployment decisions. In Kubernetes, put the metrics token in
`existingSecret`; configure the external scraper to send it as a Bearer token. `existingSecret`; configure the external scraper to send it as a Bearer token.
The provisioned Grafana overview also shows one-hour transactional-email
attempts grouped only by the fixed application-owned purpose and outcome. It
does not expose recipient addresses, subjects, message bodies, support
references, or user identifiers. The panel is intended to answer which bounded
workflow is creating delivery volume or failures; it is not a user-activity
log.
Support conversations deliberately do not send one email per staff message.
The requester receives an email for the first staff response and for later
public status changes; additional messages while the status is unchanged stay
in the private support conversation and the in-product notification flow.
Anonymous submissions receive the address-confirmation message before they
enter the operator queue. Operator email alerts are disabled unless
`SUPPORT_OPERATOR_EMAIL_MODE=immediate` is explicitly configured.
## Production release without pushing the frozen repository ## Production release without pushing the frozen repository
The post-submission workflow keeps the public Git repository and The post-submission workflow keeps the public Git repository and

View File

@ -369,6 +369,48 @@
], ],
"title": "BEAM scheduler run queue by replica", "title": "BEAM scheduler run queue by replica",
"type": "timeseries" "type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "wnh-prometheus"
},
"fieldConfig": {
"defaults": {
"decimals": 0,
"unit": "short"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 24,
"x": 0,
"y": 40
},
"id": 11,
"options": {
"legend": {
"displayMode": "table",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"targets": [
{
"editorMode": "code",
"expr": "sum by (kind, status) (increase(who_need_help_email_by_kind_deliveries_total[1h]))",
"legendFormat": "{{kind}} {{status}}",
"range": true,
"refId": "A"
}
],
"title": "Transactional email attempts by purpose and outcome (1h)",
"type": "timeseries"
} }
], ],
"refresh": "5s", "refresh": "5s",

View File

@ -549,7 +549,7 @@ curl --fail --silent --show-error \
if ! jq -e ' if ! jq -e '
.dashboard.uid == "wnh-overview" and .dashboard.uid == "wnh-overview" and
.meta.provisioned == true and .meta.provisioned == true and
(.dashboard.panels | length) == 10 (.dashboard.panels | length) == 11
' "$output_dir/grafana-dashboard.json" >/dev/null; then ' "$output_dir/grafana-dashboard.json" >/dev/null; then
echo "The provisioned Grafana dashboard did not match the tracked dashboard." >&2 echo "The provisioned Grafana dashboard did not match the tracked dashboard." >&2
exit 1 exit 1

View File

@ -1561,7 +1561,7 @@ docker run --rm \
"$PYTHON_IMAGE" python -c \ "$PYTHON_IMAGE" python -c \
'import py_compile; py_compile.compile("/src/mock_server.py", cfile="/tmp/mock_server.pyc", doraise=True)' 'import py_compile; py_compile.compile("/src/mock_server.py", cfile="/tmp/mock_server.pyc", doraise=True)'
jq --exit-status \ jq --exit-status \
'type == "object" and .uid == "wnh-overview" and (.panels | length) == 10' \ 'type == "object" and .uid == "wnh-overview" and (.panels | length) == 11' \
ops/observability/grafana/dashboards/who-need-help-overview.json \ ops/observability/grafana/dashboards/who-need-help-overview.json \
>/dev/null >/dev/null