metrics

package
v0.0.0-...-e3e60e4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 27, 2023 License: AGPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package metrics contains various k6 components that deal with metrics and thresholds.

Index

Constants

View Source
const (
	VUsName               = "vus" //nolint:revive
	VUsMaxName            = "vus_max"
	IterationsName        = "iterations"
	IterationDurationName = "iteration_duration"
	DroppedIterationsName = "dropped_iterations"

	ChecksName        = "checks"
	GroupDurationName = "group_duration"

	HTTPReqsName              = "http_reqs"
	HTTPReqFailedName         = "http_req_failed"
	HTTPReqDurationName       = "http_req_duration"
	HTTPReqBlockedName        = "http_req_blocked"
	HTTPReqConnectingName     = "http_req_connecting"
	HTTPReqTLSHandshakingName = "http_req_tls_handshaking"
	HTTPReqSendingName        = "http_req_sending"
	HTTPReqWaitingName        = "http_req_waiting"
	HTTPReqReceivingName      = "http_req_receiving"

	WSSessionsName         = "ws_sessions"
	WSMessagesSentName     = "ws_msgs_sent"
	WSMessagesReceivedName = "ws_msgs_received"
	WSPingName             = "ws_ping"
	WSSessionDurationName  = "ws_session_duration"
	WSConnectingName       = "ws_connecting"

	GRPCReqDurationName = "grpc_req_duration"

	DataSentName     = "data_sent"
	DataReceivedName = "data_received"
)
View Source
const (
	Counter = MetricType(iota) // A counter that sums its data points
	Gauge                      // A gauge that displays the latest value
	Trend                      // A trend, min/max/avg/med are interesting
	Rate                       // A rate, displays % of values that aren't 0
)

Possible values for MetricType.

View Source
const (
	Default = ValueType(iota) // Values are presented as-is
	Time                      // Values are timestamps (nanoseconds)
	Data                      // Values are data amounts (bytes)
)

Possible values for ValueType.

Variables

DefaultSystemTagSet includes all of the system tags emitted with metrics by default. Other tags that are not enabled by default include: iter, vu, ocsp_status, ip

View Source
var ErrInvalidMetricType = errors.New("invalid metric type")

ErrInvalidMetricType indicates the serialized metric type is invalid.

View Source
var ErrInvalidThreshold = errors.New("invalid threshold")

ErrInvalidThreshold indicates a threshold is not valid

View Source
var ErrInvalidValueType = errors.New("invalid value type")

ErrInvalidValueType indicates the serialized value type is invalid.

View Source
var ErrMetricNameParsing = errors.New("parsing metric name failed")

ErrMetricNameParsing indicates parsing a metric name failed

View Source
var NonIndexableSystemTags = SystemTagSet(TagIter | TagVU)

NonIndexableSystemTags are high cardinality system tags (i.e. metadata).

Functions

func B

func B(b bool) float64

B formats a boolean value for emission.

func D

func D(d time.Duration) float64

D formats a duration for emission. The reverse of D() is ToD().

func GetResolversForTrendColumns

func GetResolversForTrendColumns(trendColumns []string) (map[string]func(s *TrendSink) float64, error)

GetResolversForTrendColumns checks if passed trend columns are valid for use in the summary output and then returns a map of the corresponding resolvers.

func MarshalJSONWithoutHTMLEscape

func MarshalJSONWithoutHTMLEscape(t interface{}) ([]byte, error)

MarshalJSONWithoutHTMLEscape marshals t to JSON without escaping characters for safe use in HTML.

func ParseMetricName

func ParseMetricName(name string) (string, []string, error)

ParseMetricName parses a metric name expression of the form metric_name{tag_key:tag_value,...} Its first return value is the parsed metric name, second are parsed tags as as slice of "key:value" strings. On failure, it returns an error containing the `ErrMetricNameParsing` in its chain.

func PushIfNotDone

func PushIfNotDone(ctx context.Context, output chan<- SampleContainer, sample SampleContainer) bool

PushIfNotDone first checks if the supplied context is done and doesn't push the sample container if it is.

func ToD

func ToD(d float64) time.Duration

ToD converts an emitted duration to a time.Duration. The reverse of ToD() is D().

Types

type BuiltinMetrics

