Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ on: # yamllint disable-line rule:truthy
pull_request:
workflow_call:
jobs:
test_frontend:
test_elm_frontend:
name: Test alertmanager frontend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- run: make clean
- run: make all
working-directory: ./ui/app
- run: make assets
- run: make elm-assets
- run: make apiv2
- run: git diff --exit-code

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
/.tarballs
/vendor

# Static assets for UI
/ui/static

!.golangci.yml
!/cli/testdata/*.yml
!/cli/config/testdata/*.yml
Expand Down
4 changes: 3 additions & 1 deletion .promu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ build:
tags:
all:
- netgo
windows: []
- builtinassets
windows:
- builtinassets
ldflags: |
-X github.com/prometheus/common/version.Version={{.Version}}
-X github.com/prometheus/common/version.Revision={{.Revision}}
Expand Down
30 changes: 27 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2015 The Prometheus Authors
# Copyright The Prometheus Authors
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
Expand All @@ -16,6 +16,9 @@ DOCKER_ARCHS ?= amd64 armv7 arm64 ppc64le s390x

include Makefile.common

UI_PATH = ui
MANTINE_PATH = $(UI_PATH)/mantine-ui
# deprecated, use UI_PATH instead
FRONTEND_DIR = $(BIN_DIR)/ui/app
TEMPLATE_DIR = $(BIN_DIR)/template
DOCKER_IMAGE_NAME ?= alertmanager
Expand All @@ -27,13 +30,34 @@ STATICCHECK_IGNORE =
build-all: assets apiv2 build

.PHONY: build
build: common-build
build: assets-compress common-build
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.

Currently the project ships pre-compiled assets bundle so UI does not have to be built each time.

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.

I think we should re-evaluate that for the mantine based UI. The build output has unique filenames per build. This will cause a lot of churn in git.


.PHONY: lint
lint: common-lint

.PHONY: ui-install
ui-install:
cd $(MANTINE_PATH) && npm install

.PHONY: ui-build
ui-build:
cd $(UI_PATH) && bash ./build_ui.sh

.PHONY: ui-lint
ui-lint:
cd $(MANTINE_PATH) && npm run lint

.PHONY: assets
assets: asset/assets_vfsdata.go
assets: ui-install ui-build

.PHONY: assets-compress
assets-compress: assets
- @echo '>> compressing assets'
- scripts/compress_assets.sh

# This target is used in CI to generate the Go file with the embedded elm UI assets.
.PHONY: elm-assets
elm-assets: asset/assets_vfsdata.go

.PHONY: assets-tarball
assets-tarball: ui/app/script.js ui/app/index.html
Expand Down
2 changes: 1 addition & 1 deletion cmd/alertmanager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ func run() int {

webReload := make(chan chan error)

ui.Register(router, webReload, logger)
ui.Register(router, webReload, logger, ff.EnableUIV2())

mux := api.Register(router, *routePrefix)

Expand Down
21 changes: 20 additions & 1 deletion featurecontrol/featurecontrol.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023 Prometheus Team
// Copyright The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
Expand Down Expand Up @@ -27,6 +27,7 @@ const (
FeatureUTF8StrictMode = "utf8-strict-mode"
FeatureAutoGOMEMLIMIT = "auto-gomemlimit"
FeatureAutoGOMAXPROCS = "auto-gomaxprocs"
FeatureUIV2 = "ui-v2"
)

var AllowedFlags = []string{
Expand All @@ -36,6 +37,7 @@ var AllowedFlags = []string{
FeatureUTF8StrictMode,
FeatureAutoGOMEMLIMIT,
FeatureAutoGOMAXPROCS,
FeatureUIV2,
}

type Flagger interface {
Expand All @@ -45,6 +47,7 @@ type Flagger interface {
UTF8StrictMode() bool
EnableAutoGOMEMLIMIT() bool
EnableAutoGOMAXPROCS() bool
EnableUIV2() bool
}

type Flags struct {
Expand All @@ -55,6 +58,7 @@ type Flags struct {
utf8StrictMode bool
enableAutoGOMEMLIMIT bool
enableAutoGOMAXPROCS bool
enableUIV2 bool
}

func (f *Flags) EnableAlertNamesInMetrics() bool {
Expand All @@ -81,6 +85,10 @@ func (f *Flags) EnableAutoGOMAXPROCS() bool {
return f.enableAutoGOMAXPROCS
}

func (f *Flags) EnableUIV2() bool {
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 don't think UI is ready to be shipped with next release, so I would rather not include it in the release. Would it be possible for us to provide a separate build target instead?

return f.enableUIV2
}

type flagOption func(flags *Flags)

func enableReceiverNameInMetrics() flagOption {
Expand Down Expand Up @@ -119,6 +127,12 @@ func enableAlertNamesInMetrics() flagOption {
}
}

func enableUIV2() flagOption {
return func(configs *Flags) {
configs.enableUIV2 = true
}
}

func NewFlags(logger *slog.Logger, features string) (Flagger, error) {
fc := &Flags{logger: logger}
opts := []flagOption{}
Expand Down Expand Up @@ -147,6 +161,9 @@ func NewFlags(logger *slog.Logger, features string) (Flagger, error) {
case FeatureAutoGOMAXPROCS:
opts = append(opts, enableAutoGOMAXPROCS())
logger.Warn("Automatically set GOMAXPROCS to match Linux container CPU quota")
case FeatureUIV2:
opts = append(opts, enableUIV2())
logger.Warn("Enable the new UI (UIv2) and disable the old UI (UIv1)")
default:
return nil, fmt.Errorf("unknown option '%s' for --enable-feature", feature)
}
Expand Down Expand Up @@ -176,3 +193,5 @@ func (n NoopFlags) UTF8StrictMode() bool { return false }
func (n NoopFlags) EnableAutoGOMEMLIMIT() bool { return false }

func (n NoopFlags) EnableAutoGOMAXPROCS() bool { return false }

func (n NoopFlags) EnableUIV2() bool { return false }
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ require (
github.com/oklog/ulid/v2 v2.1.1
github.com/prometheus/client_golang v1.23.2
github.com/prometheus/common v0.67.5
github.com/prometheus/common/assets v0.2.0
github.com/prometheus/exporter-toolkit v0.15.1
github.com/prometheus/sigv4 v0.4.0
github.com/rs/cors v1.11.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,8 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
github.com/prometheus/common/assets v0.2.0 h1:0P5OrzoHrYBOSM1OigWL3mY8ZvV2N4zIE/5AahrSrfM=
github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI=
github.com/prometheus/exporter-toolkit v0.15.1 h1:XrGGr/qWl8Gd+pqJqTkNLww9eG8vR/CoRk0FubOKfLE=
github.com/prometheus/exporter-toolkit v0.15.1/go.mod h1:P/NR9qFRGbCFgpklyhix9F6v6fFr/VQB/CVsrMDGKo4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
Expand Down
46 changes: 46 additions & 0 deletions scripts/compress_assets.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
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.

We removed this file in #4617 do we need to add it back now again?

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.

It's used in prometheus for the bundling of static assets into a go file. I think we should keep it.

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 don't think we should add compress_assets.sh.

  • It is very complex, having to both generate .go files and running extra shell scripts as part of the build. It would be better to just directly use Vite for building the gzip files in a dist folder. This would allow us to easily add brotli compression later.

  • Everytime the ui is opened, alertmanager will decompress the files before sending them over the network. This can be seen from the curl output:

curl -s -D - -H "Accept-Encoding: gzip" http://localhost:9093/assets/index-D3YozeYE.js -o /dev/null
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 530907
Content-Type: application/javascript
Date: Sat, 07 Mar 2026 19:22:22 GMT

So, we are missing out on the main benefit of compression: Reducing the number of TCP round trips.

  • The benefits of compression are negligible:
❯ du -hs  assets/index-D3YozeYE.js.gz  assets/index-pOPVlMO9.css.gz index.html.gz
164K	assets/index-D3YozeYE.js.gz
32K	assets/index-pOPVlMO9.css.gz
4.0K	index.html.gz
❯ du -hs  assets/index-D3YozeYE.js  assets/index-pOPVlMO9.css index.html
520K	assets/index-D3YozeYE.js
216K	assets/index-pOPVlMO9.css
4.0K	index.html

Thus, your change will reduce the binary size by 500K .

TLDR; We should keep it simple and not do any compression. If we want to do compression, we should do it properly, and support streaming the files compressed over the network.

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.

The binary file saving are small right now because of tree shaking. There is very little in the UI if you compile it from this PR. As more features and functionality get added, this will grow. I don't have hard data around what that will be, but if there's consensus around embedding the uncompressed files, I'll pull this out.


# Copyright The Prometheus Authors
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -euo pipefail

export STATIC_DIR=static
PREBUILT_ASSETS_STATIC_DIR=${PREBUILT_ASSETS_STATIC_DIR:-}
if [ -n "$PREBUILT_ASSETS_STATIC_DIR" ]; then
STATIC_DIR=$(realpath $PREBUILT_ASSETS_STATIC_DIR)
fi

cd ui
cp embed.go.tmpl embed.go

GZIP_OPTS="-fkn"
# gzip option '-k' may not always exist in the latest gzip available on different distros.
if ! gzip -k -h &>/dev/null; then GZIP_OPTS="-fn"; fi

mkdir -p static
find static -type f -name '*.gz' -delete

# Compress files from the prebuilt static directory and replicate the structure in the current static directory
find "${STATIC_DIR}" -type f ! -name '*.gz' -exec bash -c '
for file; do
dest="${file#${STATIC_DIR}}"
mkdir -p "static/$(dirname "$dest")"
gzip '"$GZIP_OPTS"' "$file" -c > "static/${dest}.gz"
done
' bash {} +

# Append the paths of gzipped files to embed.go
find static -type f -name '*.gz' -print0 | sort -z | xargs -0 echo //go:embed >> embed.go

echo var EmbedFS embed.FS >> embed.go
2 changes: 2 additions & 0 deletions ui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.gz
embed.go
24 changes: 24 additions & 0 deletions ui/assets_embed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build builtinassets

package ui

import (
"net/http"

"github.com/prometheus/common/assets"
)

var Assets = http.FS(assets.New(EmbedFS))
33 changes: 33 additions & 0 deletions ui/build_ui.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash

# Copyright The Prometheus Authors
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -e

if ! [[ -w $HOME ]]
then
export npm_config_cache=$(mktemp -d)
fi

assetsDir="./static"

function buildMantineUI() {
echo "build mantine-ui"
(cd mantine-ui && npm run build)
mkdir -p ${assetsDir}
rm -rf ${assetsDir}/mantine-ui
mv ./mantine-ui/dist ${assetsDir}/mantine-ui
}

buildMantineUI
18 changes: 18 additions & 0 deletions ui/embed.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build builtinassets

package ui

import "embed"
34 changes: 34 additions & 0 deletions ui/mantine-ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions ui/mantine-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
"@mantine/code-highlight": "^8.3.14",
"@mantine/core": "^8.3.13",
"@mantine/hooks": "^8.3.13",
"@tabler/icons-react": "^3.36.1",
"@tanstack/react-query": "^5.90.20",
"dayjs": "^1.11.19",
"highlight.js": "^11.11.1",
"react": "^19.1.0",
"react-dom": "^19.2.4",
Expand Down
6 changes: 6 additions & 0 deletions ui/mantine-ui/src/components/Header.module.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
.header {
background-color: rgb(65, 73, 81);
color: #fff;
border-bottom: 1px solid var(--mantine-color-gray-6);
}

.navMain {
flex: 1;
}
Expand Down
Loading
Loading