"""Parse-outcome telemetry for the work-order email processor. Pure stdout EMF emitter -- no AWS client, no boto3. The extraction path is async and the role already has logs:PutLogEvents, so parse outcomes are written as EMF log lines rather than PutMetricData API calls. """ from emf import emit_parse_outcome # CloudWatch EMF namespace + metric for parse-outcome observability. METRIC_NAMESPACE = "Seahaven/WorkorderIngest" def emit_parse_metric(method, template_id, reason_code, work_order_id): """Emit one CloudWatch EMF line recording the parse outcome. Zero-latency (no PutMetricData API call): the extraction path is async and the role already has logs:PutLogEvents. ParseMethod/TemplateId are the only promoted (dimensioned) fields to keep cardinality low; ReasonCode and work_order_id ride along as Logs-Insights-queryable properties. Two dimension sets are published: ["ParseMethod"] (aggregated across all template ids -- the series the fallback-rate alarm queries) AND ["ParseMethod", "TemplateId"] (per-template breakdown for Logs Insights / dashboards). CloudWatch materializes only the exact dimension sets listed here and does NOT auto-aggregate, so the alarm's single-dimension query would receive no data unless ["ParseMethod"] is emitted explicitly.""" emit_parse_outcome( METRIC_NAMESPACE, method, template_id, reason_code, "work_order_id", work_order_id, )