type BuiltinMetrics struct {
	VUs               *Metric
	VUsMax            *Metric
	Iterations        *Metric
	IterationDuration *Metric
	DroppedIterations *Metric

	// Runner-emitted.
	Checks        *Metric
	GroupDuration *Metric

	// HTTP-related.
	HTTPReqs              *Metric
	HTTPReqFailed         *Metric
	HTTPReqDuration       *Metric
	HTTPReqBlocked        *Metric
	HTTPReqConnecting     *Metric
	HTTPReqTLSHandshaking *Metric
	HTTPReqSending        *Metric
	HTTPReqWaiting        *Metric
	HTTPReqReceiving      *Metric

	// Websocket-related
	WSSessions         *Metric
	WSMessagesSent     *Metric
	WSMessagesReceived *Metric
	WSPing             *Metric
	WSSessionDuration  *Metric
	WSConnecting       *Metric

	// gRPC-related
	GRPCReqDuration *Metric

	// Network-related; used for future protocols as well.
	DataSent     *Metric
	DataReceived *Metric
}

BuiltinMetrics represent all the builtin metrics of k6

func RegisterBuiltinMetrics

func RegisterBuiltinMetrics(registry *Registry) *BuiltinMetrics

RegisterBuiltinMetrics register and returns the builtin metrics in the provided registry

type ConnectedSampleContainer

type ConnectedSampleContainer interface {
	SampleContainer
	GetTags() *TagSet
	GetTime() time.Time
}

ConnectedSampleContainer is an extension of the SampleContainer interface that should be implemented when emitted samples are connected and share the same time and tags.

type ConnectedSamples

type ConnectedSamples struct {
	Samples []Sample
	Tags    *TagSet
	Time    time.Time
}

ConnectedSamples is the simplest ConnectedSampleContainer implementation that will be used when there's no need for extra information

func (ConnectedSamples) GetSamples

func (cs ConnectedSamples) GetSamples() []Sample

GetSamples implements the SampleContainer and ConnectedSampleContainer interfaces and returns the stored slice with samples.

func (ConnectedSamples) GetTags

func (cs ConnectedSamples) GetTags() *TagSet

GetTags implements ConnectedSampleContainer interface and returns stored tags.

func (ConnectedSamples) GetTime

func (cs ConnectedSamples) GetTime() time.Time

GetTime implements ConnectedSampleContainer interface and returns stored time.

type CounterSink

type CounterSink struct {
	Value float64
	First time.Time
}

func (*CounterSink) Add

func (c *CounterSink) Add(s Sample)

func (*CounterSink) Format

func (c *CounterSink) Format(t time.Duration) map[string]float64

func (*CounterSink) IsEmpty

func (c *CounterSink) IsEmpty() bool

IsEmpty indicates whether the CounterSink is empty.

type DummySink

type DummySink map[string]float64

func (DummySink) Add

func (d DummySink) Add(s Sample)

func (DummySink) Format

func (d DummySink) Format(t time.Duration) map[string]float64

func (DummySink) IsEmpty

func (d DummySink) IsEmpty() bool

IsEmpty indicates whether the DummySink is empty.

type EnabledTags

type EnabledTags map[string]bool

EnabledTags is a string to bool map (for lookup efficiency) that is used to keep track of which system tags and non-system tags to include.

TODO: move to types.StringSet or something like that, this isn't metrics specific

func (*EnabledTags) MarshalJSON

func (i *EnabledTags) MarshalJSON() ([]byte, error)

MarshalJSON converts the EnabledTags to a list (JS array).

func (*EnabledTags) UnmarshalJSON

func (i *EnabledTags) UnmarshalJSON(data []byte) error

UnmarshalJSON converts the tag list back to expected tag set.

func (*EnabledTags) UnmarshalText

func (i *EnabledTags) UnmarshalText(data []byte) error

UnmarshalText converts the tag list to EnabledTags.

type GaugeSink

type GaugeSink struct {
	Value    float64
	Max, Min float64
	// contains filtered or unexported fields
}

func (*GaugeSink) Add

func (g *GaugeSink) Add(s Sample)

func (*GaugeSink) Format

func (g *GaugeSink) Format(t time.Duration) map[string]float64

func (*GaugeSink) IsEmpty

func (g *GaugeSink) IsEmpty() bool

IsEmpty indicates whether the GaugeSink is empty.

type Metric

type Metric struct {
	Name     string     `json:"name"`
	Type     MetricType `json:"type"`
	Contains ValueType  `json:"contains"`

	// TODO: decouple the metrics from the sinks and thresholds... have them
	// linked, but not in the same struct?
	Tainted    null.Bool    `json:"tainted"`
	Thresholds Thresholds   `json:"thresholds"`
	Submetrics []*Submetric `json:"submetrics"`
	Sub        *Submetric   `json:"-"`
	Sink       Sink         `json:"-"`
	Observed   bool         `json:"-"`
	// contains filtered or unexported fields
}

A Metric defines the shape of a set of data.

func (*Metric) AddSubmetric

func (m *Metric) AddSubmetric(keyValues string) (*Submetric, error)

AddSubmetric creates a new submetric from the key:value threshold definition and adds it to the metric's submetrics list.

type MetricType

type MetricType int

A MetricType specifies the type of a metric.

func (MetricType) MarshalJSON

func (t MetricType) MarshalJSON() ([]byte, error)

MarshalJSON serializes a MetricType as a human readable string.

func (MetricType) MarshalText

func (t MetricType) MarshalText() ([]byte, error)

MarshalText serializes a MetricType as a human readable string.

func (MetricType) String

func (t MetricType) String() string

func (*MetricType) UnmarshalText

func (t *MetricType) UnmarshalText(data []byte) error

UnmarshalText deserializes a MetricType from a string representation.

type RateSink

type RateSink struct {
	Trues int64
	Total int64
}

func (*RateSink) Add

func (r *RateSink) Add(s Sample)

func (RateSink) Format

func (r RateSink) Format(t time.Duration) map[string]float64

func (*RateSink) IsEmpty

func (r *RateSink) IsEmpty() bool

IsEmpty indicates whether the RateSink is empty.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry is what can create metrics

func NewRegistry

func NewRegistry() *Registry

NewRegistry returns a new registry

func (*Registry) Get

func (r *Registry) Get(name string) *Metric

Get returns the Metric with the given name. If that metric doesn't exist, Get() will return a nil value.

func (*Registry) MustNewMetric

func (r *Registry) MustNewMetric(name string, typ MetricType, t ...ValueType) *Metric

MustNewMetric is like NewMetric, but will panic if there is an error

func (*Registry) NewMetric

func (r *Registry) NewMetric(name string, typ MetricType, t ...ValueType) (*Metric, error)

NewMetric returns new metric registered to this registry TODO have multiple versions returning specific metric types when we have such things

func (*Registry) RootTagSet

func (r *Registry) RootTagSet() *TagSet

RootTagSet is the empty root set that all other TagSets must originate from.

type Sample

type Sample struct {
	TimeSeries
	Time  time.Time
	Value float64

	// Optional high-cardinality metadata that won't be indexed in atlas.
	//
	// It can be nil if it wasn't explicitly specified, reduce memory
	// allocations and GC overhead.
	Metadata map[string]string
}

A Sample is a single metric measurement at a specific point in time. It can have two sets of string key=value metadata:

  • indexed Tags for low-cardinality data that are part of the TimeSeries
  • optional non-indexed Metadata that are meant for high-cardinality information

func (Sample) GetSamples

func (s Sample) GetSamples() []Sample

GetSamples implement the ConnectedSampleContainer interface for a single Sample, since it's obviously connected with itself :)

func (Sample) GetTags

func (s Sample) GetTags() *TagSet

GetTags implements ConnectedSampleContainer interface and returns the sample's tags.

func (Sample) GetTime

func (s Sample) GetTime() time.Time

GetTime just implements ConnectedSampleContainer interface and returns the sample's time.

type SampleContainer

type SampleContainer interface {
	GetSamples() []Sample
}

SampleContainer is a simple abstraction that allows sample producers to attach extra information to samples they return

func GetBufferedSamples

func GetBufferedSamples(input <-chan SampleContainer) (result []SampleContainer)

GetBufferedSamples will read all present (i.e. buffered or currently being pushed) values in the input channel and return them as a slice.

type Samples

type Samples []Sample

Samples is just the simplest SampleContainer implementation that will be used when there's no need for extra information

func (Samples) GetSamples

func (s Samples) GetSamples() []Sample

GetSamples just implements the SampleContainer interface

type Sink

type Sink interface {
	Add(s Sample)                              // Add a sample to the sink.
	Format(t time.Duration) map[string]float64 // Data for thresholds.
	IsEmpty() bool                             // Check if the Sink is empty.
}

type Submetric

type Submetric struct {
	Name   string  `json:"name"`
	Suffix string  `json:"suffix"` // TODO: rename?
	Tags   *TagSet `json:"tags"`

	Metric *Metric `json:"-"`
	Parent *Metric `json:"-"`
}

A Submetric represents a filtered dataset based on a parent metric.

type SystemTag

type SystemTag uint32

SystemTag values are bit-shifted identifiers of all of the various system tags that k6 has.

const (
	TagProto SystemTag = 1 << iota
	TagSubproto
	TagStatus
	TagMethod
	TagURL
	TagName
	TagGroup
	TagCheck
	TagError
	TagErrorCode
	TagTLSVersion
	TagScenario
	TagService
	TagExpectedResponse

	// System tags not enabled by default.
	TagIter // non-indexable
	TagVU   // non-indexable
	TagOCSPStatus
	TagIP
)

Default system tags includes all of the system tags emitted with metrics by default.

func SystemTagString

func SystemTagString(s string) (SystemTag, error)

SystemTagString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.

func SystemTagValues

func SystemTagValues() []SystemTag

SystemTagValues returns all values of the enum

func (SystemTag) IsASystemTag

func (i SystemTag) IsASystemTag() bool

IsASystemTag returns "true" if the value is listed in the enum definition. "false" otherwise

func (SystemTag) String

func (i SystemTag) String() string

type SystemTagSet

type SystemTagSet SystemTag

SystemTagSet is a bitmask that is used to keep track which system tags should be included in metric Samples.

func NewSystemTagSet

func NewSystemTagSet(tags ...SystemTag) *SystemTagSet

NewSystemTagSet returns a SystemTagSet from input.

func ToSystemTagSet

func ToSystemTagSet(tags []string) *SystemTagSet

ToSystemTagSet converts list of tags to SystemTagSet TODO: emit error instead of discarding invalid values.

func (*SystemTagSet) Add

func (i *SystemTagSet) Add(tag SystemTag)

Add adds a tag to tag set.

func (*SystemTagSet) Has

func (i *SystemTagSet) Has(tag SystemTag) bool

Has checks a tag included in tag set.

func (SystemTagSet) Map

func (i SystemTagSet) Map() EnabledTags

Map returns the EnabledTags with current value from SystemTagSet

func (*SystemTagSet) MarshalJSON

func (i *SystemTagSet) MarshalJSON() ([]byte, error)

MarshalJSON converts the SystemTagSet to a list (JS array).

func (SystemTagSet) SetString

func (i SystemTagSet) SetString() string

SetString returns comma separated list of the string representation of all values in the set

func (*SystemTagSet) UnmarshalJSON

func (i *SystemTagSet) UnmarshalJSON(data []byte) error

UnmarshalJSON converts the tag list back to expected tag set.

func (*SystemTagSet) UnmarshalText

func (i *SystemTagSet) UnmarshalText(data []byte) error

UnmarshalText converts the tag list to SystemTagSet.

type TagSet

type TagSet atlas.Node

A TagSet represents an immutable set of metric tags. For the efficient and thread-safe storage of the key=value tag pairs, it uses the https://github.com/mstoykov/atlas data structure.

Assuming all tag sets start from the same root (see Registry.RootTagSet()), you can compare *TagSet values of different metric Samples with the `==` Go operator to check if they have the same tags, and you can also use *TagSet values for map indexes and caching.

See also the TimeSeries type for comparing a Sample's {metric+tags} for equality at the same time.

func (*TagSet) Contains

func (ts *TagSet) Contains(other *TagSet) bool

Contains checks that each key=value tag pair in the provided TagSet exists in the receiver tag set as well, i.e. that the given set is a sub-set of it.

func (*TagSet) Get

func (ts *TagSet) Get(name string) (string, bool)

Get returns the value of the tag with the given name and true, if that tag exists in the set, and an empty string and false otherwise.

func (*TagSet) IsEmpty

func (ts *TagSet) IsEmpty() bool

