Skip to content

feature: Add query_name parameter to all(), filters(), and get() for observability #923

@fatih-acar

Description

@fatih-acar

Component

Python SDK

Describe the Feature Request

Feature Request: Add query_name parameter to all(), filters(), and get() for observability

Context

Related to IFC-2395 — Enrich trace data with generator-side context.

Infrahub's backend already collects trace data at the platform level (database queries, API calls, timing) and exposes trace attributes for GraphQL query operation names. However, the SDK query methods (all(), filters(), get()) generate GraphQL queries internally without any user-supplied operation name. This makes it impossible to correlate a trace back to a specific call site in user code (e.g. inside a generator or transform).

Problem

When a generator or transform issues multiple SDK queries, all of them appear in traces as anonymous GraphQL operations. There is no way to distinguish which client.all(...) or client.get(...) call produced a given trace span. This forces developers to either:

  • Instrument their own code manually with custom timing/logging
  • Drop down to execute_graphql() with hand-written queries just to control the operation name
  • Rely on guesswork to map slow traces back to specific lines of code

Proposed Solution

Add an optional query_name: str | None = None parameter to the all(), filters(), and get() methods on both InfrahubClient and InfrahubClientSync. When provided, this name should be used as the GraphQL operation name in the generated query, so that it appears in backend traces.

Example Usage

# Today — anonymous query, no way to identify in traces
devices = await client.all(kind="InfraDevice")

# Proposed — named query, shows up as "GetAllEdgeDevices" in trace spans
devices = await client.all(kind="InfraDevice", query_name="GetAllEdgeDevices")
# In a generator, giving each query a meaningful name for trace correlation
site = await client.get(
    kind="LocationSite",
    name__value=site_name,
    query_name="SiteGenerator_FetchTargetSite",
)

vlans = await client.filters(
    kind="InfraVLAN",
    site__name__value=site_name,
    query_name="SiteGenerator_FetchSiteVLANs",
)

Expected Behavior

  1. When query_name is provided, the SDK should use it as the GraphQL operation name in the generated query string (e.g. query SiteGenerator_FetchTargetSite { ... } instead of query { ... }).
  2. When query_name is None (default), behavior is unchanged — no breaking change.
  3. The operation name should flow through to the backend's existing trace attributes for GraphQL query names, enabling direct correlation between a trace span and a specific SDK call in user code.

Methods to Update

  • InfrahubClient.all() / InfrahubClientSync.all()
  • InfrahubClient.filters() / InfrahubClientSync.filters()
  • InfrahubClient.get() / InfrahubClientSync.get()
  • InfrahubClient.count() / InfrahubClientSync.count() (if applicable)

Implementation Notes

  • The query_name should be validated to conform to GraphQL operation name rules (alphanumeric + underscore, must not start with a digit).
  • The internal GraphQL query builder that these methods use should accept the operation name and inject it into the query string.
  • The execute_graphql method already sits downstream and could be extended to propagate the operation name into trace metadata if it doesn't already.

Motivation

This is a building block for the broader goal described in IFC-2395: enabling generator authors to debug performance issues without custom instrumentation. With named queries, a developer looking at a trace can immediately see that a slow span came from SiteGenerator_FetchSiteVLANs rather than an anonymous query, and jump straight to the relevant code.

Describe the Use Case

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions