Skip to content

Commit

Permalink
Move to single tracing-endpoint option
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-cattermole committed Mar 18, 2024
1 parent 43afa41 commit 0e3f68a
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 117 deletions.
139 changes: 60 additions & 79 deletions doc/server/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,8 @@ Options:
Include the Limit Name in prometheus label
-v...
Sets the level of verbosity
--tracing-host <tracing_host>
The host for the tracing service
--tracing-port <tracing_port>
The port for the tracing service [default: 4317]
--tracing-endpoint <tracing_endpoint>
The endpoint for the tracing service
--validate
Validates the LIMITS_FILE and exits
-H, --rate-limit-headers <rate_limit_headers>
Expand All @@ -47,7 +45,8 @@ Options:
Print version
```

The values used are authoritative over any [environment variables](#configuration-using-environment-variables) independently set.
The values used are authoritative over any [environment variables](#configuration-using-environment-variables)
independently set.

### Limit definitions

Expand Down Expand Up @@ -101,13 +100,13 @@ variables:
- user_id
```
- `namespace` namespaces the limit, will generally be the domain, [see here](../how-it-works.md)
- `seconds` is the duration for which the limit applies, in seconds: e.g. `60` is a span of time of one minute
- `max_value` is the actual limit, e.g. `100` would limit to 100 requests
- `name` lets the user _optionally_ name the limit
- `variables` is an array of variables, which once resolved, will be used to qualify counters for the limit,
e.g. `api_key` to limit per api keys
- `conditions` is an array of conditions, which once evaluated will decide whether to apply the limit or not
- `namespace` namespaces the limit, will generally be the domain, [see here](../how-it-works.md)
- `seconds` is the duration for which the limit applies, in seconds: e.g. `60` is a span of time of one minute
- `max_value` is the actual limit, e.g. `100` would limit to 100 requests
- `name` lets the user _optionally_ name the limit
- `variables` is an array of variables, which once resolved, will be used to qualify counters for the limit,
e.g. `api_key` to limit per api keys
- `conditions` is an array of conditions, which once evaluated will decide whether to apply the limit or not

#### `condition` syntax

Expand All @@ -116,9 +115,9 @@ Each `condition` is an expression producing a boolean value (`true` or `false`).

Expressions follow the following syntax: `$IDENTIFIER $OP $STRING_LITERAL`, where:

- `$IDENTIFIER` will be used to resolve the value at evaluation time, e.g. `role`
- `$OP` is an operator, either `==` or `!=`
- `$STRING_LITERAL` is a literal string value, `"` or `'` demarcated, e.g. `"admin"`
- `$IDENTIFIER` will be used to resolve the value at evaluation time, e.g. `role`
- `$OP` is an operator, either `==` or `!=`
- `$STRING_LITERAL` is a literal string value, `"` or `'` demarcated, e.g. `"admin"`

So that `role != "admin"` would apply the limit on request from all users, but `admin`'s.

Expand Down Expand Up @@ -281,7 +280,8 @@ For an in-depth coverage of the different topologies supported and how they affe
## Configuration using environment variables

The Limitador server has some options that can be configured with environment variables. These will override the
_default_ values the server uses. [Any argument](#command-line-configuration) used when starting the server will prevail over the
_default_ values the server uses. [Any argument](#command-line-configuration) used when starting the server will prevail
over the
environment variables.

#### `ENVOY_RLS_HOST`
Expand All @@ -290,137 +290,120 @@ environment variables.
- Optional. Defaults to `"0.0.0.0"`.
- Format: `string`.


#### `ENVOY_RLS_PORT`

- Port where the Envoy RLS server listens.
- Optional. Defaults to `8081`.
- Format: `integer`.


#### `HTTP_API_HOST`

- Host where the HTTP server listens.
- Optional. Defaults to `"0.0.0.0"`.
- Format: `string`.


#### `HTTP_API_PORT`

- Port where the HTTP API listens.
- Optional. Defaults to `8080`.
- Format: `integer`.


#### `LIMITS_FILE`

- YAML file that contains the limits to create when Limitador boots. If the
limits specified already have counters associated, Limitador will not delete them.
Changes to the file will be picked up by the running server.
limits specified already have counters associated, Limitador will not delete them.
Changes to the file will be picked up by the running server.
- *Required*. No default
- Format: `string`, file path.


#### `LIMIT_NAME_IN_PROMETHEUS_LABELS`

- Enables using limit names as labels in Prometheus metrics. This is disabled by
default because for a few limits it should be fine, but it could become a
problem when defining lots of limits. See the caution note in the [Prometheus
docs](https://prometheus.io/docs/practices/naming/#labels)
default because for a few limits it should be fine, but it could become a
problem when defining lots of limits. See the caution note in the [Prometheus
docs](https://prometheus.io/docs/practices/naming/#labels)
- Optional. Disabled by default.
- Format: `bool`, set to `"1"` to enable.

#### `TRACING_HOST`
#### `TRACING_ENDPOINT`

- Host of the OTLP tracing collector.
- The endpoint of the OTLP tracing collector (scheme://host:port).
- Optional. Default to `""` (tracing disabled)
- Format: `string`

#### `TRACING_PORT`

- Port of the OTLP tracing collector.
- Optional. Defaults to `4317`.
- Format: `integer`.

#### `REDIS_LOCAL_CACHE_ENABLED`

- Enables a storage implementation that uses Redis, but also caches some data in
memory. The idea is to improve throughput and latencies by caching the counters
in memory to reduce the number of accesses to Redis. To achieve that, this mode
sacrifices some rate-limit accuracy. This mode does two things:
memory. The idea is to improve throughput and latencies by caching the counters
in memory to reduce the number of accesses to Redis. To achieve that, this mode
sacrifices some rate-limit accuracy. This mode does two things:
- Batches counter updates. Instead of updating the counters on every
request, it updates them in memory and commits them to Redis in batches. The
flushing interval can be configured with the
[`REDIS_LOCAL_CACHE_FLUSHING_PERIOD_MS`](#redis_local_cache_flushing_period_ms)
env. The trade-off is that when running several instances of Limitador,
other instances will not become aware of the counter updates until they're
committed to Redis.
request, it updates them in memory and commits them to Redis in batches. The
flushing interval can be configured with the
[`REDIS_LOCAL_CACHE_FLUSHING_PERIOD_MS`](#redis_local_cache_flushing_period_ms)
env. The trade-off is that when running several instances of Limitador,
other instances will not become aware of the counter updates until they're
committed to Redis.
- Caches counters. Instead of fetching the value of a counter every time
it's needed, the value is cached for a configurable period. The trade-off is
that when running several instances of Limitador, an instance will not
become aware of the counter updates other instances do while the value is
cached. When a counter is already at 0 (limit exceeded), it's cached until
it expires in Redis. In this case, no matter what other instances do, we
know that the quota will not be reestablished until the key expires in
Redis, so in this case, rate-limit accuracy is not affected. When a counter
has still some quota remaining the situation is different, that's why we can
tune for how long it will be cached. The formula is as follows:
MIN(ttl_in_redis/[`REDIS_LOCAL_CACHE_TTL_RATIO_CACHED_COUNTERS`](#redis_local_cache_ttl_ratio_cached_counters),
[`REDIS_LOCAL_CACHE_MAX_TTL_CACHED_COUNTERS_MS`](#redis_local_cache_max_ttl_cached_counters_ms)).
For example, let's image that the current TTL (time remaining until the
limit resets) in Redis for a counter is 10 seconds, and we set the ratio to
2, and the max time for 30s. In this case, the counter will be cached for 5s
(min(10/2, 30)). During those 5s, Limitador will not fetch the value of that
counter from Redis, so it will answer faster, but it will also miss the
updates done by other instances, so it can go over the limits in that 5s
interval.
it's needed, the value is cached for a configurable period. The trade-off is
that when running several instances of Limitador, an instance will not
become aware of the counter updates other instances do while the value is
cached. When a counter is already at 0 (limit exceeded), it's cached until
it expires in Redis. In this case, no matter what other instances do, we
know that the quota will not be reestablished until the key expires in
Redis, so in this case, rate-limit accuracy is not affected. When a counter
has still some quota remaining the situation is different, that's why we can
tune for how long it will be cached. The formula is as follows:
MIN(ttl_in_redis/[`REDIS_LOCAL_CACHE_TTL_RATIO_CACHED_COUNTERS`](#redis_local_cache_ttl_ratio_cached_counters),
[`REDIS_LOCAL_CACHE_MAX_TTL_CACHED_COUNTERS_MS`](#redis_local_cache_max_ttl_cached_counters_ms)).
For example, let's image that the current TTL (time remaining until the
limit resets) in Redis for a counter is 10 seconds, and we set the ratio to
2, and the max time for 30s. In this case, the counter will be cached for 5s
(min(10/2, 30)). During those 5s, Limitador will not fetch the value of that
counter from Redis, so it will answer faster, but it will also miss the
updates done by other instances, so it can go over the limits in that 5s
interval.
- Optional. Disabled by default.
- Format: set to "1" to enable.
- Note: "REDIS_URL" needs to be set.


#### `REDIS_LOCAL_CACHE_FLUSHING_PERIOD_MS`

- Used to configure the local cache when using Redis. See
[`REDIS_LOCAL_CACHE_ENABLED`](#redis_local_cache_enabled). This env only applies
when `"REDIS_LOCAL_CACHE_ENABLED" == 1`.
[`REDIS_LOCAL_CACHE_ENABLED`](#redis_local_cache_enabled). This env only applies
when `"REDIS_LOCAL_CACHE_ENABLED" == 1`.
- Optional. Defaults to `1000`.
- Format: `integer`. Duration in milliseconds.


#### `REDIS_LOCAL_CACHE_MAX_TTL_CACHED_COUNTERS_MS`

- Used to configure the local cache when using Redis. See
[`REDIS_LOCAL_CACHE_ENABLED`](#redis_local_cache_enabled). This env only applies
when `"REDIS_LOCAL_CACHE_ENABLED" == 1`.
[`REDIS_LOCAL_CACHE_ENABLED`](#redis_local_cache_enabled). This env only applies
when `"REDIS_LOCAL_CACHE_ENABLED" == 1`.
- Optional. Defaults to `5000`.
- Format: `integer`. Duration in milliseconds.


#### `REDIS_LOCAL_CACHE_TTL_RATIO_CACHED_COUNTERS`

- Used to configure the local cache when using Redis. See
[`REDIS_LOCAL_CACHE_ENABLED`](#redis_local_cache_enabled). This env only applies
when `"REDIS_LOCAL_CACHE_ENABLED" == 1`.
[`REDIS_LOCAL_CACHE_ENABLED`](#redis_local_cache_enabled). This env only applies
when `"REDIS_LOCAL_CACHE_ENABLED" == 1`.
- Optional. Defaults to `10`.
- Format: `integer`.


#### `REDIS_URL`

- Redis URL. Required only when you want to use Redis to store the limits.
- Optional. By default, Limitador stores the limits in memory and does not
require Redis.
require Redis.
- Format: `string`, URL in the format of `"redis://127.0.0.1:6379"`.


#### `RUST_LOG`

- Defines the log level.
- Optional. Defaults to `"error"`.
- Format: `enum`: `"debug"`, `"error"`, `"info"`, `"warn"`, or `"trace"`.


### When built with the `infinispan` feature - _experimental_

#### `INFINISPAN_CACHE_NAME`
Expand All @@ -431,15 +414,13 @@ require Redis.
- Optional. By default, Limitador will use a cache called `"limitador"`.
- Format: `string`.


#### `INFINISPAN_COUNTERS_CONSISTENCY`

- Defines the consistency mode for the Infinispan counters created by Limitador.
This variable applies only when [`INFINISPAN_URL`](#infinispan_url) is set.
- Optional. Defaults to `"strong"`.
- Format: `enum`: `"Strong"` or `"Weak"`.


#### `INFINISPAN_URL`

- Infinispan URL. Required only when you want to use Infinispan to store the
Expand All @@ -448,12 +429,12 @@ require Redis.
require Infinispan.
- Format: `URL`, in the format of `http://username:[email protected]:11222`.


#### `RATE_LIMIT_HEADERS`

- Enables rate limit response headers. Only supported by the RLS server.
- Optional. Defaults to `"NONE"`.
- Must be one of:
- `"NONE"` - Does not add any additional headers to the http response.
- `"DRAFT_VERSION_03"`. Adds response headers per https://datatracker.ietf.org/doc/id/draft-polli-ratelimit-headers-03.html
- `"NONE"` - Does not add any additional headers to the http response.
- `"DRAFT_VERSION_03"`. Adds response headers
per https://datatracker.ietf.org/doc/id/draft-polli-ratelimit-headers-03.html

20 changes: 5 additions & 15 deletions limitador-server/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ pub struct Configuration {
http_host: String,
http_port: u16,
pub limit_name_in_labels: bool,
pub tracing_host: String,
tracing_port: u16,
pub tracing_endpoint: String,
pub log_level: Option<LevelFilter>,
pub rate_limit_headers: RateLimitHeaders,
pub grpc_reflection_service: bool,
Expand All @@ -47,8 +46,7 @@ pub mod env {
pub static ref ENVOY_RLS_PORT: Option<&'static str> = value_for("ENVOY_RLS_PORT");
pub static ref HTTP_API_HOST: Option<&'static str> = value_for("HTTP_API_HOST");
pub static ref HTTP_API_PORT: Option<&'static str> = value_for("HTTP_API_PORT");
pub static ref TRACING_HOST: Option<&'static str> = value_for("TRACING_HOST");
pub static ref TRACING_PORT: Option<&'static str> = value_for("TRACING_PORT");
pub static ref TRACING_ENDPOINT: Option<&'static str> = value_for("TRACING_ENDPOINT");
pub static ref DISK_PATH: Option<&'static str> = value_for("DISK_PATH");
pub static ref DISK_OPTIMIZE: Option<&'static str> = value_for("DISK_OPTIMIZE");
pub static ref REDIS_URL: Option<&'static str> = value_for("REDIS_URL");
Expand Down Expand Up @@ -76,7 +74,6 @@ pub mod env {
impl Configuration {
pub const DEFAULT_RLS_PORT: &'static str = "8081";
pub const DEFAULT_HTTP_PORT: &'static str = "8080";
pub const DEFAULT_TRACING_PORT: &'static str = "4317";
pub const DEFAULT_IP_BIND: &'static str = "0.0.0.0";

#[allow(clippy::too_many_arguments)]
Expand All @@ -88,8 +85,7 @@ impl Configuration {
http_host: String,
http_port: u16,
limit_name_in_labels: bool,
tracing_host: String,
tracing_port: u16,
tracing_endpoint: String,
rate_limit_headers: RateLimitHeaders,
grpc_reflection_service: bool,
) -> Self {
Expand All @@ -101,8 +97,7 @@ impl Configuration {
http_host,
http_port,
limit_name_in_labels,
tracing_host,
tracing_port,
tracing_endpoint,
log_level: None,
rate_limit_headers,
grpc_reflection_service,
Expand All @@ -116,10 +111,6 @@ impl Configuration {
pub fn http_address(&self) -> String {
format!("{}:{}", self.http_host, self.http_port)
}

pub fn tracing_address(&self) -> String {
format!("{}:{}", self.tracing_host, self.tracing_port)
}
}

#[cfg(test)]
Expand All @@ -135,8 +126,7 @@ impl Default for Configuration {
http_host: "".to_string(),
http_port: 0,
limit_name_in_labels: false,
tracing_host: "".to_string(),
tracing_port: 0,
tracing_endpoint: "".to_string(),
log_level: None,
rate_limit_headers: RateLimitHeaders::None,
grpc_reflection_service: false,
Expand Down
Loading

0 comments on commit 0e3f68a

Please sign in to comment.