IsEmpty checks if the tag set is empty, i.e. if it's the root atlas node.

func (*TagSet) Map

func (ts *TagSet) Map() map[string]string

Map returns a {key: value} string map with all of the tags in the set.

func (*TagSet) MarshalEasyJSON

func (ts *TagSet) MarshalEasyJSON(w *jwriter.Writer)

MarshalEasyJSON supports easyjson.Marshaler interface for better performance.

func (*TagSet) MarshalJSON

func (ts *TagSet) MarshalJSON() ([]byte, error)

MarshalJSON serializes the tags to a JSON string.

func (*TagSet) UnmarshalEasyJSON

func (ts *TagSet) UnmarshalEasyJSON(l *jlexer.Lexer)

UnmarshalEasyJSON WILL ALWAYS RETURN AN ERROR because a TagSet needs to be started from a common atlas root. This function exists to prevent any automatic reflection-based attempts at unmarshaling.

func (*TagSet) UnmarshalJSON

func (ts *TagSet) UnmarshalJSON([]byte) error

UnmarshalJSON WILL ALWAYS RETURN AN ERROR because a TagSet needs to be started from a common atlas root. This function exists to prevent any automatic reflection-based attempts at unmarshaling.

func (*TagSet) With

func (ts *TagSet) With(name, value string) *TagSet

With returns another TagSet object that contains the combination of the current receiver tags and the name=value tag from its parameters.

It doesn't modify the receiver, it will either return an already existing TagSet with these tags, if it exists, or create a new TagSet with them and return it.

If a tag with the specified name already exists in the set, it will be overwritten with the new value in the returned set.

func (*TagSet) WithTagsFromMap

func (ts *TagSet) WithTagsFromMap(m map[string]string) *TagSet

WithTagsFromMap sorts the given tags by their keys and adds them to the current tag set one by one, without branching out. This is generally discouraged and sequential usage of the TagSet.With() method should be preferred and used in a consistent sequence, whenever possible.

The only place this method should be used is if we already have a map[string]string of tags, e.g. with the test-wide --tags from the root, with scenario.tags, with custom per-request tags from a user, etc. Then it's more efficient to sort their keys before we add them. If we don't, go map iteration happens in pseudo-random order and this will generate a lot of useless dead-end atlas Nodes on multiple TagSet accretions.

func (*TagSet) Without

func (ts *TagSet) Without(name string) *TagSet

Without returns another TagSet object that contains all of the tags from the existing TagSet except the one with the given key.

It doesn't modify the receiver, it will either return an already existing TagSet with these tags, if it exists, or create a new TagSet with them and return it.

If a tag with the specified name doesn't exist in the set, it will return the receiver.

type TagsAndMeta

type TagsAndMeta struct {
	Tags     *TagSet
	Metadata map[string]string // could be nil
}

TagsAndMeta is a helper type that provides easy group manipulation of the indexed Tags and the non-indexed Metadata values together. While both of them are part of a metric Sample, the TagsAndMeta type isn't used there because the Tags participate in the Sample's TimeSeries and the Metadata does not.

Instead, this type is mostly used by the VU and JS code while it assembles the final consolidated Tags and Metadata values to put in the Sample.

IMPORTANT: this data structure is not thread safe! The methods of the lib.VUStateTags type are where the synchronization happens.

func (TagsAndMeta) Clone

func (tm TagsAndMeta) Clone() TagsAndMeta

Clone makes a complete copy of the current TagsAndMeta object and returns it.

func (*TagsAndMeta) DeleteMetadata

func (tm *TagsAndMeta) DeleteMetadata(key string)

DeleteMetadata removes the given key from metadata.

func (*TagsAndMeta) DeleteTag

func (tm *TagsAndMeta) DeleteTag(key string)

DeleteTag removes the given key from tags.

func (*TagsAndMeta) SetMetadata

func (tm *TagsAndMeta) SetMetadata(key, value string)

SetMetadata adds the given key=value datum to the Metadata.

func (*TagsAndMeta) SetSystemTagOrMeta

func (tm *TagsAndMeta) SetSystemTagOrMeta(tag SystemTag, value string)

SetSystemTagOrMeta automatically adds the system tag either as an indexed tag or an unindexed one (metadata), based on the NonIndexableSystemTags set.

func (*TagsAndMeta) SetSystemTagOrMetaIfEnabled

func (tm *TagsAndMeta) SetSystemTagOrMetaIfEnabled(enabledSystemTags *SystemTagSet, tag SystemTag, value string)

SetSystemTagOrMetaIfEnabled checks if the supplied SystemTag is enabled in this test run (i.e. is in the SystemTagSet) and passes it to SetSystemTagOrMeta() if it is.

func (*TagsAndMeta) SetTag

func (tm *TagsAndMeta) SetTag(key, value string)

SetTag adds the given key=value tag to the Tags.

type Threshold

type Threshold struct {
	// Source is the text based source of the threshold
	Source string
	// LastFailed is a marker if the last testing of this threshold failed
	LastFailed bool
	// AbortOnFail marks if a given threshold fails that the whole test should be aborted
	AbortOnFail bool
	// AbortGracePeriod is a the minimum amount of time a test should be running before a failing
	// this threshold will abort the test
	AbortGracePeriod types.NullDuration
	// contains filtered or unexported fields
}

Threshold is a representation of a single threshold for a single metric

type Thresholds

type Thresholds struct {
	Thresholds []*Threshold
	Abort      bool
	// contains filtered or unexported fields
}

Thresholds is the combination of all Thresholds for a given metric

func NewThresholds

func NewThresholds(sources []string) Thresholds

NewThresholds returns Thresholds objects representing the provided source strings

func (Thresholds) MarshalJSON

func (ts Thresholds) MarshalJSON() ([]byte, error)

MarshalJSON is implementation of json.Marshaler

func (*Thresholds) Parse

func (ts *Thresholds) Parse() error

Parse parses the Thresholds and fills each Threshold.parsed field with the result. It effectively asserts they are syntaxically correct.

func (*Thresholds) Run

func (ts *Thresholds) Run(sink Sink, duration time.Duration) (bool, error)

Run processes all the thresholds with the provided Sink at the provided time and returns if any of them fails

func (*Thresholds) UnmarshalJSON

func (ts *Thresholds) UnmarshalJSON(data []byte) error

UnmarshalJSON is implementation of json.Unmarshaler

func (*Thresholds) Validate

func (ts *Thresholds) Validate(metricName string, r *Registry) error

Validate ensures a threshold definition is consistent with the metric it applies to. Given a metric registry and a metric name to apply the expressions too, Validate will assert that each threshold expression uses an aggregation method that's supported by the provided metric. It returns an error otherwise. Note that this function expects the passed in thresholds to have been parsed already, and have their Parsed (ThresholdExpression) field already filled.

type TimeSeries

type TimeSeries struct {
	Metric *Metric
	Tags   *TagSet
}

A TimeSeries uniquely identifies the metric and the set of metric tags that a Sample (i.e. a metric measurement) has. TimeSeries objects are comparable with the == operator and can be used as map indexes.

type TrendSink

type TrendSink struct {
	Values []float64

	Count    uint64
	Min, Max float64
	Sum, Avg float64
	// contains filtered or unexported fields
}

func (*TrendSink) Add

func (t *TrendSink) Add(s Sample)

func (*TrendSink) Format

func (t *TrendSink) Format(tt time.Duration) map[string]float64

func (*TrendSink) IsEmpty

func (t *TrendSink) IsEmpty() bool

IsEmpty indicates whether the TrendSink is empty.

func (*TrendSink) P

func (t *TrendSink) P(pct float64) float64

P calculates the given percentile from sink values.

type ValueType

type ValueType int

ValueType holds the type of values a metric contains.

func (ValueType) MarshalJSON

func (t ValueType) MarshalJSON() ([]byte, error)

MarshalJSON serializes a ValueType to a JSON string.

func (ValueType) MarshalText

func (t ValueType) MarshalText() ([]byte, error)

MarshalText serializes a ValueType as a human readable string.

func (ValueType) String

func (t ValueType) String() string

func (*ValueType) UnmarshalText

func (t *ValueType) UnmarshalText(data []byte) error

UnmarshalText deserializes a ValueType from a string representation.

Directories

Path Synopsis
Package engine contains the internal metrics engine responsible for aggregating metrics during the test and evaluating thresholds against them.
Package engine contains the internal metrics engine responsible for aggregating metrics during the test and evaluating thresholds against them.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL