Skip to content

ui: Move useful parts to httpserver#5097

Merged
SoloJacobs merged 1 commit intoprometheus:mainfrom
SoloJacobs:move-functionality
Mar 26, 2026
Merged

ui: Move useful parts to httpserver#5097
SoloJacobs merged 1 commit intoprometheus:mainfrom
SoloJacobs:move-functionality

Conversation

@SoloJacobs
Copy link
Copy Markdown
Contributor

@SoloJacobs SoloJacobs commented Mar 15, 2026

Stacks on top of #5092

We want to allow users to still be able to import parts of the ui, just not the ones depending on js. Ideas for naming welcome. I also considered changing the name of Register to make it a bit more obvious that this function now does something different, but decided to only change the signature in the end, since we don't plan to expose it.

Pull Request Checklist

Which user-facing changes does this PR introduce?

CHANGE: `ui.Register` no longer exposes all endpoints, one must use `weboperations.Register` as well.

Summary by CodeRabbit

  • Refactor

    • Operational HTTP endpoints (metrics, reload, health/readiness and debug/pprof) are now registered via a dedicated HTTP handler instead of the UI registration.
  • Tests

    • Added/updated tests to verify debug/pprof routing with and without a route prefix and to reflect the new handler registration.

Comment thread cmd/alertmanager/main.go Outdated

ui.Register(router, webReload, logger)
ui.Register(router)
weboperations.Register(router, webReload)
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.

I would call it httpserver, or apiserver, or something like that? Or webops if you want to be shorter...

But apiserver should make it clear that it's the server exposing our api (via http, implementaton detail)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is the list of endpoints we have in this package:

GET /metrics
POST /-/reload
GET /-/healthy
GET /-/ready
GET /debug/*subpath

The api.Register function actually lives in the api package, so I find apiserver quite confusing. httpserver seems ok to. I think we could then consider moving other functionality in cmd/alertmanager/main.go into that package. I think the routing logic from ui should maybe also live in this package, since then users have an easier time migrating. So, hopefully httpserver captures these different parts well enough.

@SoloJacobs SoloJacobs requested a review from Spaceman1701 March 24, 2026 18:17
@ultrotter
Copy link
Copy Markdown
Contributor

ultrotter commented Mar 24, 2026 via email

@SoloJacobs
Copy link
Copy Markdown
Contributor Author

I specifically meant code such as this

// Make routePrefix default to externalURL path if empty string.
if *routePrefix == "" {
	*routePrefix = amURL.Path
}
*routePrefix = "/" + strings.Trim(*routePrefix, "/")
logger.Debug("route prefix", "routePrefix", *routePrefix)

router := route.New().WithInstrumentation(instrumentHandler)
if *routePrefix != "/" {
	router.Get("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, *routePrefix, http.StatusFound)
	})
	router = router.WithPrefix(*routePrefix)
}

But splitting up the remainder of cmd/alertmanager is also a worthwhile endeavor. 😄 Currently, I don't have a good grasp what our package layout should look like. All I want is to avoid causing pain to those who depend on alertmanager as a library.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 26, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cb73a3e2-7bc3-4077-80ac-06a3ce257bfa

📥 Commits

Reviewing files that changed from the base of the PR and between 026d9da and b4475f7.

📒 Files selected for processing (5)
  • cmd/alertmanager/main.go
  • httpserver/httpserver.go
  • httpserver/httpserver_test.go
  • ui/web.go
  • ui/web_test.go

📝 Walkthrough

Walkthrough

Auxiliary HTTP endpoints (metrics, reload, health/readiness, debug/pprof) were moved from ui.Register into a new httpserver.Register; cmd/alertmanager/main.go now calls ui.Register(router) and httpserver.Register(router, webReload) to wire the reload channel.

Changes

Cohort / File(s) Summary
Main entry point
cmd/alertmanager/main.go
Replaced ui.Register(router, webReload, logger) with ui.Register(router) and added httpserver.Register(router, webReload) to wire reload-related endpoints.
New HTTP server package
httpserver/httpserver.go, httpserver/httpserver_test.go
Added httpserver.Register(r *route.Router, reloadCh chan<- chan error) registering /metrics, POST /-/reload (sends a response channel on reloadCh and returns 500 on error), health/readiness probes (/-/healthy, /-/ready), and debug/pprof forwarding (/debug/*). Added tests validating pprof debug routing with and without a route prefix.
Simplified UI layer
ui/web.go, ui/web_test.go
Removed metrics, reload, health, and debug endpoint registrations from ui.Register; changed signature to func Register(r *route.Router) and updated tests to call the simplified Register, dropping logger/reload-channel wiring and related imports.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Router
  participant HTTPServer as httpserver.Handler
  participant Main as cmd/main
  participant Worker as reloadWorker

  Client->>Router: POST /-/reload
  Router->>HTTPServer: route to reload handler
  HTTPServer->>Main: send chan error (respCh) on reloadCh
  Main->>Worker: perform reload (worker reads respCh)
  Worker-->>Main: send error or nil on respCh
  Main-->>HTTPServer: respCh receives result
  HTTPServer-->>Client: 200 OK or 500 with error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • ui: Move useful parts to httpserver #5097 — Performs the same refactor: removing reload/logger parameters from ui.Register and adding httpserver.Register(router, webReload) to move metrics, reload, health, and debug handlers into a separate package.

Suggested reviewers

  • Spaceman1701
  • ultrotter

Poem

🐰 I hopped through code with tiny feet,

Split handlers and moved them neat,
Metrics, reloads, pprof take flight,
UI stays light and sleeps at night,
I nibble bugs and then I beat!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is vague and does not clearly convey what the main change is; 'move useful parts' lacks specificity about which functionality is being moved or why. Consider a more specific title like 'ui: Extract HTTP endpoints to new httpserver package' or 'Refactor: Move non-UI HTTP handlers from ui to httpserver'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description covers the main objective and includes signed-off status and release notes, though it could provide more detail about the motivation and scope of changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@SoloJacobs SoloJacobs changed the title ui: Move useful parts to weboperations ui: Move useful parts to httpserver Mar 26, 2026
In the future, we want to remove the ui build artifacts from the
repository. This will break the usages of

```sh
go get github.com/prometheus/alertmanager/ui
```

That is exactly as expected, since the ui can't function correctly
without the ui artefacts.

This change attempts to make the transition a bit less painful.

Signed-off-by: Solomon Jacobs <solomonjacobs@protonmail.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
ui/web.go (1)

27-28: Make the split contract explicit here.

Register now only mounts static UI assets, but the exported name/comment still read like the old all-in-one entrypoint. A tighter doc comment (or a more specific name such as RegisterAssets) would make it easier for embedders to spot the companion httpserver.Register call now required in cmd/alertmanager/main.go, Line 586-587.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/web.go` around lines 27 - 28, The exported Register(r *route.Router)
currently only mounts static UI assets but its docstring still implies it
registers the whole web entrypoint; update the comment to explicitly state that
Register only mounts static UI assets (or rename the function to RegisterAssets)
and mention in the comment that embedders must call the companion
httpserver.Register entrypoint in main to register dynamic HTTP handlers;
reference the Register function and route.Router (and the companion
httpserver.Register) so readers can find and wire both pieces together.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@httpserver/httpserver.go`:
- Around line 31-36: The POST /-/reload handler currently does two potentially
blocking operations (sending errc into reloadCh and waiting on <-errc). Change
the handler to create a buffered reply channel (e.g., errc := make(chan error,
1)) and use select when sending to reloadCh and when waiting for the reply so
you also listen on req.Context().Done(); on context cancellation return early
with an error response. Update the anonymous handler function (the closure
passed to r.Post) to perform both the send to reloadCh and the receive from errc
via select statements that respect req.Context().Done() to avoid indefinite
blocking.

---

Nitpick comments:
In `@ui/web.go`:
- Around line 27-28: The exported Register(r *route.Router) currently only
mounts static UI assets but its docstring still implies it registers the whole
web entrypoint; update the comment to explicitly state that Register only mounts
static UI assets (or rename the function to RegisterAssets) and mention in the
comment that embedders must call the companion httpserver.Register entrypoint in
main to register dynamic HTTP handlers; reference the Register function and
route.Router (and the companion httpserver.Register) so readers can find and
wire both pieces together.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 01bdf608-ac31-4351-b214-c29785df8c11

📥 Commits

Reviewing files that changed from the base of the PR and between 2e46186 and 026d9da.

📒 Files selected for processing (5)
  • cmd/alertmanager/main.go
  • httpserver/httpserver.go
  • httpserver/httpserver_test.go
  • ui/web.go
  • ui/web_test.go

Comment thread httpserver/httpserver.go
@SoloJacobs SoloJacobs merged commit b649011 into prometheus:main Mar 26, 2026
7 checks passed
@SoloJacobs SoloJacobs deleted the move-functionality branch March 26, 2026 19:24
@SoloJacobs SoloJacobs mentioned this pull request Apr 6, 2026
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.

2 participants