Skip to content

fix: Enforce Singleton For Running Alloy Extension Instances#5763

Open
blewis12 wants to merge 17 commits intomainfrom
enforce-singleton-alloy-extension
Open

fix: Enforce Singleton For Running Alloy Extension Instances#5763
blewis12 wants to merge 17 commits intomainfrom
enforce-singleton-alloy-extension

Conversation

@blewis12
Copy link
Copy Markdown
Member

@blewis12 blewis12 commented Mar 11, 2026

Brief description of Pull Request

This addresses an issue brought up in #5669, where if you attempt to run multiple instances of the alloyengine extension you will encounter errors. These errors are because the default engine has global state that gets mucked up when you try to run multiple pipelines in the same process

Pull Request Details

My proposal is: I don't think we should support this. We don't currently have a way of doing that outside of the extension, and if we enable the ability to run multiple default pipelines in one collector instance via the extension, it opens up for quite some complexity. Instead, I think we should do what extensions like pprof do and enforce a rule that only one extension instance can be started/running at once. I have stolen their implementation and applied it here to the alloy engine extension, and adjusted the documentation accordingly

This change means that users can do something like

extensions:
  alloyengine/one:
    config:
      file: /opt/pwd/config.alloy
    flags:
      server.http.listen-addr: 0.0.0.0:12345
  alloyengine/two:
    config:
      file: /opt/pwd/config.alloy
    flags:
      server.http.listen-addr: 0.0.0.0:12346

service:
  extensions: [alloyengine/one]

but as soon as they add an extension to their running list like

service:
  extensions: [alloyengine/one, alloyengine/two]

they will encounter an error with a clear indicator that only one extension can be running.

The other approach could be to merge the config for multiple extensions into one running extension - but this isn't very conceptually clean, and we already allow users to pass in a directory (since the extension just exposes the same functionality as the run CLI command). I've made it a bit more clear in the docs here that you can indeed pass a directory through the extension, I feel that wasn't so clear before.

@blewis12 blewis12 requested review from a team and clayton-cornell as code owners March 11, 2026 15:11
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 11, 2026

💻 Deploy preview available (fix: Enforce Singleton For Running Alloy Extension Instances):

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enforces a singleton constraint for the alloyengine extension so only one instance can run per process, avoiding conflicts from process-global Default Engine state.

Changes:

  • Add a process-wide atomic guard to prevent starting more than one alloyengine extension instance.
  • Add a lifecycle test verifying a second instance fails to start while the first is running.
  • Update user documentation to describe the limitation and clarify config path behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
extension/alloyengine/extension.go Adds a process-global atomic singleton guard around Start() / run lifecycle.
extension/alloyengine/extension_test.go Adds a test asserting the second instance fails while the first is running.
extension/alloyengine/README.md Documents the new “single active instance per process” limitation.
docs/sources/set-up/otel_engine.md Clarifies config can be file/dir and warns about the singleton limitation.

Comment thread extension/alloyengine/extension.go Outdated
Comment thread extension/alloyengine/extension_test.go
Comment thread docs/sources/set-up/otel_engine.md Outdated
Comment thread extension/alloyengine/README.md
Comment thread extension/alloyengine/extension_test.go Outdated
@blewis12 blewis12 added the backport/v1.14 Backport to release/v1.14 label Mar 11, 2026
Comment thread docs/sources/set-up/otel_engine.md Outdated
Comment thread extension/alloyengine/extension.go Outdated
Comment thread extension/alloyengine/extension_test.go Outdated
@ptodev ptodev self-assigned this Mar 11, 2026
@blewis12 blewis12 force-pushed the enforce-singleton-alloy-extension branch from e0b6240 to b126b99 Compare March 12, 2026 12:00
@blewis12 blewis12 requested a review from ptodev March 16, 2026 14:27
}

func (e *alloyEngineExtension) Start(ctx context.Context, host component.Host) error {
func (e *alloyEngineExtension) Start(_ context.Context, host component.Host) error {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should running be set to true in the beginning to avoid race conditions? Or we could use a mutex instead?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

running already uses an atomic.Bool type so it should be able to handle race conditions. But i'm i've implemented this in a way that will set this after flags have been parsed/validated so we don't set running to true unless we're actually running

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, having an atomic bool is fine. It might be better to delete the defer statement from Start altogether? It'd make it easier to reason about edge cases.

For example:

  • Is there a bug if there is already an alloy extension running that set "running" to true, and then the config is refreshed and startErr set to something non-nil causes "running" to become "false"?
  • The "only one alloyengine extension can be active" error on line 118 is also technically a start error but startErr isn't set there.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a good point, I think we can just do: 6619130

wdyt?

Comment thread extension/alloyengine/extension_test.go Outdated
Comment thread extension/alloyengine/extension_test.go Outdated
Comment thread docs/sources/set-up/otel_engine.md Outdated
@blewis12 blewis12 removed the backport/v1.14 Backport to release/v1.14 label Apr 7, 2026
@blewis12 blewis12 force-pushed the enforce-singleton-alloy-extension branch from c24265f to a6e9feb Compare April 7, 2026 11:43
@blewis12 blewis12 requested a review from ptodev April 9, 2026 09:52
blewis12 and others added 2 commits April 14, 2026 10:58
Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com>
@clayton-cornell clayton-cornell added the type/docs Docs Squad label across all Grafana Labs repos label Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/docs Docs Squad label across all Grafana Labs repos

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants