flowsense-engine 0.3.0__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. flowsense_engine-0.5.0/CHANGELOG.md +159 -0
  2. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/MANIFEST.in +1 -0
  3. {flowsense_engine-0.3.0/src/flowsense_engine.egg-info → flowsense_engine-0.5.0}/PKG-INFO +96 -9
  4. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/README.md +94 -8
  5. flowsense_engine-0.5.0/docs/alerting.md +57 -0
  6. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/docs/architecture.md +27 -3
  7. flowsense_engine-0.5.0/docs/authentication.md +85 -0
  8. flowsense_engine-0.5.0/docs/grafana.md +70 -0
  9. flowsense_engine-0.5.0/docs/migrating-to-0.5.md +63 -0
  10. flowsense_engine-0.5.0/docs/production-quickstart.md +235 -0
  11. flowsense_engine-0.5.0/docs/prometheus.md +65 -0
  12. flowsense_engine-0.5.0/docs/python-api.md +142 -0
  13. flowsense_engine-0.5.0/docs/release-0.5.0.md +48 -0
  14. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/docs/releasing.md +6 -5
  15. flowsense_engine-0.5.0/examples/dags/flowsense_demo.py +48 -0
  16. flowsense_engine-0.5.0/examples/python/production_batch.py +86 -0
  17. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/pyproject.toml +21 -1
  18. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/__init__.py +24 -0
  19. flowsense_engine-0.5.0/src/flowsense/application/__init__.py +60 -0
  20. flowsense_engine-0.5.0/src/flowsense/application/batch.py +129 -0
  21. flowsense_engine-0.5.0/src/flowsense/application/client.py +61 -0
  22. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/application/output.py +24 -2
  23. flowsense_engine-0.5.0/src/flowsense/application/policy_document.py +35 -0
  24. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/application/ports.py +20 -0
  25. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/application/serialization.py +39 -0
  26. flowsense_engine-0.5.0/src/flowsense/cli/doctor.py +110 -0
  27. flowsense_engine-0.5.0/src/flowsense/cli/main.py +551 -0
  28. flowsense_engine-0.5.0/src/flowsense/cli/policy.py +103 -0
  29. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/domain/__init__.py +2 -0
  30. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/domain/enums.py +6 -0
  31. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/domain/policy.py +6 -0
  32. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/domain/results.py +3 -0
  33. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/engine/drift.py +16 -15
  34. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/infrastructure/airflow/__init__.py +17 -1
  35. flowsense_engine-0.5.0/src/flowsense/infrastructure/airflow/auth.py +63 -0
  36. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/infrastructure/airflow/client.py +235 -54
  37. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/infrastructure/airflow/config.py +24 -8
  38. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/infrastructure/airflow/dto.py +6 -0
  39. flowsense_engine-0.5.0/src/flowsense/infrastructure/airflow/factory.py +35 -0
  40. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/mcp/server.py +4 -0
  41. flowsense_engine-0.5.0/src/flowsense/observability/__init__.py +5 -0
  42. flowsense_engine-0.5.0/src/flowsense/observability/prometheus.py +248 -0
  43. flowsense_engine-0.5.0/src/flowsense/observability/service.py +111 -0
  44. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0/src/flowsense_engine.egg-info}/PKG-INFO +96 -9
  45. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense_engine.egg-info/SOURCES.txt +28 -0
  46. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense_engine.egg-info/requires.txt +1 -0
  47. flowsense_engine-0.5.0/tests/test_airflow_auth.py +179 -0
  48. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_airflow_client.py +177 -12
  49. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_airflow_compatibility.py +62 -1
  50. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_airflow_contract.py +2 -0
  51. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_airflow_factory.py +32 -2
  52. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_airflow_resilience.py +4 -1
  53. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_analysis_golden.py +1 -1
  54. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_analysis_output.py +6 -0
  55. flowsense_engine-0.5.0/tests/test_analysis_policy_document.py +33 -0
  56. flowsense_engine-0.5.0/tests/test_batch_analysis_output.py +71 -0
  57. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_benchmark_analysis.py +1 -1
  58. flowsense_engine-0.5.0/tests/test_cli.py +778 -0
  59. flowsense_engine-0.5.0/tests/test_cli_policy.py +58 -0
  60. flowsense_engine-0.5.0/tests/test_doctor.py +84 -0
  61. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_domain.py +1 -1
  62. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_drift.py +38 -2
  63. flowsense_engine-0.5.0/tests/test_examples.py +22 -0
  64. flowsense_engine-0.5.0/tests/test_library_client.py +169 -0
  65. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_mcp_integration.py +6 -2
  66. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_mcp_server.py +17 -3
  67. flowsense_engine-0.5.0/tests/test_observability_assets.py +58 -0
  68. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_package_metadata.py +1 -1
  69. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_policy.py +34 -11
  70. flowsense_engine-0.5.0/tests/test_prometheus.py +216 -0
  71. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_public_api.py +12 -0
  72. flowsense_engine-0.3.0/CHANGELOG.md +0 -80
  73. flowsense_engine-0.3.0/src/flowsense/application/__init__.py +0 -30
  74. flowsense_engine-0.3.0/src/flowsense/cli/main.py +0 -190
  75. flowsense_engine-0.3.0/src/flowsense/infrastructure/airflow/factory.py +0 -12
  76. flowsense_engine-0.3.0/tests/test_cli.py +0 -254
  77. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/LICENSE +0 -0
  78. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/docs/benchmarks.md +0 -0
  79. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/docs/migrating-to-0.3.md +0 -0
  80. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/setup.cfg +0 -0
  81. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/application/analysis_engine.py +0 -0
  82. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/application/analyzer.py +0 -0
  83. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/application/pipeline.py +0 -0
  84. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/application/request.py +0 -0
  85. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/application/use_cases.py +0 -0
  86. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/cli/__init__.py +0 -0
  87. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/cli/report.py +0 -0
  88. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/collector/__init__.py +0 -0
  89. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/collector/airflow_client.py +0 -0
  90. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/config.py +0 -0
  91. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/domain/exceptions.py +0 -0
  92. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/domain/models.py +0 -0
  93. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/engine/__init__.py +0 -0
  94. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/engine/analyzer.py +0 -0
  95. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/engine/change_point.py +0 -0
  96. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/engine/history.py +0 -0
  97. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/engine/impact.py +0 -0
  98. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/engine/propagation.py +0 -0
  99. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/engine/root_cause.py +0 -0
  100. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/engine/timing.py +0 -0
  101. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/engine/trend.py +0 -0
  102. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/engine/validation.py +0 -0
  103. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/infrastructure/__init__.py +0 -0
  104. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/infrastructure/airflow/exceptions.py +0 -0
  105. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/infrastructure/airflow/mapper.py +0 -0
  106. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/mcp/__init__.py +0 -0
  107. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/models/__init__.py +0 -0
  108. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/models/dag_analysis.py +0 -0
  109. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/models/task_run.py +0 -0
  110. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/py.typed +0 -0
  111. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense/version.py +0 -0
  112. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense_engine.egg-info/dependency_links.txt +0 -0
  113. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense_engine.egg-info/entry_points.txt +0 -0
  114. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/src/flowsense_engine.egg-info/top_level.txt +0 -0
  115. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_airflow_client_integration.py +0 -0
  116. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_airflow_mapper.py +0 -0
  117. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_analysis_pipeline.py +0 -0
  118. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_analysis_request.py +0 -0
  119. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_analysis_use_case.py +0 -0
  120. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_analyzer.py +0 -0
  121. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_architecture.py +0 -0
  122. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_change_point.py +0 -0
  123. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_cli_report.py +0 -0
  124. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_dag_summary.py +0 -0
  125. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_deprecations.py +0 -0
  126. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_history.py +0 -0
  127. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_impact.py +0 -0
  128. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_observation_validation.py +0 -0
  129. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_propagation.py +0 -0
  130. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_root_cause.py +0 -0
  131. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_timing.py +0 -0
  132. {flowsense_engine-0.3.0 → flowsense_engine-0.5.0}/tests/test_trend.py +0 -0
@@ -0,0 +1,159 @@
1
+ # Changelog
2
+
3
+ All notable changes to FlowSense are documented in this file. The project uses
4
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
+
6
+ ## [Unreleased]
7
+
8
+ ### Added
9
+
10
+ ### Changed
11
+
12
+ ### Fixed
13
+
14
+ ## [0.5.0] - 2026-09-23
15
+
16
+ ### Added
17
+
18
+ - Added a production quickstart and executable bounded batch-analysis example.
19
+ - Added `flowsense doctor` for safe configuration, Airflow API, authentication,
20
+ and DAG-visibility diagnostics.
21
+ - Added `flowsense dags` for read-only DAG discovery with table and JSON output.
22
+ - Added `flowsense analyze-batch` for bounded multi-DAG CLI analysis with the
23
+ versioned batch JSON contract.
24
+ - Added severity-based CI exit thresholds to batch analysis.
25
+ - Added full analysis-policy configuration to the batch CLI.
26
+ - Added bounded DAG discovery to batch analysis with `--all-dags`,
27
+ `--dag-limit`, and optional paused-DAG inclusion.
28
+ - Added CLI access to the versioned batch output JSON Schema through
29
+ `flowsense schema --document batch`.
30
+ - Added reliable versioned JSON file output to single-DAG analysis through
31
+ `flowsense analyze --output-file`.
32
+ - Added reusable, versioned JSON analysis policies for single and batch CLI
33
+ commands, with explicit command-line overrides and JSON Schema export.
34
+ - Added versioned analysis-policy support to the optional Prometheus metrics
35
+ command and propagated the selected policy through every collection cycle.
36
+ - Added a validated per-cycle history limit to the Prometheus metrics command
37
+ so Airflow collection remains explicitly bounded.
38
+ - Added expanded Ruff quality rules, a 90% CI coverage gate, and graceful MCP
39
+ test skipping when the optional dependency is not installed.
40
+ - Reduced Airflow collection overhead with bounded server-side DAG run filters
41
+ and batched task-instance retrieval, including compatibility fallbacks for
42
+ deployments that do not support the optimized endpoints.
43
+ - Added explicit drift direction and effective MAD fields to analysis results,
44
+ plus configurable relative and absolute dispersion floors.
45
+
46
+ ### Changed
47
+
48
+ - Airflow login tokens are now refreshed once after an unauthorized API
49
+ response, while static bearer, Basic, and custom authentication lifecycles
50
+ remain application-owned.
51
+ - Advanced the analysis output schema to version `1.2` for the new drift and
52
+ policy fields.
53
+
54
+ ### Fixed
55
+
56
+ - Constant and near-constant baselines no longer classify negligible timing
57
+ noise as an automatic critical anomaly when raw MAD is zero or extremely
58
+ small.
59
+
60
+ ## [0.4.0] - 2026-09-20
61
+
62
+ ### Added
63
+
64
+ - Added paginated Airflow 2 and 3 DAG discovery with optional paused-DAG
65
+ inclusion.
66
+ - Added an immutable multi-DAG analysis result and bounded, opt-in concurrency
67
+ through `FlowSenseClient.analyze_many()`.
68
+ - Added a versioned, typed batch output document with serialization and JSON
69
+ Schema helpers.
70
+ - Added the `FlowSenseClient` facade for concise embedded Python usage and an
71
+ explicit Airflow data-source factory for application-owned configuration.
72
+ - Added pluggable Airflow authentication providers for Basic Auth, login-token
73
+ exchange, static or rotating bearer tokens, and deployment-specific headers.
74
+ - Added a bounded Prometheus metrics exporter and the optional
75
+ `flowsense serve-metrics` command for continuous DAG analysis.
76
+ - Added a provisioned Grafana dashboard and local Docker Compose example for
77
+ inspecting analysis health, coverage, severity, task drift, and handoffs.
78
+ - Added Prometheus alert rules, Alertmanager configuration, synthetic rule
79
+ tests, and CI validation for FlowSense analysis failures and anomalies.
80
+
81
+ ### Changed
82
+
83
+ - Kept observability integrations as optional delivery adapters so the core
84
+ analysis package remains independent from Prometheus, Grafana, and hosted
85
+ service infrastructure.
86
+
87
+ ## [0.3.0] - 2026-09-20
88
+
89
+ ### Added
90
+
91
+ - Added `AnalyzeDAG` as the shared application use-case boundary for CLI, MCP,
92
+ and library integrations.
93
+ - Added the `DAGAnalysisEngine` extension port and injectable default analysis
94
+ engine.
95
+ - Added versioned golden regression coverage for the complete analysis output.
96
+ - Added deterministic performance benchmarks with machine-readable results and
97
+ a manually triggered GitHub Actions workflow.
98
+ - Added an Airflow 2 and Airflow 3 REST contract test matrix covering
99
+ authentication, routing, validation, mapping, and end-to-end analysis.
100
+
101
+ ### Changed
102
+
103
+ - Separated environment loading and Airflow client construction through explicit
104
+ `AirflowConfig` and infrastructure factories.
105
+ - Made the `TaskRun` domain entity immutable and framework-independent while
106
+ keeping Pydantic at external DTO and output-contract boundaries.
107
+ - Added automated enforcement preventing the domain layer from importing
108
+ Pydantic.
109
+ - Added architecture dependency guardrails and documented supported extension
110
+ points and compatibility boundaries.
111
+
112
+ ### Fixed
113
+
114
+ - Rejected non-finite and negative analysis inputs at the domain boundary.
115
+ - Made root-cause selection deterministic when candidates have equal scores.
116
+
117
+ ## [0.2.1] - 2026-09-10
118
+
119
+ ### Changed
120
+
121
+ - Renamed the Python distribution to `flowsense-engine` while preserving the
122
+ `flowsense` import package and CLI command.
123
+ - Added tokenless PyPI publishing through GitHub Actions Trusted Publishing.
124
+
125
+ ## [0.2.0] - 2026-09-10
126
+
127
+ ### Added
128
+
129
+ - Task handoff drift, impact classification, propagation, and root-cause analysis.
130
+ - Configurable drift, mapped-task aggregation, change-point, and trend policies.
131
+ - Apache Airflow 2 and 3 API compatibility with pagination and bounded history.
132
+ - Retry, timeout, backoff, and `Retry-After` handling for Airflow requests.
133
+ - Historical DAG run analysis with preceding-history isolation.
134
+ - Rich CLI reports, JSON output, severity-based exit thresholds, and schema output.
135
+ - MCP analysis tool with the same policy and versioned response contract as the CLI.
136
+ - Typed `AnalysisRequest` and `AnalysisDocument` contracts with JSON Schema support.
137
+ - Supported top-level library API, typed package marker, and Python 3.12/3.13 CI.
138
+
139
+ ### Changed
140
+
141
+ - Split the analysis workflow into domain, application, infrastructure, and adapter
142
+ boundaries.
143
+ - Analysis output schema advanced to version `1.1` with `current_dag_run_id`.
144
+ - Expected configuration, Airflow API, and payload failures now use a unified error
145
+ hierarchy.
146
+
147
+ ### Fixed
148
+
149
+ - Preserved anomaly origins across normal dependency gaps.
150
+ - Detected drift when the historical median absolute deviation is zero.
151
+ - Aggregated dynamically mapped task instances before analysis.
152
+ - Reported insufficient history and invalid handoff timing as diagnostics.
153
+
154
+ ## [0.1.0] - 2026-08-18
155
+
156
+ ### Added
157
+
158
+ - Initial FlowSense prototype with Airflow task-duration collection and robust
159
+ median/MAD drift detection.
@@ -1,2 +1,3 @@
1
1
  include CHANGELOG.md
2
2
  recursive-include docs *.md
3
+ recursive-include examples *.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flowsense-engine
3
- Version: 0.3.0
3
+ Version: 0.5.0
4
4
  Summary: Temporal drift and anomaly detection for Apache Airflow
5
5
  Author: Omer Cengiz
6
6
  License-Expression: Apache-2.0
@@ -28,6 +28,7 @@ Provides-Extra: dev
28
28
  Requires-Dist: build>=1.2; extra == "dev"
29
29
  Requires-Dist: pyright>=1.1.400; extra == "dev"
30
30
  Requires-Dist: pytest>=8.0; extra == "dev"
31
+ Requires-Dist: pytest-cov>=5.0; extra == "dev"
31
32
  Requires-Dist: ruff>=0.6; extra == "dev"
32
33
  Provides-Extra: mcp
33
34
  Requires-Dist: mcp[cli]>=2.0; extra == "mcp"
@@ -37,10 +38,12 @@ Dynamic: license-file
37
38
 
38
39
  Temporal drift, anomaly detection, and dependency-aware propagation analysis for Apache Airflow.
39
40
 
40
- Current package release: `0.3.0`. See [CHANGELOG.md](CHANGELOG.md) for release
41
+ Current package release: `0.5.0`. See [CHANGELOG.md](CHANGELOG.md) for release
41
42
  notes, [docs/architecture.md](docs/architecture.md) for the system architecture,
42
43
  [docs/benchmarks.md](docs/benchmarks.md) for performance measurement, and
43
- [docs/migrating-to-0.3.md](docs/migrating-to-0.3.md) for migration guidance.
44
+ [docs/production-quickstart.md](docs/production-quickstart.md) for a production
45
+ walkthrough. See [docs/migrating-to-0.5.md](docs/migrating-to-0.5.md) for the
46
+ current migration guidance.
44
47
  Maintainers can use [docs/releasing.md](docs/releasing.md) as the release checklist.
45
48
 
46
49
  FlowSense analyzes historical DAG executions to identify abnormal task behavior and trace how anomalies propagate through downstream dependencies.
@@ -153,6 +156,9 @@ Once published on PyPI, install the distribution with:
153
156
  pip install flowsense-engine
154
157
  ```
155
158
 
159
+ For an end-to-end Airflow setup, follow the
160
+ [production quickstart](docs/production-quickstart.md).
161
+
156
162
  The distribution name is `flowsense-engine`; Python imports and CLI commands
157
163
  remain `flowsense`.
158
164
 
@@ -180,6 +186,7 @@ AIRFLOW_USERNAME=your_username
180
186
  AIRFLOW_PASSWORD=your_password
181
187
  AIRFLOW_API_VERSION=v2
182
188
  AIRFLOW_AUTH_MODE=token
189
+ # AIRFLOW_BEARER_TOKEN=your_static_token
183
190
  AIRFLOW_CONNECT_TIMEOUT=10
184
191
  AIRFLOW_READ_TIMEOUT=10
185
192
  AIRFLOW_MAX_RETRIES=2
@@ -192,6 +199,12 @@ Stable REST API deployments. Airflow 3.x uses the `v2` API and typically uses
192
199
  token authentication. Authentication still depends on the API auth backend
193
200
  configured in the Airflow deployment.
194
201
 
202
+ Static bearer tokens can use `AIRFLOW_AUTH_MODE=bearer` with
203
+ `AIRFLOW_BEARER_TOKEN`; username and password are not required in that mode.
204
+ Library integrations may inject a custom `AirflowAuthProvider` for rotating
205
+ tokens, identity-aware proxies, or deployment-specific headers. See
206
+ [docs/authentication.md](docs/authentication.md) for the complete contract.
207
+
195
208
  CI verifies both integrations through versioned Airflow 2 and Airflow 3 REST
196
209
  contract fixtures. These boundary tests cover authentication, endpoint routing,
197
210
  response validation, domain mapping, and the complete analysis use case.
@@ -211,9 +224,15 @@ export $(grep -v '^#' .env | xargs)
211
224
  Then run:
212
225
 
213
226
  ```bash
227
+ flowsense doctor
228
+ flowsense dags
214
229
  flowsense analyze <dag_id>
