From 008764f49cabeff59167d62ac58a1621f1faa1d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Krasnoborski?= Date: Tue, 23 Aug 2022 18:34:05 +0200 Subject: [PATCH] Expand doc comments for policies Non-actuator components for now. --- api/aperture/policy/language/v1/policy.proto | 157 +++++++++++++-- api/gen/openapiv2/aperture.swagger.yaml | 181 +++++++++++++++--- .../aperture/policy/language/v1/policy.pb.go | 157 +++++++++++++-- docs/gen/policies/swagger.md | 171 +++++++++++++++-- 4 files changed, 583 insertions(+), 83 deletions(-) diff --git a/api/aperture/policy/language/v1/policy.proto b/api/aperture/policy/language/v1/policy.proto index 316adcf6d0..fad6bd23cf 100644 --- a/api/aperture/policy/language/v1/policy.proto +++ b/api/aperture/policy/language/v1/policy.proto @@ -27,14 +27,31 @@ message AllPolicies { } // Policy is defined as a dataflow graph (circuit) of inter-connected components. +// // Signals flow between components via ports. // As signals traverse the circuit, they get processed, stored within components or get acted upon (e.g. load shed, rate-limit, auto-scale etc.). // Policies are evaluated periodically in order to respond to changes in signal readings. +// +// :::info +// **Signal** +// +// Signals are floating-point values. +// +// A signal also have a special **Invalid** value. It's usually used to +// communicate that signal doesn't have a meaningful value at the moment, eg. +// [PromQL](#-v1promql) emits such a value if it cannot execute a query. +// Components know when their input signals are invalid and can act +// accordingly. They can either propagate the invalidness, by making their +// output itself invalid (like eg. +// [ArithmeticCombinator](#-v1arithmeticcombinator)) or use some different +// logic, like eg. [Extrapolator](#-v1extrapolator). Refer to a component's +// docs on how exactly it handles invalid inputs. +// ::: message Policy { // Defines a signal processing graph as a list of components. repeated Component circuit = 1; - // Evaluation interval (ticks) is the time period between consecutive runs of the policy circuit. + // Evaluation interval (tick) is the time period between consecutive runs of the policy circuit. // This interval is typically aligned with how often the corrective action (actuation) needs to be taken. google.protobuf.Duration evaluation_interval = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { extensions: { @@ -46,12 +63,30 @@ message Policy { }]; // @gotags: default:"0.5s" // FluxMeters are installed in the data-plane and form the observability leg of the feedback loop. + // + // FluxMeters'-created metrics can be consumed as input to the circuit via the PromQL component. map flux_meters = 3; } // FluxMeter gathers metrics for the traffic that matches its selector. +// +// Example of a selector that creates a histogram metric for all HTTP requests +// to particular service: +// ```yaml +// selector: +// service: myservice.mynamespace.svc.cluster.local +// control_point: +// traffic: ingress +// ``` message FluxMeter { - // Policies are only applied to flows that are matched based on the fields in the selector. + // What latency should we measure in the histogram created by this FluxMeter. + // + // * For traffic control points, fluxmeter will measure the duration of the + // whole http transaction (including sending request and receiving + // response). + // * For feature control points, fluxmeter will measure execution of the span + // associated with particular feature. What contributes to the span's + // duration is entirely up to the user code that uses Aperture library. common.selector.v1.Selector selector = 1; // Latency histogram buckets (in ms) for this FluxMeter. @@ -65,11 +100,38 @@ message FluxMeter { }]; // @gotags: default:"[5.0,10.0,25.0,50.0,100.0,250.0,500.0,1000.0,2500.0,5000.0,10000.0]" } -// Computational blocks that form the circuit. +// Computational block that form the circuit +// // Signals flow into the components via input ports and results are emitted on output ports. // Components are wired to each other based on signal names forming an execution graph of the circuit. +// +// :::note // Loops are broken by the runtime at the earliest component index that is part of the loop. // The looped signals are saved in the tick they are generated and served in the subsequent tick. +// ::: +// +// There are three categories of components: +// * "source" components – they take some sort of input from "the real world" and output +// a signal based on this input. Example: [PromQL](#-v1promql). In the UI +// they're represented by green color. +// * internal components – "pure" components that don't interact with the "real world". +// Examples: [GradientController](#-v1gradientcontroller), [Max](#-v1max). +// :::note +// Internal components's output can depend on their internal state, in addition to the inputs. +// Eg. see the [Exponential Moving Average filter](#-v1ema). +// ::: +// * "sink" components – they affect the real world. +// [ConcurrencyLimiter](#-v1ConcurrencyLimiter) and [RateLimiter](#-v1ratelimiter). +// Also sometimes called _actuators_. In the UI, represented by orange color. +// Sink components are usually also "sources" too, they usually emit a +// feedback signal, like `accepted_concurrency` in case of ConcurrencyLimiter. +// +// :::tip +// Sometimes you may want to use a constant value as one of component's inputs. +// You can use the [Constant](#-constant) component for this. +// ::: +// +// See also [Policy](#-v1policy) for a higher-level explanation of circuits. message Component { oneof component { // Gradient controller basically calculates the ratio between the signal and the setpoint to determine the magnitude of the correction that need to be applied. @@ -117,11 +179,34 @@ message Port { string signal_name = 1; } -// Gradient controller +// Gradient controller is a type of controller which tries to adjust the +// control variable proportionally to the relative difference between setpoint +// and actual value of the signal. +// +// The `gradient` describes a corrective factor that should be applied to the +// control variable to get the signal closer to the setpoint. It is computed as follows: // -// Describes the gradient values which is computed as follows $\text{gradient} = \frac{\text{setpoint}}{\text{signal}} \cdot \text{tolerance}$. -// Limits gradient to range [min_gradient, max_gradient]. -// Output: (gradient \* control_variable) + optimize. +// $$ +// \text{gradient} = \frac{\text{setpoint}}{\text{signal}} \cdot \text{tolerance} +// $$ +// +// `gradient` is then clamped to [min_gradient, max_gradient] range. +// +// The output of gradient controller is computed as follows: +// $$ +// \text{output} = \text{gradient}_{\text{clamped}} \cdot \text{control_variable} + optimize. +// $$ +// +// Note the additional `optimize` signal, that can be used to "nudge" the +// controller into desired idle state. +// +// The output can be _optionally_ clamped to desired range using `max` and +// `min` input. +// +// :::caution +// Some changes are expected in the near future: +// [#182](https://github.com/fluxninja/aperture/issues/182) +// ::: message GradientController { // Inputs for the Gradient Controller component. message Ins { @@ -134,13 +219,15 @@ message GradientController { // Optimize signal is added to the output of the gradient calculation. Port optimize = 3; - // Maximum value to limit the gradient. + // Maximum value to limit the output signal. Port max = 4; - // Minimum value to limit the gradient. + // Minimum value to limit the output signal. Port min = 5; - // Control variable is multiplied by the gradient to produce the output. + // Actual current value of the control variable. + // + // This signal is multiplied by the gradient to produce the output. Port control_variable = 6; } @@ -156,7 +243,13 @@ message GradientController { // Output ports of the Gradient Controller. Outs out_ports = 2; - // Tolerance of the gradient controller beyond which the correction is made. + // Tolerance is a way to pre-multiply a setpoint by given value. + // + // Value of tolerance should be close or equal to 1, eg. 1.1. + // + // :::caution + // [This is going to be deprecated](https://github.com/fluxninja/aperture/issues/182). + // ::: double tolerance = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { extensions: { key: "x-go-validate" @@ -191,10 +284,9 @@ message GradientController { // // At any time EMA component operates in one of the following states: // 1. Warm up state: The first warm_up_window samples are used to compute the initial EMA. -// If an invalid reading is received during the warm_up_window, the last good average is emitted and the state gets reset back to beginning of Warm up state. +// If an invalid reading is received during the warm_up_window, the last good average is emitted and the state gets reset back to beginning of Warm up state. // 2. Normal state: The EMA is computed using following formula. // -// If an invalid reading is received continuously for ema_window during the EMA stage, the last good EMA is emitted and the state gets reset back to Warm up state. // The EMA for a series $Y$ is calculated recursively as: // // $$ @@ -212,6 +304,8 @@ message GradientController { // $$ // \alpha = \frac{2}{N + 1} \quad\text{where } N = \frac{\text{ema\_window}}{\text{evalutation\_period}} // $$ +// +// The EMA filter also employs a min-max-envolope logic during warm up stage, explained [here](#-v1emains). message EMA { // Inputs for the EMA component. message Ins { @@ -219,9 +313,23 @@ message EMA { Port input = 1; // Upper bound of the moving average. + // + // Used during the warm-up stage: if the signal would exceed `max_envelope` + // it's multiplied by `correction_factor_on_max_envelope_violation` **once per tick**. + // + // :::note + // If the signal deviates from `max_envelope` faster than the correction + // faster, it might end up exceeding the envelope. + // ::: + // + // :::note + // The envelope logic is **not** used outside the warm-up stage! + // ::: Port max_envelope = 2; // Lower bound of the moving average. + // + // Used during the warm-up stage analoguously to `max_envelope`. Port min_envelope = 3; } @@ -248,6 +356,7 @@ message EMA { }]; // @gotags: default:"5s" // Duration of EMA warming up window. + // // The initial value of the EMA is the average of signal readings received during the warm up window. google.protobuf.Duration warm_up_window = 4 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { extensions: { @@ -292,7 +401,6 @@ message EMA { } // Type of combinator that computes the arithmetic operation on the operand signals. -// The arithmetic operation can be addition, subtraction, multiplication, division, XOR, right bit shift or left bit shift. message ArithmeticCombinator { // Inputs for the Arithmetic Combinator component. message Ins { @@ -316,6 +424,9 @@ message ArithmeticCombinator { Outs out_ports = 2; // Operator of the arithmetic operation. + // + // The arithmetic operation can be addition, subtraction, multiplication, division, XOR, right bit shift or left bit shift. + // In case of XOR and bitshifts, value of signals is cast to integers before performing the operation. string operator = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { extensions: { key: "x-go-validate" @@ -326,10 +437,15 @@ message ArithmeticCombinator { }]; // @gotags: validate:"oneof=add sub mul div xor lshift rshift" } -// Type of combinator that computes the comparison operation on lhs and rhs signals and switches between on_true and on_false signals based on the result of the comparison. +// Type of combinator that computes the comparison operation on lhs and rhs signals and switches between `on_true` and `on_false` signals based on the result of the comparison. +// // The comparison operator can be greater-than, less-than, greater-than-or-equal, less-than-or-equal, equal, or not-equal. -// This component also supports time-based response, i.e. the output transitions between on_true or on_false signal if the decider condition is true or false for at least "positive_for" or "negative_for" duration. -// If true_for and false_for durations are zero then the transitions are instantaneous. +// +// This component also supports time-based response, i.e. the output +// transitions between on_true or on_false signal if the decider condition is +// true or false for at least "positive_for" or "negative_for" duration. If +// `true_for` and `false_for` durations are zero then the transitions are +// instantaneous. message Decider { // Inputs for the Decider component. message Ins { @@ -620,6 +736,11 @@ message PromQL { Outs out_ports = 1; // Describes the Prometheus query to be run. + // + // :::caution + // TODO we should describe how to construct the query, eg. how to employ the + // fluxmeters here or link to appropriate place in docs. + // ::: string query_string = 2; // Describes the interval between successive evaluations of the Prometheus query. @@ -684,7 +805,7 @@ message Sqrt { } // Extrapolates the input signal by repeating the last valid value during the period in which it is invalid. -// It does so until maximum_extrapolation_interval is reached, beyond which it emits invalid signal unless input signal becomes valid again. +// It does so until `maximum_extrapolation_interval` is reached, beyond which it emits invalid signal unless input signal becomes valid again. message Extrapolator { // Inputs for the Extrapolator component. message Ins { diff --git a/api/gen/openapiv2/aperture.swagger.yaml b/api/gen/openapiv2/aperture.swagger.yaml index 895edda85b..de1efe3620 100644 --- a/api/gen/openapiv2/aperture.swagger.yaml +++ b/api/gen/openapiv2/aperture.swagger.yaml @@ -339,8 +339,26 @@ definitions: x-go-default: '[5.0,10.0,25.0,50.0,100.0,250.0,500.0,1000.0,2500.0,5000.0,10000.0]' selector: $ref: '#/definitions/v1Selector' - description: Policies are only applied to flows that are matched based on the fields in the selector. - description: FluxMeter gathers metrics for the traffic that matches its selector. + description: |- + What latency should we measure in the histogram created by this FluxMeter. + + * For traffic control points, fluxmeter will measure the duration of the + whole http transaction (including sending request and receiving + response). + * For feature control points, fluxmeter will measure execution of the span + associated with particular feature. What contributes to the span's + duration is entirely up to the user code that uses Aperture library. + description: |- + FluxMeter gathers metrics for the traffic that matches its selector. + + Example of a selector that creates a histogram metric for all HTTP requests + to particular service: + ```yaml + selector: + service: myservice.mynamespace.svc.cluster.local + control_point: + traffic: ingress + ``` protobufAny: type: object properties: @@ -525,14 +543,16 @@ definitions: description: Input ports for the Arithmetic Combinator component. operator: type: string - description: Operator of the arithmetic operation. + description: |- + Operator of the arithmetic operation. + + The arithmetic operation can be addition, subtraction, multiplication, division, XOR, right bit shift or left bit shift. + In case of XOR and bitshifts, value of signals is cast to integers before performing the operation. x-go-validate: oneof=add sub mul div xor lshift rshift out_ports: $ref: '#/definitions/v1ArithmeticCombinatorOuts' description: Output ports for the Arithmetic Combinator component. - description: |- - Type of combinator that computes the arithmetic operation on the operand signals. - The arithmetic operation can be addition, subtraction, multiplication, division, XOR, right bit shift or left bit shift. + description: Type of combinator that computes the arithmetic operation on the operand signals. v1ArithmeticCombinatorIns: type: object properties: @@ -652,11 +672,37 @@ definitions: $ref: '#/definitions/v1Sqrt' description: Takes an input signal and emits the square root of the input signal. description: |- - Computational blocks that form the circuit. Signals flow into the components via input ports and results are emitted on output ports. Components are wired to each other based on signal names forming an execution graph of the circuit. + + :::note Loops are broken by the runtime at the earliest component index that is part of the loop. The looped signals are saved in the tick they are generated and served in the subsequent tick. + ::: + + There are three categories of components: + * "source" components – they take some sort of input from "the real world" and output + a signal based on this input. Example: [PromQL](#-v1promql). In the UI + they're represented by green color. + * internal components – "pure" components that don't interact with the "real world". + Examples: [GradientController](#-v1gradientcontroller), [Max](#-v1max). + :::note + Internal components's output can depend on their internal state, in addition to the inputs. + Eg. see the [Exponential Moving Average filter](#-v1ema). + ::: + * "sink" components – they affect the real world. + [ConcurrencyLimiter](#-v1ConcurrencyLimiter) and [RateLimiter](#-v1ratelimiter). + Also sometimes called _actuators_. In the UI, represented by orange color. + Sink components are usually also "sources" too, they usually emit a + feedback signal, like `accepted_concurrency` in case of ConcurrencyLimiter. + + :::tip + Sometimes you may want to use a constant value as one of component's inputs. + You can use the [Constant](#-constant) component for this. + ::: + + See also [Policy](#-v1policy) for a higher-level explanation of circuits. + title: Computational block that form the circuit v1Constant: type: object properties: @@ -730,10 +776,15 @@ definitions: If the duration is zero, the transition will happen instantaneously. x-go-default: 0s description: |- - Type of combinator that computes the comparison operation on lhs and rhs signals and switches between on_true and on_false signals based on the result of the comparison. + Type of combinator that computes the comparison operation on lhs and rhs signals and switches between `on_true` and `on_false` signals based on the result of the comparison. + The comparison operator can be greater-than, less-than, greater-than-or-equal, less-than-or-equal, equal, or not-equal. - This component also supports time-based response, i.e. the output transitions between on_true or on_false signal if the decider condition is true or false for at least "positive_for" or "negative_for" duration. - If true_for and false_for durations are zero then the transitions are instantaneous. + + This component also supports time-based response, i.e. the output + transitions between on_true or on_false signal if the decider condition is + true or false for at least "positive_for" or "negative_for" duration. If + `true_for` and `false_for` durations are zero then the transitions are + instantaneous. v1DeciderIns: type: object properties: @@ -801,15 +852,15 @@ definitions: type: string description: |- Duration of EMA warming up window. + The initial value of the EMA is the average of signal readings received during the warm up window. x-go-default: 0s description: |- At any time EMA component operates in one of the following states: 1. Warm up state: The first warm_up_window samples are used to compute the initial EMA. - If an invalid reading is received during the warm_up_window, the last good average is emitted and the state gets reset back to beginning of Warm up state. + If an invalid reading is received during the warm_up_window, the last good average is emitted and the state gets reset back to beginning of Warm up state. 2. Normal state: The EMA is computed using following formula. - If an invalid reading is received continuously for ema_window during the EMA stage, the last good EMA is emitted and the state gets reset back to Warm up state. The EMA for a series $Y$ is calculated recursively as: $$ @@ -827,6 +878,8 @@ definitions: $$ \alpha = \frac{2}{N + 1} \quad\text{where } N = \frac{\text{ema\_window}}{\text{evalutation\_period}} $$ + + The EMA filter also employs a min-max-envolope logic during warm up stage, explained [here](#-v1emains). title: Exponential Moving Average (EMA) is a type of moving average that applies exponenially more weight to recent signal readings v1EMAIns: type: object @@ -836,10 +889,26 @@ definitions: description: Input signal to be used for the EMA computation. max_envelope: $ref: '#/definitions/v1Port' - description: Upper bound of the moving average. + description: |- + Upper bound of the moving average. + + Used during the warm-up stage: if the signal would exceed `max_envelope` + it's multiplied by `correction_factor_on_max_envelope_violation` **once per tick**. + + :::note + If the signal deviates from `max_envelope` faster than the correction + faster, it might end up exceeding the envelope. + ::: + + :::note + The envelope logic is **not** used outside the warm-up stage! + ::: min_envelope: $ref: '#/definitions/v1Port' - description: Lower bound of the moving average. + description: |- + Lower bound of the moving average. + + Used during the warm-up stage analoguously to `max_envelope`. description: Inputs for the EMA component. v1EMAOuts: type: object @@ -920,7 +989,7 @@ definitions: description: Output ports for the Extrapolator component. description: |- Extrapolates the input signal by repeating the last valid value during the period in which it is invalid. - It does so until maximum_extrapolation_interval is reached, beyond which it emits invalid signal unless input signal becomes valid again. + It does so until `maximum_extrapolation_interval` is reached, beyond which it emits invalid signal unless input signal becomes valid again. v1ExtrapolatorIns: type: object properties: @@ -957,25 +1026,59 @@ definitions: tolerance: type: number format: double - description: Tolerance of the gradient controller beyond which the correction is made. + description: |- + Tolerance is a way to pre-multiply a setpoint by given value. + + Value of tolerance should be close or equal to 1, eg. 1.1. + + :::caution + [This is going to be deprecated](https://github.com/fluxninja/aperture/issues/182). + ::: x-go-validate: gte=0.0 description: |- - Describes the gradient values which is computed as follows $\text{gradient} = \frac{\text{setpoint}}{\text{signal}} \cdot \text{tolerance}$. - Limits gradient to range [min_gradient, max_gradient]. - Output: (gradient \* control_variable) + optimize. - title: Gradient controller + Gradient controller is a type of controller which tries to adjust the + control variable proportionally to the relative difference between setpoint + and actual value of the signal. + + The `gradient` describes a corrective factor that should be applied to the + control variable to get the signal closer to the setpoint. It is computed as follows: + + $$ + \text{gradient} = \frac{\text{setpoint}}{\text{signal}} \cdot \text{tolerance} + $$ + + `gradient` is then clamped to [min_gradient, max_gradient] range. + + The output of gradient controller is computed as follows: + $$ + \text{output} = \text{gradient}_{\text{clamped}} \cdot \text{control_variable} + optimize. + $$ + + Note the additional `optimize` signal, that can be used to "nudge" the + controller into desired idle state. + + The output can be _optionally_ clamped to desired range using `max` and + `min` input. + + :::caution + Some changes are expected in the near future: + [#182](https://github.com/fluxninja/aperture/issues/182) + ::: v1GradientControllerIns: type: object properties: control_variable: $ref: '#/definitions/v1Port' - description: Control variable is multiplied by the gradient to produce the output. + description: |- + Actual current value of the control variable. + + This signal is multiplied by the gradient to produce the output. max: $ref: '#/definitions/v1Port' - description: Maximum value to limit the gradient. + description: Maximum value to limit the output signal. min: $ref: '#/definitions/v1Port' - description: Minimum value to limit the gradient. + description: Minimum value to limit the output signal. optimize: $ref: '#/definitions/v1Port' description: Optimize signal is added to the output of the gradient calculation. @@ -1327,19 +1430,39 @@ definitions: evaluation_interval: type: string description: |- - Evaluation interval (ticks) is the time period between consecutive runs of the policy circuit. + Evaluation interval (tick) is the time period between consecutive runs of the policy circuit. This interval is typically aligned with how often the corrective action (actuation) needs to be taken. x-go-default: 0.5s flux_meters: type: object additionalProperties: $ref: '#/definitions/policylanguagev1FluxMeter' - description: FluxMeters are installed in the data-plane and form the observability leg of the feedback loop. + description: |- + FluxMeters are installed in the data-plane and form the observability leg of the feedback loop. + + FluxMeters'-created metrics can be consumed as input to the circuit via the PromQL component. description: |- Policy is defined as a dataflow graph (circuit) of inter-connected components. + Signals flow between components via ports. As signals traverse the circuit, they get processed, stored within components or get acted upon (e.g. load shed, rate-limit, auto-scale etc.). Policies are evaluated periodically in order to respond to changes in signal readings. + + :::info + **Signal** + + Signals are floating-point values. + + A signal also have a special **Invalid** value. It's usually used to + communicate that signal doesn't have a meaningful value at the moment, eg. + [PromQL](#-v1promql) emits such a value if it cannot execute a query. + Components know when their input signals are invalid and can act + accordingly. They can either propagate the invalidness, by making their + output itself invalid (like eg. + [ArithmeticCombinator](#-v1arithmeticcombinator)) or use some different + logic, like eg. [Extrapolator](#-v1extrapolator). Refer to a component's + docs on how exactly it handles invalid inputs. + ::: v1Port: type: object properties: @@ -1367,7 +1490,13 @@ definitions: description: Output ports for the PromQL component. query_string: type: string - description: Describes the Prometheus query to be run. + description: |- + Describes the Prometheus query to be run. + + :::caution + TODO we should describe how to construct the query, eg. how to employ the + fluxmeters here or link to appropriate place in docs. + ::: description: Component that runs a Prometheus query periodically and returns the result as an output signal. v1PromQLOuts: type: object diff --git a/api/gen/proto/go/aperture/policy/language/v1/policy.pb.go b/api/gen/proto/go/aperture/policy/language/v1/policy.pb.go index 32fd674a0c..27a009bd92 100644 --- a/api/gen/proto/go/aperture/policy/language/v1/policy.pb.go +++ b/api/gen/proto/go/aperture/policy/language/v1/policy.pb.go @@ -121,9 +121,26 @@ func (x *AllPolicies) GetAllPolicies() map[string]*Policy { } // Policy is defined as a dataflow graph (circuit) of inter-connected components. +// // Signals flow between components via ports. // As signals traverse the circuit, they get processed, stored within components or get acted upon (e.g. load shed, rate-limit, auto-scale etc.). // Policies are evaluated periodically in order to respond to changes in signal readings. +// +// :::info +// **Signal** +// +// Signals are floating-point values. +// +// A signal also have a special **Invalid** value. It's usually used to +// communicate that signal doesn't have a meaningful value at the moment, eg. +// [PromQL](#-v1promql) emits such a value if it cannot execute a query. +// Components know when their input signals are invalid and can act +// accordingly. They can either propagate the invalidness, by making their +// output itself invalid (like eg. +// [ArithmeticCombinator](#-v1arithmeticcombinator)) or use some different +// logic, like eg. [Extrapolator](#-v1extrapolator). Refer to a component's +// docs on how exactly it handles invalid inputs. +// ::: type Policy struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -131,10 +148,12 @@ type Policy struct { // Defines a signal processing graph as a list of components. Circuit []*Component `protobuf:"bytes,1,rep,name=circuit,proto3" json:"circuit,omitempty"` - // Evaluation interval (ticks) is the time period between consecutive runs of the policy circuit. + // Evaluation interval (tick) is the time period between consecutive runs of the policy circuit. // This interval is typically aligned with how often the corrective action (actuation) needs to be taken. EvaluationInterval *durationpb.Duration `protobuf:"bytes,2,opt,name=evaluation_interval,json=evaluationInterval,proto3" json:"evaluation_interval,omitempty" default:"0.5s"` // @gotags: default:"0.5s" // FluxMeters are installed in the data-plane and form the observability leg of the feedback loop. + // + // FluxMeters'-created metrics can be consumed as input to the circuit via the PromQL component. FluxMeters map[string]*FluxMeter `protobuf:"bytes,3,rep,name=flux_meters,json=fluxMeters,proto3" json:"flux_meters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -192,12 +211,28 @@ func (x *Policy) GetFluxMeters() map[string]*FluxMeter { } // FluxMeter gathers metrics for the traffic that matches its selector. +// +// Example of a selector that creates a histogram metric for all HTTP requests +// to particular service: +// ```yaml +// selector: +// service: myservice.mynamespace.svc.cluster.local +// control_point: +// traffic: ingress +// ``` type FluxMeter struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Policies are only applied to flows that are matched based on the fields in the selector. + // What latency should we measure in the histogram created by this FluxMeter. + // + // * For traffic control points, fluxmeter will measure the duration of the + // whole http transaction (including sending request and receiving + // response). + // * For feature control points, fluxmeter will measure execution of the span + // associated with particular feature. What contributes to the span's + // duration is entirely up to the user code that uses Aperture library. Selector *v1.Selector `protobuf:"bytes,1,opt,name=selector,proto3" json:"selector,omitempty"` // Latency histogram buckets (in ms) for this FluxMeter. HistogramBuckets []float64 `protobuf:"fixed64,2,rep,packed,name=histogram_buckets,json=histogramBuckets,proto3" json:"histogram_buckets,omitempty" default:"[5.0,10.0,25.0,50.0,100.0,250.0,500.0,1000.0,2500.0,5000.0,10000.0]"` // @gotags: default:"[5.0,10.0,25.0,50.0,100.0,250.0,500.0,1000.0,2500.0,5000.0,10000.0]" @@ -249,11 +284,38 @@ func (x *FluxMeter) GetHistogramBuckets() []float64 { return nil } -// Computational blocks that form the circuit. +// Computational block that form the circuit +// // Signals flow into the components via input ports and results are emitted on output ports. // Components are wired to each other based on signal names forming an execution graph of the circuit. +// +// :::note // Loops are broken by the runtime at the earliest component index that is part of the loop. // The looped signals are saved in the tick they are generated and served in the subsequent tick. +// ::: +// +// There are three categories of components: +// * "source" components – they take some sort of input from "the real world" and output +// a signal based on this input. Example: [PromQL](#-v1promql). In the UI +// they're represented by green color. +// * internal components – "pure" components that don't interact with the "real world". +// Examples: [GradientController](#-v1gradientcontroller), [Max](#-v1max). +// :::note +// Internal components's output can depend on their internal state, in addition to the inputs. +// Eg. see the [Exponential Moving Average filter](#-v1ema). +// ::: +// * "sink" components – they affect the real world. +// [ConcurrencyLimiter](#-v1ConcurrencyLimiter) and [RateLimiter](#-v1ratelimiter). +// Also sometimes called _actuators_. In the UI, represented by orange color. +// Sink components are usually also "sources" too, they usually emit a +// feedback signal, like `accepted_concurrency` in case of ConcurrencyLimiter. +// +// :::tip +// Sometimes you may want to use a constant value as one of component's inputs. +// You can use the [Constant](#-constant) component for this. +// ::: +// +// See also [Policy](#-v1policy) for a higher-level explanation of circuits. type Component struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -536,11 +598,34 @@ func (x *Port) GetSignalName() string { return "" } -// Gradient controller +// Gradient controller is a type of controller which tries to adjust the +// control variable proportionally to the relative difference between setpoint +// and actual value of the signal. +// +// The `gradient` describes a corrective factor that should be applied to the +// control variable to get the signal closer to the setpoint. It is computed as follows: // -// Describes the gradient values which is computed as follows $\text{gradient} = \frac{\text{setpoint}}{\text{signal}} \cdot \text{tolerance}$. -// Limits gradient to range [min_gradient, max_gradient]. -// Output: (gradient \* control_variable) + optimize. +// $$ +// \text{gradient} = \frac{\text{setpoint}}{\text{signal}} \cdot \text{tolerance} +// $$ +// +// `gradient` is then clamped to [min_gradient, max_gradient] range. +// +// The output of gradient controller is computed as follows: +// $$ +// \text{output} = \text{gradient}_{\text{clamped}} \cdot \text{control_variable} + optimize. +// $$ +// +// Note the additional `optimize` signal, that can be used to "nudge" the +// controller into desired idle state. +// +// The output can be _optionally_ clamped to desired range using `max` and +// `min` input. +// +// :::caution +// Some changes are expected in the near future: +// [#182](https://github.com/fluxninja/aperture/issues/182) +// ::: type GradientController struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -550,7 +635,13 @@ type GradientController struct { InPorts *GradientController_Ins `protobuf:"bytes,1,opt,name=in_ports,json=inPorts,proto3" json:"in_ports,omitempty"` // Output ports of the Gradient Controller. OutPorts *GradientController_Outs `protobuf:"bytes,2,opt,name=out_ports,json=outPorts,proto3" json:"out_ports,omitempty"` - // Tolerance of the gradient controller beyond which the correction is made. + // Tolerance is a way to pre-multiply a setpoint by given value. + // + // Value of tolerance should be close or equal to 1, eg. 1.1. + // + // :::caution + // [This is going to be deprecated](https://github.com/fluxninja/aperture/issues/182). + // ::: Tolerance float64 `protobuf:"fixed64,3,opt,name=tolerance,proto3" json:"tolerance,omitempty" validate:"gte=0.0"` // @gotags: validate:"gte=0.0" // Minimum gradient which clamps the computed gradient value to the range, [min_gradient, max_gradient]. MinGradient float64 `protobuf:"fixed64,4,opt,name=min_gradient,json=minGradient,proto3" json:"min_gradient,omitempty" default:"-1.79769313486231570814527423731704356798070e+308"` // @gotags: default:"-1.79769313486231570814527423731704356798070e+308" @@ -629,10 +720,9 @@ func (x *GradientController) GetMaxGradient() float64 { // // At any time EMA component operates in one of the following states: // 1. Warm up state: The first warm_up_window samples are used to compute the initial EMA. -// If an invalid reading is received during the warm_up_window, the last good average is emitted and the state gets reset back to beginning of Warm up state. +// If an invalid reading is received during the warm_up_window, the last good average is emitted and the state gets reset back to beginning of Warm up state. // 2. Normal state: The EMA is computed using following formula. // -// If an invalid reading is received continuously for ema_window during the EMA stage, the last good EMA is emitted and the state gets reset back to Warm up state. // The EMA for a series $Y$ is calculated recursively as: // // $$ @@ -650,6 +740,8 @@ func (x *GradientController) GetMaxGradient() float64 { // $$ // \alpha = \frac{2}{N + 1} \quad\text{where } N = \frac{\text{ema\_window}}{\text{evalutation\_period}} // $$ +// +// The EMA filter also employs a min-max-envolope logic during warm up stage, explained [here](#-v1emains). type EMA struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -662,6 +754,7 @@ type EMA struct { // Duration of EMA sampling window. EmaWindow *durationpb.Duration `protobuf:"bytes,3,opt,name=ema_window,json=emaWindow,proto3" json:"ema_window,omitempty" default:"5s"` // @gotags: default:"5s" // Duration of EMA warming up window. + // // The initial value of the EMA is the average of signal readings received during the warm up window. WarmUpWindow *durationpb.Duration `protobuf:"bytes,4,opt,name=warm_up_window,json=warmUpWindow,proto3" json:"warm_up_window,omitempty" default:"0s"` // @gotags: default:"0s" // Correction factor to apply on the output value if its in violation of the min envelope. @@ -745,7 +838,6 @@ func (x *EMA) GetCorrectionFactorOnMaxEnvelopeViolation() float64 { } // Type of combinator that computes the arithmetic operation on the operand signals. -// The arithmetic operation can be addition, subtraction, multiplication, division, XOR, right bit shift or left bit shift. type ArithmeticCombinator struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -756,6 +848,9 @@ type ArithmeticCombinator struct { // Output ports for the Arithmetic Combinator component. OutPorts *ArithmeticCombinator_Outs `protobuf:"bytes,2,opt,name=out_ports,json=outPorts,proto3" json:"out_ports,omitempty"` // Operator of the arithmetic operation. + // + // The arithmetic operation can be addition, subtraction, multiplication, division, XOR, right bit shift or left bit shift. + // In case of XOR and bitshifts, value of signals is cast to integers before performing the operation. Operator string `protobuf:"bytes,3,opt,name=operator,proto3" json:"operator,omitempty" validate:"oneof=add sub mul div xor lshift rshift"` // @gotags: validate:"oneof=add sub mul div xor lshift rshift" } @@ -812,10 +907,15 @@ func (x *ArithmeticCombinator) GetOperator() string { return "" } -// Type of combinator that computes the comparison operation on lhs and rhs signals and switches between on_true and on_false signals based on the result of the comparison. +// Type of combinator that computes the comparison operation on lhs and rhs signals and switches between `on_true` and `on_false` signals based on the result of the comparison. +// // The comparison operator can be greater-than, less-than, greater-than-or-equal, less-than-or-equal, equal, or not-equal. -// This component also supports time-based response, i.e. the output transitions between on_true or on_false signal if the decider condition is true or false for at least "positive_for" or "negative_for" duration. -// If true_for and false_for durations are zero then the transitions are instantaneous. +// +// This component also supports time-based response, i.e. the output +// transitions between on_true or on_false signal if the decider condition is +// true or false for at least "positive_for" or "negative_for" duration. If +// `true_for` and `false_for` durations are zero then the transitions are +// instantaneous. type Decider struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1210,6 +1310,11 @@ type PromQL struct { // Output ports for the PromQL component. OutPorts *PromQL_Outs `protobuf:"bytes,1,opt,name=out_ports,json=outPorts,proto3" json:"out_ports,omitempty"` // Describes the Prometheus query to be run. + // + // :::caution + // TODO we should describe how to construct the query, eg. how to employ the + // fluxmeters here or link to appropriate place in docs. + // ::: QueryString string `protobuf:"bytes,2,opt,name=query_string,json=queryString,proto3" json:"query_string,omitempty"` // Describes the interval between successive evaluations of the Prometheus query. EvaluationInterval *durationpb.Duration `protobuf:"bytes,3,opt,name=evaluation_interval,json=evaluationInterval,proto3" json:"evaluation_interval,omitempty" default:"10s"` // @gotags: default:"10s" @@ -1398,7 +1503,7 @@ func (x *Sqrt) GetScale() float64 { } // Extrapolates the input signal by repeating the last valid value during the period in which it is invalid. -// It does so until maximum_extrapolation_interval is reached, beyond which it emits invalid signal unless input signal becomes valid again. +// It does so until `maximum_extrapolation_interval` is reached, beyond which it emits invalid signal unless input signal becomes valid again. type Extrapolator struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1595,11 +1700,13 @@ type GradientController_Ins struct { Setpoint *Port `protobuf:"bytes,2,opt,name=setpoint,proto3" json:"setpoint,omitempty"` // Optimize signal is added to the output of the gradient calculation. Optimize *Port `protobuf:"bytes,3,opt,name=optimize,proto3" json:"optimize,omitempty"` - // Maximum value to limit the gradient. + // Maximum value to limit the output signal. Max *Port `protobuf:"bytes,4,opt,name=max,proto3" json:"max,omitempty"` - // Minimum value to limit the gradient. + // Minimum value to limit the output signal. Min *Port `protobuf:"bytes,5,opt,name=min,proto3" json:"min,omitempty"` - // Control variable is multiplied by the gradient to produce the output. + // Actual current value of the control variable. + // + // This signal is multiplied by the gradient to produce the output. ControlVariable *Port `protobuf:"bytes,6,opt,name=control_variable,json=controlVariable,proto3" json:"control_variable,omitempty"` } @@ -1735,8 +1842,22 @@ type EMA_Ins struct { // Input signal to be used for the EMA computation. Input *Port `protobuf:"bytes,1,opt,name=input,proto3" json:"input,omitempty"` // Upper bound of the moving average. + // + // Used during the warm-up stage: if the signal would exceed `max_envelope` + // it's multiplied by `correction_factor_on_max_envelope_violation` **once per tick**. + // + // :::note + // If the signal deviates from `max_envelope` faster than the correction + // faster, it might end up exceeding the envelope. + // ::: + // + // :::note + // The envelope logic is **not** used outside the warm-up stage! + // ::: MaxEnvelope *Port `protobuf:"bytes,2,opt,name=max_envelope,json=maxEnvelope,proto3" json:"max_envelope,omitempty"` // Lower bound of the moving average. + // + // Used during the warm-up stage analoguously to `max_envelope`. MinEnvelope *Port `protobuf:"bytes,3,opt,name=min_envelope,json=minEnvelope,proto3" json:"min_envelope,omitempty"` } diff --git a/docs/gen/policies/swagger.md b/docs/gen/policies/swagger.md index 9bdd1afa21..6b7972da3a 100644 --- a/docs/gen/policies/swagger.md +++ b/docs/gen/policies/swagger.md @@ -19,11 +19,13 @@ - [languagev1ConcurrencyLimiter](#languagev1-concurrency-limiter) – Concurrency Limiter is an actuator component that regulates flows in order to pr… - [languagev1RateLimiter](#languagev1-rate-limiter) - [policylanguagev1FluxMeter](#policylanguagev1-flux-meter) – FluxMeter gathers metrics for the traffic that matches its selector. + +Example of… + - [v1ArithmeticCombinator](#v1-arithmetic-combinator) – Type of combinator that computes the arithmetic operation on the operand signals… - [v1ArithmeticCombinatorIns](#v1-arithmetic-combinator-ins) – Inputs for the Arithmetic Combinator component. - [v1ArithmeticCombinatorOuts](#v1-arithmetic-combinator-outs) – Outputs for the Arithmetic Combinator component. -- [v1Component](#v1-component) – Computational blocks that form the circuit. - Signals flow into the components via… +- [v1Component](#v1-component) – Computational block that form the circuit - [v1Constant](#v1-constant) – Component that emits a constant value as an output signal. - [v1ConstantOuts](#v1-constant-outs) – Outputs for the Constant component. - [v1ControlPoint](#v1-control-point) – Identifies control point within a service that the rule or policy should apply t… @@ -37,7 +39,8 @@ - [v1Extrapolator](#v1-extrapolator) – Extrapolates the input signal by repeating the last valid value during the perio… - [v1ExtrapolatorIns](#v1-extrapolator-ins) – Inputs for the Extrapolator component. - [v1ExtrapolatorOuts](#v1-extrapolator-outs) – Outputs for the Extrapolator component. -- [v1GradientController](#v1-gradient-controller) – Gradient controller +- [v1GradientController](#v1-gradient-controller) – Gradient controller is a type of controller which tries to adjust the + control va… - [v1GradientControllerIns](#v1-gradient-controller-ins) – Inputs for the Gradient Controller component. - [v1GradientControllerOuts](#v1-gradient-controller-outs) – Outputs for the Gradient Controller component. - [v1K8sLabelMatcherRequirement](#v1-k8s-label-matcher-requirement) – Label selector requirement which is a selector that contains values, a key, and … @@ -56,7 +59,9 @@ - [v1MinIns](#v1-min-ins) – Inputs for the Min component. - [v1MinOuts](#v1-min-outs) – Output ports for the Min component. - [v1Policy](#v1-policy) – Policy is defined as a dataflow graph (circuit) of inter-connected components. - S… + +… + - [v1Port](#v1-port) – Components are interconnected with each other via Ports. - [v1PromQL](#v1-prom-q-l) – Component that runs a Prometheus query periodically and returns the result as an… - [v1PromQLOuts](#v1-prom-q-l-outs) – Output for the PromQL component. @@ -290,6 +295,16 @@ Concurrency is calculated in terms of total tokens which translate to (avg. late FluxMeter gathers metrics for the traffic that matches its selector. +Example of a selector that creates a histogram metric for all HTTP requests +to particular service: + +```yaml +selector: + service: myservice.mynamespace.svc.cluster.local + control_point: + traffic: ingress +``` + #### Properties
@@ -304,7 +319,14 @@ FluxMeter gathers metrics for the traffic that matches its selector.
selector
-([V1Selector](#v1-selector)) Policies are only applied to flows that are matched based on the fields in the selector. +([V1Selector](#v1-selector)) What latency should we measure in the histogram created by this FluxMeter. + +- For traffic control points, fluxmeter will measure the duration of the + whole http transaction (including sending request and receiving + response). +- For feature control points, fluxmeter will measure execution of the span + associated with particular feature. What contributes to the span's + duration is entirely up to the user code that uses Aperture library.
@@ -312,7 +334,6 @@ FluxMeter gathers metrics for the traffic that matches its selector. ### v1ArithmeticCombinator Type of combinator that computes the arithmetic operation on the operand signals. -The arithmetic operation can be addition, subtraction, multiplication, division, XOR, right bit shift or left bit shift. #### Properties @@ -330,6 +351,9 @@ The arithmetic operation can be addition, subtraction, multiplication, division, (string, `oneof=add sub mul div xor lshift rshift`) Operator of the arithmetic operation. +The arithmetic operation can be addition, subtraction, multiplication, division, XOR, right bit shift or left bit shift. +In case of XOR and bitshifts, value of signals is cast to integers before performing the operation. +
@@ -381,11 +405,39 @@ Outputs for the Arithmetic Combinator component. ### v1Component -Computational blocks that form the circuit. +Computational block that form the circuit + Signals flow into the components via input ports and results are emitted on output ports. Components are wired to each other based on signal names forming an execution graph of the circuit. + +:::note Loops are broken by the runtime at the earliest component index that is part of the loop. The looped signals are saved in the tick they are generated and served in the subsequent tick. +::: + +There are three categories of components: + +- "source" components – they take some sort of input from "the real world" and output + a signal based on this input. Example: [PromQL](#-v1promql). In the UI + they're represented by green color. +- internal components – "pure" components that don't interact with the "real world". + Examples: [GradientController](#-v1gradientcontroller), [Max](#-v1max). + :::note + Internal components's output can depend on their internal state, in addition to the inputs. + Eg. see the [Exponential Moving Average filter](#-v1ema). + ::: +- "sink" components – they affect the real world. + [ConcurrencyLimiter](#-v1ConcurrencyLimiter) and [RateLimiter](#-v1ratelimiter). + Also sometimes called _actuators_. In the UI, represented by orange color. + Sink components are usually also "sources" too, they usually emit a + feedback signal, like `accepted_concurrency` in case of ConcurrencyLimiter. + +:::tip +Sometimes you may want to use a constant value as one of component's inputs. +You can use the [Constant](#-constant) component for this. +::: + +See also [Policy](#-v1policy) for a higher-level explanation of circuits. #### Properties @@ -559,10 +611,15 @@ Usually powered by integration with a proxy (like envoy) or a web framework. ### v1Decider -Type of combinator that computes the comparison operation on lhs and rhs signals and switches between on_true and on_false signals based on the result of the comparison. +Type of combinator that computes the comparison operation on lhs and rhs signals and switches between `on_true` and `on_false` signals based on the result of the comparison. + The comparison operator can be greater-than, less-than, greater-than-or-equal, less-than-or-equal, equal, or not-equal. -This component also supports time-based response, i.e. the output transitions between on_true or on_false signal if the decider condition is true or false for at least "positive_for" or "negative_for" duration. -If true_for and false_for durations are zero then the transitions are instantaneous. + +This component also supports time-based response, i.e. the output +transitions between on_true or on_false signal if the decider condition is +true or false for at least "positive_for" or "negative_for" duration. If +`true_for` and `false_for` durations are zero then the transitions are +instantaneous. #### Properties @@ -673,7 +730,6 @@ At any time EMA component operates in one of the following states: If an invalid reading is received during the warm_up_window, the last good average is emitted and the state gets reset back to beginning of Warm up state. 2. Normal state: The EMA is computed using following formula. -If an invalid reading is received continuously for ema_window during the EMA stage, the last good EMA is emitted and the state gets reset back to Warm up state. The EMA for a series $Y$ is calculated recursively as: $$ @@ -692,6 +748,8 @@ $$ \alpha = \frac{2}{N + 1} \quad\text{where } N = \frac{\text{ema\_window}}{\text{evalutation\_period}} $$ +The EMA filter also employs a min-max-envolope logic during warm up stage, explained [here](#-v1emains). + #### Properties
@@ -739,6 +797,7 @@ $$
(string, default: `0s`) Duration of EMA warming up window. + The initial value of the EMA is the average of signal readings received during the warm up window.
@@ -764,6 +823,18 @@ Inputs for the EMA component. ([V1Port](#v1-port)) Upper bound of the moving average. +Used during the warm-up stage: if the signal would exceed `max_envelope` +it's multiplied by `correction_factor_on_max_envelope_violation` **once per tick**. + +:::note +If the signal deviates from `max_envelope` faster than the correction +faster, it might end up exceeding the envelope. +::: + +:::note +The envelope logic is **not** used outside the warm-up stage! +::: +
@@ -772,6 +843,8 @@ Inputs for the EMA component. ([V1Port](#v1-port)) Lower bound of the moving average. +Used during the warm-up stage analoguously to `max_envelope`. +
@@ -816,7 +889,7 @@ Label selector expression of the equal form "label == value". ### v1Extrapolator Extrapolates the input signal by repeating the last valid value during the period in which it is invalid. -It does so until maximum_extrapolation_interval is reached, beyond which it emits invalid signal unless input signal becomes valid again. +It does so until `maximum_extrapolation_interval` is reached, beyond which it emits invalid signal unless input signal becomes valid again. #### Properties @@ -877,11 +950,35 @@ Outputs for the Extrapolator component. ### v1GradientController -Gradient controller +Gradient controller is a type of controller which tries to adjust the +control variable proportionally to the relative difference between setpoint +and actual value of the signal. + +The `gradient` describes a corrective factor that should be applied to the +control variable to get the signal closer to the setpoint. It is computed as follows: + +$$ +\text{gradient} = \frac{\text{setpoint}}{\text{signal}} \cdot \text{tolerance} +$$ + +`gradient` is then clamped to [min_gradient, max_gradient] range. + +The output of gradient controller is computed as follows: + +$$ +\text{output} = \text{gradient}_{\text{clamped}} \cdot \text{control_variable} + optimize. +$$ + +Note the additional `optimize` signal, that can be used to "nudge" the +controller into desired idle state. + +The output can be _optionally_ clamped to desired range using `max` and +`min` input. -Describes the gradient values which is computed as follows $\text{gradient} = \frac{\text{setpoint}}{\text{signal}} \cdot \text{tolerance}$. -Limits gradient to range [min_gradient, max_gradient]. -Output: (gradient \* control_variable) + optimize. +:::caution +Some changes are expected in the near future: +[#182](https://github.com/fluxninja/aperture/issues/182) +::: #### Properties @@ -921,7 +1018,13 @@ Output: (gradient \* control_variable) + optimize.
tolerance
-(float64, `gte=0.0`) Tolerance of the gradient controller beyond which the correction is made. +(float64, `gte=0.0`) Tolerance is a way to pre-multiply a setpoint by given value. + +Value of tolerance should be close or equal to 1, eg. 1.1. + +:::caution +[This is going to be deprecated](https://github.com/fluxninja/aperture/issues/182). +:::
@@ -936,7 +1039,9 @@ Inputs for the Gradient Controller component.
control_variable
-([V1Port](#v1-port)) Control variable is multiplied by the gradient to produce the output. +([V1Port](#v1-port)) Actual current value of the control variable. + +This signal is multiplied by the gradient to produce the output.
@@ -944,7 +1049,7 @@ Inputs for the Gradient Controller component.
max
-([V1Port](#v1-port)) Maximum value to limit the gradient. +([V1Port](#v1-port)) Maximum value to limit the output signal.
@@ -952,7 +1057,7 @@ Inputs for the Gradient Controller component.
min
-([V1Port](#v1-port)) Minimum value to limit the gradient. +([V1Port](#v1-port)) Minimum value to limit the output signal.
@@ -1305,10 +1410,27 @@ Output ports for the Min component. ### v1Policy Policy is defined as a dataflow graph (circuit) of inter-connected components. + Signals flow between components via ports. As signals traverse the circuit, they get processed, stored within components or get acted upon (e.g. load shed, rate-limit, auto-scale etc.). Policies are evaluated periodically in order to respond to changes in signal readings. +:::info +**Signal** + +Signals are floating-point values. + +A signal also have a special **Invalid** value. It's usually used to +communicate that signal doesn't have a meaningful value at the moment, eg. +[PromQL](#-v1promql) emits such a value if it cannot execute a query. +Components know when their input signals are invalid and can act +accordingly. They can either propagate the invalidness, by making their +output itself invalid (like eg. +[ArithmeticCombinator](#-v1arithmeticcombinator)) or use some different +logic, like eg. [Extrapolator](#-v1extrapolator). Refer to a component's +docs on how exactly it handles invalid inputs. +::: + #### Properties
@@ -1323,7 +1445,7 @@ Policies are evaluated periodically in order to respond to changes in signal rea
evaluation_interval
-(string, default: `0.5s`) Evaluation interval (ticks) is the time period between consecutive runs of the policy circuit. +(string, default: `0.5s`) Evaluation interval (tick) is the time period between consecutive runs of the policy circuit. This interval is typically aligned with how often the corrective action (actuation) needs to be taken.
@@ -1334,6 +1456,8 @@ This interval is typically aligned with how often the corrective action (actuati (map of [Policylanguagev1FluxMeter](#policylanguagev1-flux-meter)) FluxMeters are installed in the data-plane and form the observability leg of the feedback loop. +FluxMeters'-created metrics can be consumed as input to the circuit via the PromQL component. +
@@ -1380,6 +1504,11 @@ Component that runs a Prometheus query periodically and returns the result as an (string) Describes the Prometheus query to be run. +:::caution +TODO we should describe how to construct the query, eg. how to employ the +fluxmeters here or link to appropriate place in docs. +::: +