How to insert my metric into caddy?

	mangleDuration := prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Name:    "mangle_html_duration_seconds",
			Help:    "Time spent processing HTML",
			Buckets: []float64{.001, .005, .01, .05, .1, .5},
		},
		[]string{"status"},
	)

I want to add a custom metric into caddy,what should I do?

Use this:

func (m *ContentFilter) Provision(ctx caddy.Context) error {
	var registerErr error

	if reg := ctx.GetMetricsRegistry(); reg != nil {
		registerOnce.Do(func() {
			logrus.Infof("Registing metric: %s", "mangle_html_duration_seconds")
			if err := reg.Register(mangleDuration); err != nil {
				registerErr = fmt.Errorf("failed to register metrics: %v", err)
			}
		})
	}
	return registerErr
}

	timer := prometheus.NewTimer(prometheus.ObserverFunc(func(v float64) {
		mangleDuration.WithLabelValues("status").Observe(v)
	}))
	defer timer.ObserveDuration()

I’m new to Caddy, why is the metric not showing up after registration?

Did you initiate any requests that affect the values of the metric? Metrics only show up when their values change from the initial one. Show us how you’re testing.

what I did

var (
	mangleDuration = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Name:    "mangle_html_duration_seconds",
			Help:    "Time spent processing HTML",
			Buckets: []float64{1, 5, 10, 50, 100, 500},
		},
		[]string{"status"},
	)
	registerOnce sync.Once
)

func mangleHTML(input []byte) ([]byte, bool) {
	var (
		buf bytes.Buffer
		err error
		doc *html.Node
	)

	timer := prometheus.NewTimer(prometheus.ObserverFunc(func(v float64) {
		mangleDuration.WithLabelValues("success").Observe(v)
		logrus.Infof("mangleHTML invoke spent %.3f", v*1000)
	}))
	defer timer.ObserveDuration()
    ......
}

func (m *ContentFilter) Provision(ctx caddy.Context) error {
	var registerErr error

	if reg := ctx.GetMetricsRegistry(); reg != nil {
		registerOnce.Do(func() {
			logrus.Infof("Registing metric: %s", "mangle_html_duration_seconds")
			if err := reg.Register(mangleDuration); err != nil {
				registerErr = fmt.Errorf("failed to register metrics: %v", err)
			}
		})
	}
	return registerErr
}

I wrote a Caddy module that intercepts reverse proxy responses to sanitize HTML. I can confirm that this method has been called, as shown in the logs below.

time="2025-04-16T17:48:21+08:00" level=info msg="mangleHTML invoke spent 17.520"
time="2025-04-16T17:48:21+08:00" level=info msg="request url: 127.0.0.1:64839/be7e29b0e84f/avatar/05bb842f87f5c312304d66352d694b02 replace to -> 127.0.0.1:64839/avatar/05bb842f87f5c312304d66352d694b02\n"

Find this metric with Grafana

I’ve already integrated Caddy metrics into Grafana.

version: "3.8"

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    restart: unless-stopped

  grafana:
    image: grafana/grafana-oss:latest
    container_name: grafana
    ports:
      - "3000:3000"
    restart: unless-stopped
global:
  scrape_interval: 5s

scrape_configs:
  - job_name: 'caddy'
    static_configs:
      - targets: ['10.21.177.52:2019']