Documentation
¶
Overview ¶
UDProbe Collector sends UDP probes to a set of target reflectors and provides statistics about their latency and reachability via an API.
Functionality for sending and receiving UDP probes on a socket.
portgroup defines PortGroup, which is used to multiplex UDPAddr structs to multiple ports via parallel channels.
Index ¶
- Constants
- func CalcCounts(results []*Result, summary *Summary)
- func CalcLoss(summary *Summary)
- func CalcRTT(results []*Result, summary *Summary)
- func EmitMetricsFromSummaries(summaries []*Summary, t TagSet, setter MetricSetter)
- func EnableTimestamps(conn *net.UDPConn)
- func FileCloseHandler(f *os.File)
- func GetTos(conn *net.UDPConn) byte
- func HandleError(err error)
- func HandleFatalError(err error)
- func HandleFatalErrorMsg(err error, msg string)
- func HandleMinorError(err error)
- func HandleMinorErrorMsg(err error, msg string)
- func IDToBytes(id string) [10]byte
- func LocalUDPAddr(conn *net.UDPConn) (*net.UDPAddr, string, error)
- func LogInfo(msg string)
- func LogWarning(msg string)
- func NewID() string
- func NowUint64() uint64
- func NsToMs(ns float64) float64
- func RTT(probe *InFlightProbe, result *Result) error
- func Receive(data []byte, oob []byte, conn *net.UDPConn) ([]byte, []byte, *net.UDPAddr, error)
- func Reflect(ctx context.Context, conn *net.UDPConn, rl *rate.Limiter)
- func RegisterPrometheus()
- func RegisterReflectorPrometheus()
- func Send(data []byte, tos byte, conn *net.UDPConn, addr *net.UDPAddr) error
- func SetRecvBufferSize(conn *net.UDPConn, size int)
- func SetTos(conn *net.UDPConn, tos byte)
- type API
- type APIConfig
- type Collector
- func (c *Collector) LoadConfig()
- func (c *Collector) Reload()
- func (c *Collector) Run()
- func (c *Collector) Setup()
- func (c *Collector) SetupAPI()
- func (c *Collector) SetupSummarizer()
- func (c *Collector) SetupTagSet()
- func (c *Collector) SetupTestRunner(test TestConfig)
- func (c *Collector) SetupTestRunners()
- func (c *Collector) Stop()
- type CollectorConfig
- type InFlightProbe
- type LegacyCollectorConfig
- type MetricSetter
- type PathDist
- type Port
- type PortConfig
- type PortGroup
- type PortGroupConfig
- type PortGroupsConfig
- type PortsConfig
- type PrometheusMetricSetter
- func (p *PrometheusMetricSetter) SetPacketLoss(labels map[string]string, value float64)
- func (p *PrometheusMetricSetter) SetPacketsLost(labels map[string]string, value float64)
- func (p *PrometheusMetricSetter) SetPacketsSent(labels map[string]string, value float64)
- func (p *PrometheusMetricSetter) SetRTT(labels map[string]string, value float64)
- type RateLimitConfig
- type RateLimitsConfig
- type ReflectorAPI
- type Result
- type ResultHandler
- type SummarizationConfig
- type Summarizer
- type Summary
- type TagSet
- type Tags
- type TargetConfig
- type TargetSet
- type TargetsConfig
- type TestConfig
- type TestRunner
- func (tr *TestRunner) Add(addrs ...*net.UDPAddr)
- func (tr *TestRunner) AddNewPort(portStr string, tos byte, cTimeout time.Duration, cCleanRate time.Duration, ...)
- func (tr *TestRunner) Del(addr *net.UDPAddr)
- func (tr *TestRunner) Run()
- func (tr *TestRunner) Set(targets []*net.UDPAddr)
- func (tr *TestRunner) Stop()
- type TestsConfig
Constants ¶
const ( // Listens on any addr to an automatically assigned port number DefaultAddrStr = "0.0.0.0:0" DefaultTos = byte(0) DefaultRcvBuff = 2097600 // 2MiB DefaultReadTimeout = 200 * time.Millisecond DefaultCacheTimeout = 2 * time.Second DefaultCacheCleanRate = 5 * time.Second ExpireNow = time.Nanosecond )
const DEFAULT_CHANNEL_SIZE int64 = 100 // Default size used for buffered channels.
Variables ¶
This section is empty.
Functions ¶
func CalcCounts ¶
CalcCounts will calculate the Sent and Lost counts on the provided summary, based on the provided results.
func CalcLoss ¶
func CalcLoss(summary *Summary)
CalcLoss will calculate the Loss percentage (out of 1) based on the Sent and Lost vaules of the provided summary.
func CalcRTT ¶
CalcRT will calculate the RTT values for the provided summary, based on the provided results.
func EmitMetricsFromSummaries ¶
func EmitMetricsFromSummaries(summaries []*Summary, t TagSet, setter MetricSetter)
EmitMetricsFromSummaries updates the Prometheus metrics based on the summaries with the necessary tags
func EnableTimestamps ¶
EnableTimestamps enables kernel receive timestamping of packets on the provided conn.
The timestamp values can later be extracted in the oob data from Receive.
func FileCloseHandler ¶
FileCloseHandler will close an open File and handle the resulting error.
func HandleError ¶
func HandleError(err error)
func HandleFatalError ¶
func HandleFatalError(err error)
HandleFatalError receives an error, then logs and exits if not nil.
func HandleFatalErrorMsg ¶
func HandleMinorError ¶
func HandleMinorError(err error)
func HandleMinorErrorMsg ¶
func LocalUDPAddr ¶
LocalUDPAddr returns the UDPAddr and net for the provided UDPConn.
For UDPConn instances, net is generaly 'udp'.
func LogWarning ¶
func LogWarning(msg string)
func NewID ¶
func NewID() string
NewID returns 10 bytes of a new UUID4 as a string.
This should be unique enough for short-lived cases, but as it's only a partial UUID.
func NowUint64 ¶
func NowUint64() uint64
NowUint64 returns the current time in nanoseconds as a uint64.
func RTT ¶
func RTT(probe *InFlightProbe, result *Result) error
RTT calculates the round trip time for a probe and updates the Result.
func Receive ¶
Receive accepts UDP packets on the provided conn and returns the data and and control message slices, as well as the UDPAddr it was received from.
func Reflect ¶
Reflect will listen on the provided UDPConn and will send back any UdpData compliant packets that it receives, in compliance with the RateLimiter.
func RegisterPrometheus ¶
func RegisterPrometheus()
func RegisterReflectorPrometheus ¶
func RegisterReflectorPrometheus()
func SetRecvBufferSize ¶
SetRecvBufferSize sets the size of the receive buffer for the conn to the provided size in bytes.
Types ¶
type API ¶
type API struct {
// contains filtered or unexported fields
}
API represnts the HTTP server answering queries for collected data.
func NewAPI ¶
func NewAPI(s *Summarizer, t TagSet, addr string) *API
New returns an initialized API struct.
func (*API) MergeUpdateTagSet ¶
MergeUpdateTagSet combines a provided TagSet with the existing one
func (*API) PromHandler ¶
PromHandler handles requests for Prometheus metrics.
func (*API) Run ¶
func (api *API) Run()
Run calls RunForever in a separate goroutine for non-blocking behavior.
func (*API) RunForever ¶
func (api *API) RunForever()
RunForever sets up the handlers above and then listens for requests until stopped or a fatal error occurs.
Calling this will block until stopped/crashed.
func (*API) StatusHandler ¶
func (api *API) StatusHandler(rw http.ResponseWriter, request *http.Request)
StatusHandler acts as a back healthcheck and simply returns 200 OK.
type APIConfig ¶
type APIConfig struct {
Bind string `yaml:"bind"`
}
APIConfig describes the parameters for the JSON HTTP API.
type Collector ¶
type Collector struct {
// contains filtered or unexported fields
}
Collector reads a YAML configuration, performs UDP probe tests against targets, and provides summaries of the results via a JSON HTTP API.
func (*Collector) LoadConfig ¶
func (c *Collector) LoadConfig()
LoadConfig loads the collector's configuration from CLI flag if provided, otherwise the default.
func (*Collector) Reload ¶
func (c *Collector) Reload()
Reload causes the config to be reread, and test runners recreated
func (*Collector) Run ¶
func (c *Collector) Run()
Run starts all of the components of the collector and begins testing.
func (*Collector) Setup ¶
func (c *Collector) Setup()
Setup is a generally wrapper around all of the other Setup* functions.
func (*Collector) SetupAPI ¶
func (c *Collector) SetupAPI()
SetupAPI creates and performs initial setup of the API based on the config.
func (*Collector) SetupSummarizer ¶
func (c *Collector) SetupSummarizer()
SetupSummarizer creates the Summarizer and ResultHandlers that will summarize and save the test results, based on the config.
func (*Collector) SetupTagSet ¶
func (c *Collector) SetupTagSet()
SetupTagSet loads the tags for targets, based on the config, that will be applied to summarized results.
func (*Collector) SetupTestRunner ¶
func (c *Collector) SetupTestRunner(test TestConfig)
SetupTestRunner takes parameters from the loaded config, and creates the specified TestConfig.
func (*Collector) SetupTestRunners ¶
func (c *Collector) SetupTestRunners()
SetupTestRunners creates all the `tests` that are defined in the config.
type CollectorConfig ¶
type CollectorConfig struct {
Summarization SummarizationConfig `yaml:"summarization"`
API APIConfig `yaml:"api"`
SrcHostname string `yaml:"src_hostname"`
Ports PortsConfig `yaml:"ports"`
PortGroups PortGroupsConfig `yaml:"port_groups"`
RateLimits RateLimitsConfig `yaml:"rate_limits"`
Tests TestsConfig `yaml:"tests"`
Targets TargetsConfig `yaml:"targets"`
}
CollectorConfig wraps all of the above structs/maps/slices and defines the overall configuration for a collector.
func NewCollectorConfig ¶
func NewCollectorConfig(data []byte) (*CollectorConfig, error)
NewCollectorConfig provides a parsed CollectorConfig based on the provided data.
`data` is expected to be a byte slice version of a YAML CollectorConfig.
func NewDefaultCollectorConfig ¶
func NewDefaultCollectorConfig() (*CollectorConfig, error)
NewDefaultCollectorConfig provides a sensible default collector config.
type InFlightProbe ¶
InFlightProbe represents a single UDP probe that was sent from, and (hopefully) received back, a Port.
func IfaceToInFlightProbe ¶
func IfaceToInFlightProbe(iface interface{}) (*InFlightProbe, error)
IfaceToInFlightProbe attempts to convert an anonymous object to a InFlightProbe, and returns and error if the operation failed.
type LegacyCollectorConfig ¶
LegacyCollectorConfig is for backward compatibility with the existing UDProbe config and represents only a map of targets to tags.
func NewLegacyCollectorConfig ¶
func NewLegacyCollectorConfig(data []byte) (*LegacyCollectorConfig, error)
NewLegacyCollectorConfig creates a new LegacyCollectorConfig struct based on the provided data, which is expected to be a YAML representation of the config.
func (*LegacyCollectorConfig) ToDefaultCollectorConfig ¶
func (legacy *LegacyCollectorConfig) ToDefaultCollectorConfig(port int64) (*CollectorConfig, error)
ToDefaultCollectorConfig converts a LegacyCollectorConfig to CollectorConfig by merging with the defaults and applying the provided port on targets.
type MetricSetter ¶
type MetricSetter interface {
SetPacketLoss(labels map[string]string, value float64)
SetPacketsSent(labels map[string]string, value float64)
SetPacketsLost(labels map[string]string, value float64)
SetRTT(labels map[string]string, value float64)
}
Interface for setting metrics. Should make it easier to test.
type PathDist ¶
type PathDist struct {
SrcIP net.IP
SrcPort int
DstIP net.IP
DstPort int
Proto string // 'udp' generally
}
PathDist -> Path Distinguisher, uniquely IDs the components that determine path selection.
type Port ¶
type Port struct {
// contains filtered or unexported fields
}
Port represents a socket and its associated caching, inputs, and outputs.
func NewDefault ¶
func NewDefault(tosend chan *net.UDPAddr, stop chan bool, cbc chan *InFlightProbe, ) *Port
NewDefault creates a new Port using default settings.
func NewPort ¶
func NewPort(conn *net.UDPConn, tosend chan *net.UDPAddr, stop chan bool, cbc chan *InFlightProbe, cTimeout time.Duration, cCleanRate time.Duration, readTimeout time.Duration, ) *Port
New creates and returns a new Port with associated inputs, outputs, and caching mechanisms.
func (*Port) Recv ¶
func (p *Port) Recv()
Recv listens on the Port for returning probes and updates them in the cache.
Once probes are received, they are located in the cache, updated, and then set for immediate expiration. If a probe is received but has no entry in the cache, it most likely exceeded the timeout.
func (*Port) Send ¶
func (p *Port) Send()
Send waits to get UDPAddr targets and sends probes to them using the associated Port.
After sending the probe, it is added to a cache with a unique ID, which is used for retrieving later. The cache will also utilize a timeout to expire probes that haven't returned in time.
type PortConfig ¶
type PortConfig struct {
IP string `yaml:"ip"`
Port int64 `yaml:"port"`
Tos int64 `yaml:"tos"`
Timeout int64 `yaml:"timeout"`
}
PortConfig describes the configuration for a single Port.
type PortGroup ¶
type PortGroup struct {
// contains filtered or unexported fields
}
func NewPortGroup ¶
func NewPortGroup(stop chan bool, cbc chan *InFlightProbe, tosend chan *net.UDPAddr) *PortGroup
New creates a new PortGroup utilizing a set of input, output, and signalling channels.
stop is used to signal stopping of the PortGroup and all ports. cbc is used as a callback for completed or timedout probes from all ports. tosend is used to receive UDPAddr targets for sending to probes, and is muxed across all Ports in the PortGroup.
func (*PortGroup) Add ¶
Add will add a Port and channel to the PortGroup.
Panics if called after Run() has been called.
func (*PortGroup) AddNew ¶
func (pg *PortGroup) AddNew(portStr string, tos byte, cTimeout time.Duration, cCleanRate time.Duration, readTimeout time.Duration) ( *Port, chan *net.UDPAddr)
AddNew will create a new Port and add it to the PortGroup via Add.
func (*PortGroup) Del ¶
Del removes a Port from the PortGroup.
Panics if called after Run() has been called.
func (*PortGroup) Run ¶
func (pg *PortGroup) Run()
Run will start sending/receiving on all Ports in the PortGroup, and then then loop muxing inbound UDPAddrs to all ports until stopped.
Once Run() is called, Add() and Del() will panic if called.
TODO(nwinemiller): Allow an arg for starting multiple goroutines? Otherwise
leave that to higher level stuff.
type PortGroupConfig ¶
type PortGroupConfig struct {
Port string `yaml:"port"` // Should correspond with a PortsConfig key
Count int64 `yaml:"count"`
}
PortGroupConfig describes a set of identical Ports in a PortGroup.
type PortGroupsConfig ¶
type PortGroupsConfig map[string][]PortGroupConfig
PortGroupsConfig is a mapping of port group "name" to PortGroupConfigs.
func (PortGroupsConfig) Exists ¶
func (pgc PortGroupsConfig) Exists(name string) bool
Exists checks if a PortGroup with the given name exists.
type PortsConfig ¶
type PortsConfig map[string]PortConfig
PortsConfig is a mapping of port "name" to a PortConfig.
func (PortsConfig) Exists ¶
func (pc PortsConfig) Exists(name string) bool
Exists checks if a Port with the given name exists.
type PrometheusMetricSetter ¶
type PrometheusMetricSetter struct{}
func (*PrometheusMetricSetter) SetPacketLoss ¶
func (p *PrometheusMetricSetter) SetPacketLoss(labels map[string]string, value float64)
func (*PrometheusMetricSetter) SetPacketsLost ¶
func (p *PrometheusMetricSetter) SetPacketsLost(labels map[string]string, value float64)
func (*PrometheusMetricSetter) SetPacketsSent ¶
func (p *PrometheusMetricSetter) SetPacketsSent(labels map[string]string, value float64)
type RateLimitConfig ¶
type RateLimitConfig struct {
CPS float64 `yaml:"cps"` // Cycles per second
}
RateLimitConfig describes the configuration for a rate limiter.
type RateLimitsConfig ¶
type RateLimitsConfig map[string]RateLimitConfig
RateLimitsConfig is a mapping of "name" to RateLimitConfig.
func (RateLimitsConfig) Exists ¶
func (rlc RateLimitsConfig) Exists(name string) bool
Exists checks if a RateLimit with the given name exists.
type ReflectorAPI ¶
type ReflectorAPI struct {
// contains filtered or unexported fields
}
func NewReflectorAPI ¶
func NewReflectorAPI(bind string) *ReflectorAPI
func (*ReflectorAPI) PromHandler ¶
func (api *ReflectorAPI) PromHandler() http.Handler
func (*ReflectorAPI) Run ¶
func (api *ReflectorAPI) Run()
func (*ReflectorAPI) StatusHandler ¶
func (api *ReflectorAPI) StatusHandler(w http.ResponseWriter, r *http.Request)
func (*ReflectorAPI) Stop ¶
func (api *ReflectorAPI) Stop()
type Result ¶
type Result struct {
Pd *PathDist // Characteristics that make this path unique
RTT uint64 // Round trip time in nanoseconds
Done uint64 // When the test completed (was received by Port) in ns
Lost bool // If the Probe was lost and never actually completed
Tos byte // ToS value for the probe
}
Result defines characteristics of a single completed Probe.
func Process ¶
func Process(probe *InFlightProbe) *Result
Process takes in a probe, performs calculations on it, and returns a Result.
type ResultHandler ¶
type ResultHandler struct {
// contains filtered or unexported fields
}
ResultHandler is a post-processor for Probes and converts them to Results.
func NewResultHandler ¶
func NewResultHandler(in chan *InFlightProbe, out chan *Result) *ResultHandler
New creates a new ResultHandler that utilizes the provided in and out channels.
func (*ResultHandler) Run ¶
func (rh *ResultHandler) Run()
Run will start the ResultHandler in a new goroutine, and cause it to forever receive Probes, process them and pass their results out.
type SummarizationConfig ¶
type SummarizationConfig struct {
Interval int64 `yaml:"interval"`
Handlers int64 `yaml:"handlers"`
}
SummarizationConfig describes the parameters for setting up a Summarizer and related ResultHandlers.
type Summarizer ¶
type Summarizer struct {
// NOTE(nwinemiller): For posterity, use value references for mutexes, not pointers
CMutex sync.RWMutex
Cache []*Summary
// contains filtered or unexported fields
}
Summarizer stores results and summarizes them at intervals.
func NewSummarizer ¶
func NewSummarizer(in chan *Result, interval time.Duration) *Summarizer
New returns a new Summarizer, based on the provided parameters.
func (*Summarizer) Run ¶
func (s *Summarizer) Run()
Run causes the summarizer to infinitely wait for new results, store them, and then summarize at an interval.
When results are summarized, they are removed and won't be summarized again.
func (*Summarizer) Stop ¶
func (s *Summarizer) Stop()
Stop will stop the summarizer from receiving results or summarizing them.
type Summary ¶
type Summary struct {
Pd *PathDist
RTTAvg float64
RTTMin float64
RTTMax float64
Sent int
Lost int
Loss float64
Tos byte
TS time.Time // No longer used, but keeping for posterity
}
Summary represents summaried results and statistics about them.
type TagSet ¶
TagSet is a collection of Tags, indexed by a key (e.g., an IP address).
To avoid panics when setting tags on a new key, use the Set method:
ts := make(TagSet)
ts.Set("1.2.3.4", "dst_hostname", "localhost")
type Tags ¶
Tags is a map of attributes and values.
It is defined as a type alias to map[string]string to allow seamless integration with other string maps (like prometheus.Labels) without needing explicit type conversions.
type TargetConfig ¶
TargetConfig describes a single target for testing, including tags that are applied to the resulting summaries.
func (*TargetConfig) AddrString ¶
func (tc *TargetConfig) AddrString() string
AddrString converts the tc into a string formated "IP:port" combo.
func (*TargetConfig) ResolveUDPAddr ¶
func (tc *TargetConfig) ResolveUDPAddr() (*net.UDPAddr, error)
ResolveUDPAddr converts the tc into a net.UDPAddr pointer.
type TargetSet ¶
type TargetSet []TargetConfig
TargetSet is a slice of TargetConfig structs.
func (TargetSet) IntoTagSet ¶
IntoTagSet is similar to TagSet but updates the provided tagset instead of creating a new one.
If a tag key already exists with a different value, a warning is logged identifying the conflict. This can occur when the same IP appears in multiple TargetSets with different tag values for the same key.
func (TargetSet) ListResolvedTargets ¶
ListResolvedTargets provides a slice of net.UDPAddr pointers for all of the targets in the ts, and will return with an error as soon as one is hit.
func (TargetSet) ListTargets ¶
ListTargets provides a slice of "IP:port" string representations for all of the targets in the ts.
type TargetsConfig ¶
TargetsConfig is a mapping of "name" to TargetSet slice.
func (TargetsConfig) Exists ¶
func (tc TargetsConfig) Exists(name string) bool
Exists checks if a TargetSet with the given name exists.
func (TargetsConfig) IntoTagSet ¶
func (tc TargetsConfig) IntoTagSet(ts TagSet, srcHostname string)
IntoTagSet is a wrapper about the same function for each contained TargetSet and merges them into an existing ts.
func (TargetsConfig) TagSet ¶
func (tc TargetsConfig) TagSet(srcHostname string) TagSet
TagSet is a wrapper, and merges the TagSet output for all TargetSet slices within the tc.
NOTE: If the same IP appears in multiple TargetSets with different tag values for the same key, a warning is logged and the last TargetSet's values win.
type TestConfig ¶
type TestConfig struct {
Targets string `yaml:"targets"` // Should correspond with a TargetsConfig key
PortGroup string `yaml:"port_group"` // Should correspond with a PortGroupsConfig key
RateLimit string `yaml:"rate_limit"` // Should correspond with a RateLimitsConfig key
}
TestConfig describes the elements of a test, for use by TestRunner, which correspond to their respective named elements in the config.
Ex. A `targets` value of "default" in the config would correspond to a TargetsConfig key of "default" which contains the definitions of targets.
type TestRunner ¶
type TestRunner struct {
// contains filtered or unexported fields
}
TestRunner repeatedly runs through a list of targets and passes them down to a PortGroup for processing.
func NewTestRunner ¶
func NewTestRunner(cbc chan *InFlightProbe, rl *rate.Limiter) *TestRunner
New creates and returns a new TestRunner instance.
`cbc` is a channel for accepting completed Probes. `rl` is a rate limiter which is used to throttle the number of cycles that may be completed per second.
func (*TestRunner) Add ¶
func (tr *TestRunner) Add(addrs ...*net.UDPAddr)
Add will add a variable number of addrs to the slice of targets for processing.
NOTE: This will block during cycles. So it should be avoided when possible.
It's better to just use `Set` to replace the whole thing. Either way, this change will only go into effect between cycles.
func (*TestRunner) AddNewPort ¶
func (tr *TestRunner) AddNewPort(portStr string, tos byte, cTimeout time.Duration, cCleanRate time.Duration, readTimeout time.Duration)
AddNewPort will add a new Port to the TestRunner's PortGroup.
See PortGroup.AddNew for more details on these arguments.
NOTE: This is basically just a passthrough for PortGroup.AddNew until
the pattern is better understood and this can be cleaned up.
func (*TestRunner) Del ¶
func (tr *TestRunner) Del(addr *net.UDPAddr)
Del will remove all occurrences of a target addr from the slice of targets.
NOTE: This will block during cycles. It will also take longer as the
number of targets increases. So it should be avoided when possible. It's better to just use `Set` to replace the whole thing. Either way, this change will only go into effect between cycles.
func (*TestRunner) Run ¶
func (tr *TestRunner) Run()
Run starts the TestRunner and begins cycling through targets.
func (*TestRunner) Set ¶
func (tr *TestRunner) Set(targets []*net.UDPAddr)
Set will replace the current slice of targets with the provided one.
NOTE: This will block during cycles. It is generally advised to use `Set`
over `Add` and `Del` in making larger changes or operating on multiple targets. It's just more atomic.
func (*TestRunner) Stop ¶
func (tr *TestRunner) Stop()
Stop will stop the TestRunner after the current cycle and any underlying PortGroup and Port(s).