Skip to content

Pass all agent.features.* flags to Beat receivers #15437

Description

@belimawr

Problem

Elastic Agent's OTel translator currently handles Beat receiver feature flags inconsistently.

The translator special-cases agent.features.fqdn.enabled and writes it into the generated Beat receiver config as features.fqdn.enabled. Other feature flags under agent.features.* are not propagated to Beat receivers through the same path, so Beat receiver behavior can diverge from process-managed Beats and from the operator's Agent policy.

This means only fqdn currently gets first-class treatment in generated Beat receiver configs, while other Beat-supported feature flags such as:

  • agent.features.log_input_run_as_filestream.enabled
  • agent.features.aws_s3_v2.enabled

are excluded from the generated receiver features block unless they are manually present in raw Beat/receiver config.

Current behavior

The OTel translator evaluates the Agent FQDN flag once and injects only that flag into each Beat receiver config:

  • FQDN value read from Agent feature state:
    // Evaluate the FQDN feature flag once, so every component in this render sees a consistent
    // value even if the global flag changes (via a concurrent policy update) while we iterate.
    fqdnEnabled := features.FQDN()
  • Hard-coded Beat receiver features.fqdn.enabled block:
    // propagate the FQDN feature flag into the receiver config
    sharedConfig["features"] = map[string]any{
    "fqdn": map[string]any{
    "enabled": fqdnEnabled,
    },
    }

On the Beat side, libbeat/features already knows how to parse more than just fqdn from a Beat config features block. It also parses log_input_run_as_filestream and aws_s3_v2: https://github.com/elastic/beats/blob/af686c255e1f319b47524835f63b06d31365d47b/libbeat/features/features.go#L52-L67

	type cfg struct {
		Features struct {
			FQDN               *conf.C `json:"fqdn" yaml:"fqdn" config:"fqdn"`
			LogRunAsFilestream *conf.C `json:"log_input_run_as_filestream" config:"log_input_run_as_filestream"`
			AwsS3V2            *conf.C `json:"aws_s3_v2" yaml:"aws_s3_v2" config:"aws_s3_v2"`
		} `json:"features" yaml:"features" config:"features"`
	}

	parsedFlags := cfg{}
	if err := c.Unpack(&parsedFlags); err != nil {
		return fmt.Errorf("could not unpack features config: %w", err)
	}

	flags.SetFQDNEnabled(parsedFlags.Features.FQDN.Enabled())
	flags.SetLogInputRunFilestream(parsedFlags.Features.LogRunAsFilestream.Enabled())
	flags.SetAwsS3V2(parsedFlags.Features.AwsS3V2.Enabled())

Because the translator's generated receiver features map currently contains only fqdn, the other Beat-supported flags do not reach OTel Beat receivers when configured as Agent feature flags.

This is different from the intended feature propagation model used by process-managed Beats. proto.Features only has a concrete typed field for fqdn, but it also carries the raw feature configuration in Source:

func (f *Flags) AsProto() *proto.Features {
return &proto.Features{
Fqdn: &proto.FQDNFeature{
Enabled: f.FQDN(),
},
Source: f.source,
}

That raw source is intentionally used so new feature flags can be propagated without changing the proto schema every time a flag is added.

The OTel translator should follow the same design intent: do not require a hard-coded typed field for every feature flag, and do not special-case only fqdn.

Desired behavior

All feature flags configured under agent.features.* should be propagated consistently to Beat receivers.

Instead of hard-coding only:

features.fqdn.enabled

the OTel translator should convert the full relevant agent.features.* tree into the Beat receiver features.* tree, preserving feature names and enabled values, for example:

agent:
  features:
    fqdn:
      enabled: true
    log_input_run_as_filestream:
      enabled: true
    aws_s3_v2:
      enabled: true

should produce Beat receiver config equivalent to:

features:
  fqdn:
    enabled: true
  log_input_run_as_filestream:
    enabled: true
  aws_s3_v2:
    enabled: true

Acceptance criteria

  • The OTel translator no longer hard-codes only fqdn when building Beat receiver features.
  • All supported agent.features.* entries are passed to generated Beat receiver config under features.*.
  • Tests cover propagation of multiple feature flags, not only fqdn.
  • The implementation avoids creating two competing feature flag propagation mechanisms for Beat receivers.

Assisted-by: GPT-5.5
Human reviewed: yes

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions