Repository: prometheus/alertmanager
File: notify/util.go (Go)

Code before:
	"crypto/sha256"
	"errors"
	"fmt"
	"io"
	"log/slog"
	"net/http"
	"net/url"
	"slices"
	"strings"

	"github.com/prometheus/common/version"

	"github.com/prometheus/alertmanager/template"
	"github.com/prometheus/alertmanager/tracing"
	"github.com/prometheus/alertmanager/types"
)

// truncationMarker is the character used to represent a truncation.
const truncationMarker = "…"

// UserAgentHeader is the default User-Agent for notification requests.
var UserAgentHeader = version.ComponentUserAgent("Alertmanager")

// WrapWithTracing wraps an HTTP client's transport with tracing instrumentation.
// This should be called once when creating the client, not on every request.
func WrapWithTracing(client *http.Client) {
	if client == nil {
		return
	}
	client.Transport = tracing.Transport(client.Transport)
}

// RedactURL removes the URL part from an error of *url.Error type.
func RedactURL(err error) error {
	var e *url.Error
	if !errors.As(err, &e) {
		return err
	}
	e.URL = "<redacted>"
	return e
}

// Get sends a GET request to the given URL.
func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
	return request(ctx, client, http.MethodGet, url, "", nil)
}

// PostJSON sends a POST request with JSON payload to the given URL.
func PostJSON(ctx context.Context, client *http.Client, url string, body io.Reader) (*http.Response, error) {
	return post(ctx, client, url, "application/json", body)
}

Review comment (security):
We could use sync.once here maybe... But also I don't fully love the need to call notify.WrapWithTracing from all notifiers. Is there a way to replace the injection with an injection that reuses a client, avoiding the memory over-use? I am OOO until next week so I can't try out options until then, and also @siavashs should be back then and we can look at options. Or we can submit this, and then look into improvements later, given the issue.

Code after:
	"crypto/sha256"
	"errors"
	"fmt"
	"io"
	"log/slog"
	"net/http"
	"net/url"
	"slices"
	"strings"

	commoncfg "github.com/prometheus/common/config"
	"github.com/prometheus/common/version"

	"github.com/prometheus/alertmanager/template"
	"github.com/prometheus/alertmanager/tracing"
	"github.com/prometheus/alertmanager/types"
)

// truncationMarker is the character used to represent a truncation.
const truncationMarker = "…"

// UserAgentHeader is the default User-Agent for notification requests.
var UserAgentHeader = version.ComponentUserAgent("Alertmanager")

// NewClientWithTracing creates a new HTTP client with tracing included
// Clients are reused across requests, so tracing is configured once at creation
// rather than on each request.
func NewClientWithTracing(cfg commoncfg.HTTPClientConfig, name string, httpOpts ...commoncfg.HTTPClientOption) (*http.Client, error) {
	client, err := commoncfg.NewClientFromConfig(cfg, name, httpOpts...)
	if err != nil {
		return nil, err
	}
	client.Transport = tracing.Transport(client.Transport)
	return client, nil
}

// RedactURL removes the URL part from an error of *url.Error type.
func RedactURL(err error) error {
	var e *url.Error
	if !errors.As(err, &e) {
		return err
	}
	e.URL = "<redacted>"
	return e
}

// Get sends a GET request to the given URL.
func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
	return request(ctx, client, http.MethodGet, url, "", nil)
}