Skip to content

feat: support multiple accounts, regions, and clusters per provider#643

Merged
davincios merged 5 commits into
Tracer-Cloud:mainfrom
hamzzaaamalik:issue/475-multi-instance-integrations
Apr 19, 2026
Merged

feat: support multiple accounts, regions, and clusters per provider#643
davincios merged 5 commits into
Tracer-Cloud:mainfrom
hamzzaaamalik:issue/475-multi-instance-integrations

Conversation

@hamzzaaamalik

Copy link
Copy Markdown
Collaborator

Adds multi-instance support to integrations a single provider (Grafana, AWS, Datadog, Honeycomb, Coralogix) can now have multiple named, tagged instances configured via *_INSTANCES JSON env vars or a new v2 store schema. Every existing single-instance config keeps working unchanged: legacy env vars are untouched, v1 store files auto-migrate on load, resolved_integrations[<service>] still returns the flat default-instance dict. New selector helpers (get_instance_by_name, get_instances_by_tag) plus Grafana end-to-end selection via a grafana_instance alert hint. Explicitly designed around PR #527's three P1 bugs (AWS role_arn path mismatch, env data loss via merge-by-service, filtered-get leak) with named regression tests for each. 54 new tests; full suite 2510/2510; zero existing tests modified.

Closes #475.

@greptile-apps

greptile-apps Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds multi-instance support to five provider integrations (Grafana, AWS, Datadog, Honeycomb, Coralogix) through a new v2 store schema, *_INSTANCES JSON env vars, and selector helpers. Legacy single-instance configs are fully preserved via backward-compat flat keys and auto-migration of v1 store records on load.

The three P1 regressions from PR #527 are explicitly addressed (AWS role_arn path, env data loss via merge_integrations_by_service, filtered-get leak), the propagation condition in resolve_effective_integrations now correctly mirrors classify_integrations's publication condition, _STRUCTURAL_RECORD_FIELDS is no longer duplicated (catalog.py imports from store.py), and the Grafana hint warning is in place. One P2 remains: tag values from _parse_instances_env are stored verbatim without lowercasing, while the selector helpers normalize only the search side — silent mismatches for any env-sourced instance whose JSON tags contain uppercase characters.

Confidence Score: 5/5

Safe to merge — all previously flagged P1 issues are resolved and the one remaining finding is a P2 edge case affecting only uppercase tag values in env-sourced instances.

All three PR #527 P1 bugs are fixed with named regression tests. Previous review threads about the propagation condition mismatch, _STRUCTURAL_RECORD_FIELDS duplication, and the Grafana hint silent fallback are all addressed in this revision. The only new finding (tag case normalization for env-sourced instances) is a P2 that only bites users who intentionally supply uppercase tag values in *_INSTANCES JSON, which is unlikely given the documentation examples all use lowercase.

app/integrations/catalog.py — tag normalization gap in _parse_instances_env (P2).

Important Files Changed

Filename Overview
app/integrations/catalog.py Core classification + env-parsing logic; multi-instance support looks correct; _STRUCTURAL_RECORD_FIELDS now imported from store.py (fixing the duplication); propagation condition in resolve_effective_integrations correctly mirrors classify_integrations; one P2: env-sourced tag values aren't lowercased, causing silent mismatch in tag-based selectors.
app/integrations/selectors.py Clean selector helpers; select_instance correctly refuses to silently fall back on a name miss; tag-based lookups normalize the search value but not stored values — consistent with the catalog-side gap flagged above.
app/integrations/store.py v1→v2 migration, instance-level CRUD, and backward-compat credentials view all look correct; _STRUCTURAL_RECORD_FIELDS is the authoritative source now that catalog.py imports from here.
app/integrations/models.py New IntegrationInstance, EffectiveIntegrationEntry, and EffectiveIntegrations models are well-structured; IntegrationInstance._normalize_tags lowercases tag values correctly but is never called in the actual env/store paths (tag normalization gap).
app/nodes/plan_actions/detect_sources.py Grafana multi-instance hint selection looks correct; unresolved hints now emit a logger.warning (previous PR thread addressed); local-Grafana flag correctly derived from empty api_key on the selected instance.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Env Vars\n*_INSTANCES JSON\nor legacy single vars] --> B[load_env_integrations]
    C[~/.tracer/integrations.json\nv1 or v2] --> D[load_integrations\nauto-migrate v1→v2]
    B --> E[merge_integrations_by_service\nstore wins over env]
    D --> E
    E --> F[classify_integrations\nfor each instance in each record]
    F --> G[resolved service\nflat default-instance config]
    F --> H[_all_service_instances\nlist of name+tags+config\nonly when multi or non-default name]
    G --> I[selectors.py\nget_default_instance / get_instance_by_name\nget_instances_by_tag / select_instance]
    H --> I
    I --> J[detect_sources.py\ngrafana_instance hint lookup]
    F --> K[resolve_effective_integrations\nEffectiveIntegrations model dump\nwith instances propagated when present]
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: app/integrations/catalog.py
Line: 593-594

Comment:
**Tag values not normalized to lowercase for env-sourced instances**

`_parse_instances_env` stores tag values verbatim from the JSON input. Both `selectors.get_instances_by_tag` and `selectors.select_instance` normalize the *search* value to lowercase (e.g., `target_value = (value or "").strip().lower()`) but compare directly against the stored, un-normalized tag value. A user who writes `"tags": {"env": "Prod"}` in `GRAFANA_INSTANCES` JSON would get `{"env": "Prod"}` stored, but any tag-based selection call like `get_instances_by_tag(..., "env", "prod")` silently returns nothing because `"Prod" != "prod"`.

The `IntegrationInstance._normalize_tags` validator in `models.py` already enforces lowercase tag values, but it is never invoked in this env-parsing path. Adding `.lower()` here would make env-sourced instances behave the same as store-sourced ones.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (5): Last reviewed commit: "merge: resolve catalog.py conflict with ..." | Re-trigger Greptile

Comment thread app/nodes/plan_actions/detect_sources.py
Comment thread app/integrations/catalog.py
Comment thread app/integrations/catalog.py Outdated
Comment thread app/integrations/catalog.py
Comment thread app/integrations/catalog.py
@hamzzaaamalik

Copy link
Copy Markdown
Collaborator Author

@Devesh36 please again review.
Thanks

@hamzzaaamalik hamzzaaamalik requested a review from Devesh36 April 18, 2026 09:51
@davincios

Copy link
Copy Markdown
Contributor

Yeah, looks good. Really appreciate the contribution. @hamzzaaamalik

@davincios davincios merged commit 6d6478e into Tracer-Cloud:main Apr 19, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

P0 Support multiple accounts, regions, and clusters in one deployment

3 participants