Add gkg_verbose_logs feature flag and propagate to GKG via headers

What does this MR do and why?

Thread a new gkg_verbose_logs ops feature flag through to the GitLab Knowledge Graph (GKG) service so that a middleware on the GKG side can gate verbose / potentially-PII debug logging. The propagation uses the same two header names that ai-assist's FeatureFlagMiddleware already parses, so the GKG middleware can be lifted almost verbatim from ai-assist:

  • x-gitlab-enabled-feature-flags - SaaS-only, a comma-separated list of flag names, populated from Rails feature flags.
  • x-gitlab-enabled-instance-verbose-ai-logs - self-hosted boolean, sourced from the existing Ai::Setting#enabled_instance_verbose_ai_logs record (reused, not duplicated).

Generic Headers map (Workhorse path)

Per reviewer feedback, the Workhorse GkgServer struct uses a single generic Headers map[string]string instead of separate JWT and per-feature fields. The Ruby layer composes all per-call metadata (including authorization: Bearer <jwt>) into this map before passing it to Workhorse, which forwards every entry as gRPC metadata verbatim. This keeps the Go side policy-free and avoids future struct changes when new headers are needed.

For the direct Ruby gRPC path, headers are built by the class method GrpcClient.outgoing_headers and merged into auth_metadata.

Related: knowledge-graph#305 (parallel GKG-side middleware work), internal tracker dgruzd/tasks#2528.

Precedent

Mirrors Gitlab::AiGateway (ee/lib/gitlab/ai_gateway.rb):

  • #enabled_instance_verbose_ai_logs (line 47-49) - same Ai::Setting read
  • #expanded_ai_logging_on_self_managed? (line 87-93) - same Gitlab::Saas.feature_available?(:gitlab_com_subscriptions) check to decide whether to send the flag-list header
  • #public_headers (line 173-174) - same two header names, same string representation

Feature flag

Name gkg_verbose_logs
Type ops
Group group::knowledge-graph
Default false
Rollout TBD (see "Rollout issue" placeholder in the YAML - will be filled in once the GKG-side middleware lands)

How to set up and validate locally

  1. Run a GKG service locally (or point Gitlab.config.knowledge_graph.grpc_endpoint at one).
  2. Enable the flag: Feature.enable(:gkg_verbose_logs) (on a SaaS-like instance).
  3. Trigger any KG RPC, e.g. from a Rails console:
    Analytics::KnowledgeGraph::GrpcClient.new.list_tools(
      user: User.first,
      source_type: Analytics::KnowledgeGraph::SourceType::REST
    )
  4. Observe the gRPC metadata on the GKG side - x-gitlab-enabled-feature-flags should contain gkg_verbose_logs.

For the self-hosted path:

Ai::Setting.instance.update!(enabled_instance_verbose_ai_logs: true)

-> x-gitlab-enabled-instance-verbose-ai-logs: true on outgoing requests.

Changelog

Added.

Testing

Ruby (grpc_client_spec.rb): 8 new examples in a describe 'verbose logging headers' block covering:

  • SaaS + flag on -> header includes verbose_gkg_logs
  • SaaS + flag off -> flag absent from header, header omitted if empty
  • Self-managed -> flag-list header not sent at all (parity with expanded_ai_logging)
  • Instance setting true / false / nil -> corresponding header values
  • Future-flag append safety (existing flag names preserved)

Ruby (workhorse_spec.rb): 2 new examples verifying the verbose logging headers flow end-to-end through send_orbit_query into the unified headers map.

Go (sendquery_test.go): TestBuildOutgoingContext (5 cases) and TestInjectHeaders (integration test) covering the generic headers map forwarding in Workhorse.

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

  • I've followed the style guide.
  • I've added unit tests.
  • I've tested locally against a running GKG instance.
  • I've verified the feature flag follows the feature-flags guidelines.
  • I've confirmed this is EE-only (Knowledge Graph is EE).
Edited by Dmitry Gruzd

Merge request reports

Loading