230
+ flowsense analyze-batch <dag_id> [<dag_id> ...]
215
231
  ```
216
232
 
233
+ Both single and batch analysis commands support `--fail-on` for CI severity
234
+ gates.
235
+
217
236
  The CLI report includes a DAG summary and separate tables for task drift,
218
237
  handoff drift, change points, trends, propagation paths, and diagnostics.
219
238
  Results are ordered by severity or subject so repeated analyses remain easy to
@@ -223,14 +242,30 @@ For automation and CI/CD integrations, request the versioned JSON document:
223
242
 
224
243
  ```bash
225
244
  flowsense analyze <dag_id> --output json
245
+ flowsense analyze <dag_id> --output-file flowsense-analysis.json
226
246
  ```
227
247
 
248
+ `--output-file` always writes the versioned JSON contract and avoids relying on
249
+ shell redirection in CI jobs.
250
+
228
251
  CI jobs can also fail when the analysis reaches a selected severity:
229
252
 
230
253
  ```bash
231
254
  flowsense analyze <dag_id> --output json --fail-on high
232
255
  ```
233
256
 
257
+ Store reusable analysis settings in a versioned JSON policy file and share it
258
+ between single and batch analysis:
259
+
260
+ ```bash
261
+ flowsense analyze <dag_id> --policy-file flowsense-policy.json
262
+ flowsense analyze-batch --all-dags --dag-limit 10 \
263
+ --policy-file flowsense-policy.json
264
+ ```
265
+
266
+ Explicit policy options override values loaded from the file. Generate its JSON
267
+ Schema with `flowsense schema --document policy`.
268
+
234
269
  `--fail-on` accepts `medium`, `high`, or `critical`. The report is always
235
270
  written before FlowSense exits: code `0` means the severity is below the
236
271
  threshold, code `2` means the threshold was reached, and code `1` remains
@@ -258,6 +293,8 @@ flowsense analyze <dag_id> --dag-run-id <dag_run_id>
258
293
 
259
294
  The MCP tool exposes the same option as `dag_run_id`. Analysis output includes
260
295
  `current_dag_run_id`; this field was introduced in output schema version `1.1`.
296
+ Output schema version `1.2` adds drift `direction`, the regularized
297
+ `effective_mad`, and the dispersion-floor policy values.
261
298
 
262
299
  The JSON document and MCP tool response share the same serialization contract
263
300
  and include a `schema_version` field. The serializer is also available from the
@@ -272,28 +309,53 @@ The same schema can be emitted without connecting to Airflow:
272
309
 
273
310
  ```bash
274
311
  flowsense schema > flowsense-analysis.schema.json
312
+ flowsense schema --document batch > flowsense-batch.schema.json
275
313
  ```
276
314
 
315
+ The default remains the single-DAG analysis schema. Use `--document batch` to
316
+ emit the versioned batch envelope schema, including successful analyses and
317
+ per-DAG failure records.
318
+
277
319
  This output is deterministic and can be used in CI contract checks, editor
278
320
  tooling, or client code generation.
279
321
 
280
322
  ## Library API
281
323
 
282
- FlowSense can also be used as a Python library through its supported top-level
283
- API:
324
+ `FlowSenseClient` is the recommended in-process Python API. The environment
325
+ configured Airflow factory keeps the basic setup concise:
284
326
 
285
327
  ```python
286
- from flowsense import AnalysisRequest, AnalyzeDAG
328
+ from flowsense import FlowSenseClient
287
329
  from flowsense.infrastructure.airflow import create_airflow_data_source
288
330
 
289
- analysis = AnalyzeDAG(create_airflow_data_source).execute(
290
- AnalysisRequest(dag_id="flowsense_demo")
291
- )
331
+ client = FlowSenseClient(create_airflow_data_source)
332
+ analysis = client.analyze("flowsense_demo")
292
333
 
293
334
  print(analysis.overall_severity)
294
335
  print(analysis.primary_origin)
295
336
  ```
296
337
 
338
+ Applications that own configuration can combine `AirflowConfig` with
339
+ `create_airflow_data_source_factory`. Typed integrations may continue to call
340
+ `client.execute(AnalysisRequest(...))`. See the complete
341
+ [Python API guide](docs/python-api.md).
342
+
343
+ Multiple DAGs can be analyzed with bounded, opt-in concurrency. Expected
344
+ FlowSense failures are isolated per DAG:
345
+
346
+ ```python
347
+ result = client.analyze_many(
348
+ ["orders", "payments", "inventory"],
349
+ max_concurrency=3,
350
+ )
351
+ ```
352
+
353
+ `AirflowClient.list_dag_ids()` provides paginated DAG discovery and excludes
354
+ paused DAGs by default.
355
+
356
+ `serialize_batch_analysis(result)` converts the result into the stable batch
357
+ output contract without exposing raw exception objects.
358
+
297
359
  Analysis behavior can be customized with an immutable policy:
298
360
 
299
361
  ```python
@@ -305,6 +367,8 @@ policy = AnalysisPolicy(
305
367
  medium_threshold=2.5,
306
368
  high_threshold=4.0,
307
369
  critical_threshold=6.0,
370
+ minimum_relative_dispersion=0.01,
371
+ minimum_absolute_dispersion=0.001,
308
372
  mapped_task_aggregation=MappedTaskAggregation.MAX,
309
373
  change_point_minimum_segment_size=4,
310
374
  change_point_score_threshold=4.0,
@@ -317,6 +381,8 @@ policy = AnalysisPolicy(
317
381
  `baseline_window` limits the number of historical values used before the current
318
382
  run. Mapped task durations can be aggregated with `MAX`, `MEAN`, or `SUM`. The
319
383
  same policy options are available through the CLI and MCP tool.
384
+ The dispersion floors prevent constant or nearly constant baselines from
385
+ turning negligible timing noise into an automatic critical anomaly.
320
386
  Change-point and trend detection can also be disabled independently with
321
387
  `change_point_detection_enabled=False` or `trend_detection_enabled=False`.
322
388
 
@@ -351,6 +417,27 @@ The server exposes the `analyze_airflow_dag` tool, which returns task drift,
351
417
  handoff drift, impact classification, propagation paths, and primary root-cause
352
418
  information for a DAG.
353
419
 
420
+ ## Prometheus
421
+
422
+ Run continuous analysis and expose the latest DAG and bounded task-level metrics:
423
+
424
+ ```bash
425
+ flowsense serve-metrics example_dag \
426
+ --host 0.0.0.0 \
427
+ --port 9108 \
428
+ --history-run-limit 50 \
429
+ --policy-file flowsense-policy.json
430
+ ```
431
+
432
+ See [docs/prometheus.md](docs/prometheus.md) for the metric contract,
433
+ cardinality policy, and Prometheus scrape configuration.
434
+
435
+ A provisioned Prometheus and Grafana development stack, including the
436
+ `FlowSense Overview` dashboard, is documented in
437
+ [docs/grafana.md](docs/grafana.md).
438
+ Default operational alerts and Alertmanager routing are documented in
439
+ [docs/alerting.md](docs/alerting.md).
440
+
354
441
  ## Development
355
442
 
356
443
  Run unit tests:
@@ -2,10 +2,12 @@
2
2
 
3
3
  Temporal drift, anomaly detection, and dependency-aware propagation analysis for Apache Airflow.
4
4
 
5
- Current package release: `0.3.0`. See [CHANGELOG.md](CHANGELOG.md) for release
5
+ Current package release: `0.5.0`. See [CHANGELOG.md](CHANGELOG.md) for release
6
6
  notes, [docs/architecture.md](docs/architecture.md) for the system architecture,
7
7
  [docs/benchmarks.md](docs/benchmarks.md) for performance measurement, and
8
- [docs/migrating-to-0.3.md](docs/migrating-to-0.3.md) for migration guidance.
8
+ [docs/production-quickstart.md](docs/production-quickstart.md) for a production
9
+ walkthrough. See [docs/migrating-to-0.5.md](docs/migrating-to-0.5.md) for the
10
+ current migration guidance.
9
11
  Maintainers can use [docs/releasing.md](docs/releasing.md) as the release checklist.
10
12
 
11
13
  FlowSense analyzes historical DAG executions to identify abnormal task behavior and trace how anomalies propagate through downstream dependencies.
@@ -118,6 +120,9 @@ Once published on PyPI, install the distribution with:
118
120
  pip install flowsense-engine
119
121
  ```
120
122
 
123
+ For an end-to-end Airflow setup, follow the
124
+ [production quickstart](docs/production-quickstart.md).
125
+
121
126
  The distribution name is `flowsense-engine`; Python imports and CLI commands
122
127
  remain `flowsense`.
123
128
 
@@ -145,6 +150,7 @@ AIRFLOW_USERNAME=your_username
145
150
  AIRFLOW_PASSWORD=your_password
146
151
  AIRFLOW_API_VERSION=v2
147
152
  AIRFLOW_AUTH_MODE=token
153
+ # AIRFLOW_BEARER_TOKEN=your_static_token
148
154
  AIRFLOW_CONNECT_TIMEOUT=10
149
155
  AIRFLOW_READ_TIMEOUT=10
150
156
  AIRFLOW_MAX_RETRIES=2
@@ -157,6 +163,12 @@ Stable REST API deployments. Airflow 3.x uses the `v2` API and typically uses
157
163
  token authentication. Authentication still depends on the API auth backend
158
164
  configured in the Airflow deployment.
159
165
 
166
+ Static bearer tokens can use `AIRFLOW_AUTH_MODE=bearer` with
167
+ `AIRFLOW_BEARER_TOKEN`; username and password are not required in that mode.
168
+ Library integrations may inject a custom `AirflowAuthProvider` for rotating
169
+ tokens, identity-aware proxies, or deployment-specific headers. See
170
+ [docs/authentication.md](docs/authentication.md) for the complete contract.
171
+
160
172
  CI verifies both integrations through versioned Airflow 2 and Airflow 3 REST
161
173
  contract fixtures. These boundary tests cover authentication, endpoint routing,
162
174
  response validation, domain mapping, and the complete analysis use case.
@@ -176,9 +188,15 @@ export $(grep -v '^#' .env | xargs)
176
188
  Then run:
177
189
 
178
190
  ```bash
191
+ flowsense doctor
192
+ flowsense dags
179
193
  flowsense analyze <dag_id>
194
+ flowsense analyze-batch <dag_id> [<dag_id> ...]
180
195
  ```
181
196
 
197
+ Both single and batch analysis commands support `--fail-on` for CI severity
198
+ gates.
199
+
182
200
  The CLI report includes a DAG summary and separate tables for task drift,
183
201
  handoff drift, change points, trends, propagation paths, and diagnostics.
184
202
  Results are ordered by severity or subject so repeated analyses remain easy to
@@ -188,14 +206,30 @@ For automation and CI/CD integrations, request the versioned JSON document:
188
206
 
189
207
  ```bash
190
208
  flowsense analyze <dag_id> --output json
209
+ flowsense analyze <dag_id> --output-file flowsense-analysis.json
191
210
  ```
192
211
 
212
+ `--output-file` always writes the versioned JSON contract and avoids relying on
213
+ shell redirection in CI jobs.
214
+
193
215
  CI jobs can also fail when the analysis reaches a selected severity:
194
216
 
195
217
  ```bash
196
218
  flowsense analyze <dag_id> --output json --fail-on high
197
219
  ```
198
220
 
221
+ Store reusable analysis settings in a versioned JSON policy file and share it
222
+ between single and batch analysis:
223
+
224
+ ```bash
225
+ flowsense analyze <dag_id> --policy-file flowsense-policy.json
226
+ flowsense analyze-batch --all-dags --dag-limit 10 \
227
+ --policy-file flowsense-policy.json
228
+ ```
229
+
230
+ Explicit policy options override values loaded from the file. Generate its JSON
231
+ Schema with `flowsense schema --document policy`.
232
+
199
233
  `--fail-on` accepts `medium`, `high`, or `critical`. The report is always
200
234
  written before FlowSense exits: code `0` means the severity is below the
201
235
  threshold, code `2` means the threshold was reached, and code `1` remains
@@ -223,6 +257,8 @@ flowsense analyze <dag_id> --dag-run-id <dag_run_id>
223
257
 
224
258
  The MCP tool exposes the same option as `dag_run_id`. Analysis output includes
225
259
  `current_dag_run_id`; this field was introduced in output schema version `1.1`.
260
+ Output schema version `1.2` adds drift `direction`, the regularized
261
+ `effective_mad`, and the dispersion-floor policy values.
226
262
 
227
263
  The JSON document and MCP tool response share the same serialization contract
228
264
  and include a `schema_version` field. The serializer is also available from the
@@ -237,28 +273,53 @@ The same schema can be emitted without connecting to Airflow:
237
273
 
238
274
  ```bash
239
275
  flowsense schema > flowsense-analysis.schema.json
276
+ flowsense schema --document batch > flowsense-batch.schema.json
240
277
  ```
241
278
 
279
+ The default remains the single-DAG analysis schema. Use `--document batch` to
280
+ emit the versioned batch envelope schema, including successful analyses and
281
+ per-DAG failure records.
282
+
242
283
  This output is deterministic and can be used in CI contract checks, editor
243
284
  tooling, or client code generation.
244
285
 
245
286
  ## Library API
246
287
 
247
- FlowSense can also be used as a Python library through its supported top-level
248
- API:
288
+ `FlowSenseClient` is the recommended in-process Python API. The environment
289
+ configured Airflow factory keeps the basic setup concise:
249
290
 
250
291
  ```python
251
- from flowsense import AnalysisRequest, AnalyzeDAG
292
+ from flowsense import FlowSenseClient
252
293
  from flowsense.infrastructure.airflow import create_airflow_data_source
253
294
 
254
- analysis = AnalyzeDAG(create_airflow_data_source).execute(
255
- AnalysisRequest(dag_id="flowsense_demo")
256
- )
295
+ client = FlowSenseClient(create_airflow_data_source)
296
+ analysis = client.analyze("flowsense_demo")
257
297
 
258
298
  print(analysis.overall_severity)
259
299
  print(analysis.primary_origin)
260
300
  ```
261
301
 
302
+ Applications that own configuration can combine `AirflowConfig` with
303
+ `create_airflow_data_source_factory`. Typed integrations may continue to call
304
+ `client.execute(AnalysisRequest(...))`. See the complete
305
+ [Python API guide](docs/python-api.md).
306
+
307
+ Multiple DAGs can be analyzed with bounded, opt-in concurrency. Expected
308
+ FlowSense failures are isolated per DAG:
309
+
310
+ ```python
311
+ result = client.analyze_many(
312
+ ["orders", "payments", "inventory"],
313
+ max_concurrency=3,
314
+ )
315
+ ```
316
+
317
+ `AirflowClient.list_dag_ids()` provides paginated DAG discovery and excludes
318
+ paused DAGs by default.
319
+
320
+ `serialize_batch_analysis(result)` converts the result into the stable batch
321
+ output contract without exposing raw exception objects.
322
+
262
323
  Analysis behavior can be customized with an immutable policy:
263
324
 
264
325
  ```python
@@ -270,6 +331,8 @@ policy = AnalysisPolicy(
270
331
  medium_threshold=2.5,
271
332
  high_threshold=4.0,
272
333
  critical_threshold=6.0,
334
+ minimum_relative_dispersion=0.01,
335
+ minimum_absolute_dispersion=0.001,
273
336
  mapped_task_aggregation=MappedTaskAggregation.MAX,
274
337
  change_point_minimum_segment_size=4,
275
338
  change_point_score_threshold=4.0,
@@ -282,6 +345,8 @@ policy = AnalysisPolicy(
282
345
  `baseline_window` limits the number of historical values used before the current
283
346
  run. Mapped task durations can be aggregated with `MAX`, `MEAN`, or `SUM`. The
284
347
  same policy options are available through the CLI and MCP tool.
348
+ The dispersion floors prevent constant or nearly constant baselines from
349
+ turning negligible timing noise into an automatic critical anomaly.
285
350
  Change-point and trend detection can also be disabled independently with
286
351
  `change_point_detection_enabled=False` or `trend_detection_enabled=False`.
287
352
 
@@ -316,6 +381,27 @@ The server exposes the `analyze_airflow_dag` tool, which returns task drift,
316
381
  handoff drift, impact classification, propagation paths, and primary root-cause
317
382
  information for a DAG.
318
383
 
384
+ ## Prometheus
385
+
386
+ Run continuous analysis and expose the latest DAG and bounded task-level metrics:
387
+
388
+ ```bash
389
+ flowsense serve-metrics example_dag \
390
+ --host 0.0.0.0 \
391
+ --port 9108 \
392
+ --history-run-limit 50 \
393
+ --policy-file flowsense-policy.json
394
+ ```
395
+
396
+ See [docs/prometheus.md](docs/prometheus.md) for the metric contract,
397
+ cardinality policy, and Prometheus scrape configuration.
398
+
399
+ A provisioned Prometheus and Grafana development stack, including the
400
+ `FlowSense Overview` dashboard, is documented in
401
+ [docs/grafana.md](docs/grafana.md).
402
+ Default operational alerts and Alertmanager routing are documented in
403
+ [docs/alerting.md](docs/alerting.md).
404
+
319
405
  ## Development
320
406
 
321
407
  Run unit tests:
@@ -0,0 +1,57 @@
1
+ # Prometheus alerting
2
+
3
+ The local observability stack loads a tested set of FlowSense alert rules and
4
+ routes firing alerts to Alertmanager.
5
+
6
+ ## Included alerts
7
+
8
+ | Alert | Default condition | Severity |
9
+ | --- | --- | --- |
10
+ | `FlowSenseExporterDown` | Metrics endpoint unavailable for 2 minutes | Critical |
11
+ | `FlowSenseAnalysisFailed` | Latest analysis failed for 2 minutes | Warning |
12
+ | `FlowSenseAnalysisStale` | No successful analysis for 10 minutes in total | Warning |
13
+ | `FlowSenseCriticalDAG` | DAG severity remains critical for 2 minutes | Critical |
14
+ | `FlowSenseCriticalTask` | Task severity remains critical for 2 minutes | Critical |
15
+ | `FlowSenseTaskMetricsDropped` | Cardinality limit omits tasks for 5 minutes | Warning |
16
+ | `FlowSenseAnalysisSlow` | Analysis remains above 30 seconds for 5 minutes | Warning |
17
+
18
+ The stale rule expression becomes true after five minutes without a successful
19
+ analysis and must remain true for another five minutes before firing. Adjust
20
+ thresholds in `deploy/observability/alerts.yml` to match the configured analysis
21
+ interval and operational expectations.
22
+
23
+ ## Validate rules
24
+
25
+ Run syntax and unit checks with the Prometheus image pinned by the Compose file:
26
+
27
+ ```bash
28
+ docker run --rm \
29
+ --entrypoint promtool \
30
+ -v "$PWD/deploy/observability:/workspace:ro" \
31
+ -w /workspace \
32
+ prom/prometheus:v3.14.0 \
33
+ check rules alerts.yml
34
+
35
+ docker run --rm \
36
+ --entrypoint promtool \
37
+ -v "$PWD/deploy/observability:/workspace:ro" \
38
+ -w /workspace \
39
+ prom/prometheus:v3.14.0 \
40
+ test rules alerts.test.yml
41
+ ```
42
+
43
+ ## Configure notifications
44
+
45
+ The committed Alertmanager configuration intentionally uses an empty local
46
+ receiver. Firing alerts are visible in the Alertmanager UI and the Grafana
47
+ dashboard, but no external notification is sent by default.
48
+
49
+ For production, replace the receiver in
50
+ `deploy/observability/alertmanager.yml` with the organization's managed email,
51
+ Slack, PagerDuty, webhook, or other supported integration. Keep credentials out
52
+ of Git and inject them through the deployment platform's secret management
53
+ mechanism.
54
+
55
+ Alertmanager is available locally at `http://localhost:9093`. Verify routing and
56
+ notification delivery in a non-production environment before enabling it for
57
+ operational incidents.