// Package integrations provides a way to run and manage Grafana Agent1// "integrations," which integrate some external system (such as MySQL) to2// Grafana Agent's existing metrics, logging, and tracing subsystems.3//4// Integrations are implemented in sub-packages. Every integration must5// have an implementation of Config that configures the integration. The Config6// interface is then used to instantiate an instance of the Integration7// interface.8//9// Implementations of integrations implement extra functionality by10// implementing interface extensions. The Integration interface is the most11// basic interface that all integrations must implement. Extensions like12// the MetricsIntegration interface define an integration that supports13// metrics.14//15// Extension interfaces are used by the integrations subsystem to enable16// common use cases. New behaviors can be implemented by manually using17// the other subsystems of the agent provided in IntegrationOptions.18package integrations1920import (21"context"22"fmt"23"net/http"24"net/url"2526"github.com/go-kit/log"27"github.com/grafana/agent/pkg/integrations/v2/autoscrape"28"github.com/grafana/agent/pkg/logs"29"github.com/grafana/agent/pkg/metrics"30"github.com/grafana/agent/pkg/server"31"github.com/grafana/agent/pkg/traces"32"github.com/prometheus/prometheus/discovery"33"github.com/prometheus/prometheus/discovery/targetgroup"34)3536var (37// ErrInvalidUpdate is returned by ApplyConfig when the config cannot38// be dynamically applied.39ErrInvalidUpdate = fmt.Errorf("invalid dynamic update")40)4142// Config provides a configuration and constructor for an integration.43type Config interface {44// Name returns the YAML field name of the integration. Name is used45// when unmarshaling the Config from YAML.46Name() string4748// ApplyDefaults should apply default settings to Config.49ApplyDefaults(Globals) error5051// Identifier returns a string to uniquely identify the integration created52// by this Config. Identifier must be unique for each integration that shares53// the same Name.54//55// If there is no reasonable identifier to use for an integration,56// Globals.AgentIdentifier may be used by default.57Identifier(Globals) (string, error)5859// NewIntegration should return a new Integration using the provided60// Globals to help initialize the Integration.61//62// NewIntegration must be idempotent for a Config. Use63// Integration.RunIntegration to do anything with side effects, such as64// opening a port.65NewIntegration(log.Logger, Globals) (Integration, error)66}6768// ComparableConfig extends Config with an ConfigEquals method.69type ComparableConfig interface {70Config7172// ConfigEquals should return true if c is equal to the ComparableConfig.73ConfigEquals(c Config) bool74}7576// Globals are used to pass around subsystem-wide settings that integrations77// can take advantage of.78type Globals struct {79// AgentIdentifier provides an identifier for the running agent. This can80// be used for labelling whenever appropriate.81//82// AgentIdentifier will be set to the hostname:port of the running agent.83// TODO(rfratto): flag to override identifier at agent level?84AgentIdentifier string8586// Some integrations may wish to interact with various subsystems for their87// implementation if the desired behavior is not supported natively by the88// integration manager.8990Metrics *metrics.Agent // Metrics subsystem91Logs *logs.Logs // Logs subsystem92Tracing *traces.Traces // Traces subsystem9394// Options the integrations subsystem is using.95SubsystemOpts SubsystemOptions96// BaseURL to use to invoke methods against the embedded HTTP server.97AgentBaseURL *url.URL98// Dialer to use for making connections. May be nil.99DialContextFunc server.DialContextFunc100}101102// CloneAgentBaseURL returns a copy of AgentBaseURL that can be modified.103func (g Globals) CloneAgentBaseURL() *url.URL {104if g.AgentBaseURL == nil {105return nil106}107rawURL := g.AgentBaseURL.String()108u, err := url.Parse(rawURL)109if err != nil {110// The URL shouldn't be invalid at this point111panic(err)112}113return u114}115116// An Integration integrates some external system with Grafana Agent's existing117// subsystems.118//119// All integrations must at least implement this interface. More behaviors120// can be added by implementing additional *Integration interfaces, such121// as HTTPIntegration.122type Integration interface {123// RunIntegration starts the integration and performs background tasks. It124// must not return until ctx is canceled, even if there is no work to do.125//126// An error will be returned if the integration failed. Integrations will127// never return the ctx error.128RunIntegration(ctx context.Context) error129}130131// UpdateIntegration is an Integration whose config can be updated132// dynamically. Integrations that do not implement this interface will be shut133// down and re-instantiated with the new Config.134type UpdateIntegration interface {135Integration136137// ApplyConfig should apply the config c to the integration. An error can be138// returned if the Config is invalid. When this happens, the old config will139// continue to run.140//141// If ApplyConfig returns ErrInvalidUpdate, the integration will be142// recreated.143ApplyConfig(c Config, g Globals) error144}145146// HTTPIntegration is an integration that exposes an HTTP handler.147//148// Integrations are given a unique base path prefix where HTTP requests will be149// routed. The prefix chosen for an integration is not guaranteed to be150// predictable.151type HTTPIntegration interface {152Integration153154// Handler returns an http.Handler. Handler will be invoked for any endpoint155// under prefix. If Handler returns nil, nothing will be called. Handler156// may be called multiple times.157//158// prefix will not be removed from the HTTP request by default.159Handler(prefix string) (http.Handler, error)160}161162// MetricsIntegration is an integration that exposes Prometheus scrape targets.163//164// It is assumed, but not required, that HTTPIntegration is also implemented165// to expose metrics. See HTTPIntegration for more information about how166// HTTP works with integrations.167type MetricsIntegration interface {168HTTPIntegration169170// Targets should return the current set of active targets exposed by this171// integration. Targets may be called multiple times throughout the lifecycle172// of the integration. Targets will not be called when the integration is not173// running.174//175// prefix will be the same prefixed passed to HTTPIntegration.Handler and176// can be used to update __metrics_path__ for targets.177Targets(ep Endpoint) []*targetgroup.Group178179// ScrapeConfigs configures automatic scraping of targets. ScrapeConfigs180// is optional if an integration should not scrape itself.181//182// Unlike Targets, ScrapeConfigs is only called once per config load, and may be183// called before the integration runs. Use the provided discovery.Configs to184// discover the targets exposed by this integration.185ScrapeConfigs(discovery.Configs) []*autoscrape.ScrapeConfig186}187188// Endpoint is a location where something is exposed.189type Endpoint struct {190// Hostname (and optional port) where endpoint is exposed.191Host string192// Base prefix of the endpoint.193Prefix string194}195196197