mirror of
https://github.com/taylanbakircioglu/flowfish.git
synced 2026-09-11 21:38:54 +00:00
7a5d4904a9
Bring the public mirror up to date with the latest developments: - L7 HTTP Path Visibility & Per-Path Edge Model (v2.7.0): real HTTP paths in the Service Map / Integration Hub / exports instead of "/". Touches event_transformer (path extraction), graph-writer per-path MERGE key + indexes, graph-query per-path counting, and the frontend. - Beyla route decoration to fix the `/*/*/*/*/*` star-explosion in API-gateway namespaces (low-cardinality route labelling). - RabbitMQ queue-declaration resilience: graph-writer and timeseries-writer tolerate a pre-existing queue whose arguments differ from the declaration (bind to the existing queue instead of crashing). - Version bump to 2.8.0 + CHANGELOG. Example hostnames/annotations use placeholder values (example.com).
10 KiB
10 KiB
Changelog
All notable changes to Flowfish are documented in this file.
The project follows Semantic Versioning.
[2.8.0] - 2026-06
Security
- nginx pinned to patched 1.31.1-alpine across the frontend image
(
frontend/Dockerfile,Dockerfile.production,Dockerfile.simple) and the local-test manifests (poolslip advisory). The floatingnginx:alpinetag previously resolved to the vulnerable 1.31.0.
Fixed — RabbitMQ queue-declaration resilience
- graph-writer and timeseries-writer no longer crash (graph-writer)
or spin in the reconnect handler (timeseries-writer) when a queue already
exists with arguments that differ from the declaration — e.g. a legacy
queue created without
x-dead-letter-exchange. The consumers now catch thePRECONDITION_FAILEDand bind to the existing queue as-is. graph-writer additionally uses a dedicated channel per consumer, so one queue's argument mismatch can no longer tear down the other consumers.
[2.7.0] - 2026-05
Fixed — L7 HTTP Path Visibility (Audit v4)
Real HTTP paths now appear in the Service Map, Integration Hub, JSON
exports, and CSV exports. Before this release every outbound HTTP
dependency rendered as / because:
event_transformer._build_http_eventonly readurl.path/http.route— both server-side attributes. OpenTelemetry HTTP semconv exposesurl.fullon CLIENT spans, which Beyla uses for every outgoing call. The transformer silently fell back to/.- The graph-writer Neo4j MERGE key was
{analysis_id}only, so multiple endpoints between two workloads collapsed onto a singleL7_COMMUNICATES_WITHedge — withhttp_pathoverwritten on every upsert.
Added — Per-path edge model
event_transformer._extract_http_path— walks the OTel HTTP semconv lookup chain (url.path → http.route → url.full → http.target → http.url). Usesurllib.parse.urlsplitfor the client-side attributes and rejects malformed URLs via a relative-path guard so garbageurl.fullpayloads cannot poison the per-path edge MERGE key._transform_single_spanHTTP branch widening — CLIENT-only spans (url.full,http.url,http.target) now trigger the HTTP branch instead of being dropped. gRPC / DNS still take priority.- Per-path Neo4j edges —
L7_COMMUNICATES_WITHMERGE key extended to{analysis_id, http_method, http_path}withcoalesce(..., '')so empty values don't violate Cypher's null-in-MERGE-key rule. Edge attributes (request_count,error_count,total_latency_ms, trace context) are now stable per endpoint. - Dedup migration alignment —
_MIGRATE_OUT_CYPHERand_MIGRATE_IN_CYPHERuse the same 3-property MERGE key when re-pointing edges offnamespace='unknown'placeholders so the periodic dedup pass does not collapse per-path edges. - Relationship property indexes —
l7_comm_method(ON (r.http_method)) andl7_comm_path(ON (r.http_path)) onL7_COMMUNICATES_WITH(Neo4j 4.3+, idempotentIF NOT EXISTS). - Distinct-peer aggregation —
graph_query_engine.get_l7_dependency_summarycounts distinct destination/source workloads instead of edges, so per-path multiplication does not inflateinbound_count/outbound_countin API responses or the Integration Hub UI. - Frontend canvas edge bundling —
ServiceMap.tsxgroups per-path edges by(source, target, protocol)before passing them to React Flow. Each bundle becomes one visual edge with aN pathslabel suffix and the full per-path breakdown indata.paths. Edge CSV export expandspathsso one CSV row corresponds to one(method, path). - Integration Hub Edges Table — rowKey extended to include
(cluster, namespace, method, path)so per-path multiplication cannot trigger React duplicate-key warnings.
Tests
services/flowfish-l7-collector/tests/test_event_transformer.py— 19 unit tests covering the OTel lookup order, server vs. client attribute split, query/fragment stripping, malformed-URL guard, legacy method fallback, and the gRPC/DNS branch isolation.services/graph-query/tests/test_l7_dependency_summary.py— 3 new scenarios pin the distinct-peer accounting (per-path collapse to single peer, protocol-as-peer-identity, filter+per-path interaction).
Migration notes (v2.6.0 → v2.7.0)
See docs/migration-notes.md
for the full table including deployment order, optional purge query
for old single-edge analyses, PII implications of per-path storage,
and Cypher cardinality observation queries with Beyla routes.patterns
guidance.
Required actions
| Audience | Action |
|---|---|
| Cluster operators | Roll out collector + graph-writer + graph-query + frontend in the same release. Neo4j indexes are created automatically. |
| Operators upgrading from v2.5.0 / v2.6.0 | Old analyses retain pre-fix data (/ paths, single edge per (src, dst)); re-run analyses you want correct paths for. Optional Cypher purge query in migration notes. |
| API consumers (read-only) | None — response shapes are unchanged. |
| Frontend snippet/CSV consumers | Re-export after upgrade; edge CSV now has one row per endpoint and JSON edges carry a structured paths array. |
[2.6.0] - 2026-05
Added — Integration Hub L7 parity
- L7 dependency summary filters.
GET /api/v1/l7/dependencies/summarynow accepts the same identification surface as the L4 summary endpoint:annotation_key,annotation_valuelabel_key,label_valueowner_name(alias forworkload_name)pod_nameworkload_namefilter_noise_annotations(boolean, defaultfalse)- All filter values support fnmatch globs (
*,?,[seq]).
is_matchedflag on every workload entry in the L7 summary response so callers can distinguish workloads matched by the filter (is_matched=true) from their immediate neighbours pulled in for context (is_matched=false).workload_name_exactflag onGET /api/v1/l7/dependencies/tree-summary. Defaulttrueto preserve previous exact-match semantics; the Integration Hub frontend explicitly sendsworkload_name_exact=falseto align with L4's case-insensitive substring behaviour.- Integration Hub BOTH analysis level. When the operator picks an analysis with
analysis_level=both:- Step 1 fans the configured form out to L4 and L7 endpoints in parallel via
Promise.allSettled. - Step 2 (Preview) renders two tabs — Network Dependencies (L4) and Application Dependencies (L7) — each with its own error banner on partial failure.
- Step 3 (Integration Code) shows a top-level L4/L7 toggle that swaps the active snippet set.
- The L4 leg covers every selected analysis; the L7 leg targets the first analysis with a toast warning when extra analyses are dropped (L7 endpoints are single-analysis).
- Step 1 fans the configured form out to L4 and L7 endpoints in parallel via
- Service Identification card visibility. The card now renders on every analysis level (L4, L7, BOTH). The standalone "L7 Workload Search" card has been removed; the unified card handles every method.
Namespaceis an orthogonal field. It applies to every identification method (annotation, label, namespace+deployment/workload, pod name, advanced) rather than onlynamespace_deployment.namespace_deploymentlabel renamed to Namespace + Deployment / Workload for clarity between L4 and L7.- OpenAPI spec updates for the two endpoints (
analysis_idis nowstring, new parameters documented).
Changed
services/graph-query/app/graph_query_engine.py:_NOISE_ANNOTATION_PREFIXES,_filter_summary_annotations,_parse_metadata_field, and_glob_match_metadataare now module-level helpers shared by the L4 and L7 paths.services/graph-query/app/graph_query_engine.py:get_l7_dependency_summarypre-filters with CypherCONTAINS(quote-wrapped for JSON-encoded strings) and post-filters with Pythonfnmatchto match L4 parity. The Neo4j query LIMIT is multiplied by 10 when a filter is active so that post-filtering does not truncate results.services/graph-query/app/graph_query_engine.py:find_l7_workload_dependenciesacceptsworkload_name_exactand uses the shared_glob_match_metadatahelper.backend/routers/l7_communications.py: proxy forwards all new parameters and aliasesowner_name → workload_name(withworkload_nametaking precedence when both are supplied).frontend/src/utils/snippetBuilders.ts: L7 cURL / Python / JS / Java / Pipeline snippets emit the full filter surface; L7 tree snippets always setworkload_name_exact=false.
Migration notes (v2.5.0 → v2.6.0)
| Topic | What changes | Required action |
|---|---|---|
GET /l7/dependencies/summary |
New optional parameters listed above. Existing callers without any filter receive the unchanged response shape plus is_matched=true on every workload (no neighbour-expansion when no filter is active). |
None for unchanged callers. |
GET /l7/dependencies/tree-summary |
New optional workload_name_exact parameter, default true. |
None — the default keeps existing behaviour. Clients that previously relied on substring matching (only the Integration Hub did so) must explicitly pass workload_name_exact=false. |
| L7 Workload Search card | Removed from the Integration Hub UI; the unified Service Identification card now exposes the same workload_name field through the Namespace + Deployment / Workload method. |
None for API consumers; UI bookmarks should re-pin the Integration Hub page. |
analysis_id on L7 endpoints |
OpenAPI type corrected to string to match the multi-cluster sub-analysis prefix already used at runtime. |
None — backend was already accepting strings; only the schema is corrected. |
| Pipeline snippets | The Integration Hub now generates the same identification parameters for L4 and L7 snippets when analysis_level=both. |
Re-copy snippets after upgrading if your pipeline relies on the L7 query string. |
Deprecated
- The standalone L7 workload search input (Integration Hub) is removed in favour of the unified identification card. The underlying API endpoints are unchanged.
Fixed
- L7 Integration Hub returning empty results for namespaces that worked in the Service Map. The mismatch was caused by the L7 summary endpoint not accepting annotation/label/owner_name filters and the frontend not routing BOTH-mode queries through both L4 and L7 endpoints.
[2.5.0] - 2026-04
Baseline release prior to the Integration Hub L7 parity work.