Skip to content

Commit 380d7ad

Browse files
authored
feat(prometheus): add more compression algorithms to Prometheus Remote Write (vectordotdev#17334)
Resolves vectordotdev#17199 - add Zstd and Gzip support to Prometheus Remote Write - add a new compression option in the config (Snappy is the default) - update the documentation Tested: - Local build
1 parent 2638cca commit 380d7ad

File tree

4 files changed

+77
-6
lines changed

4 files changed

+77
-6
lines changed

src/sinks/prometheus/remote_write.rs

+55-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::io::Read;
12
use std::sync::Arc;
23
use std::task;
34

@@ -123,10 +124,40 @@ pub struct RemoteWriteConfig {
123124
skip_serializing_if = "crate::serde::skip_serializing_if_default"
124125
)]
125126
pub acknowledgements: AcknowledgementsConfig,
127+
128+
#[configurable(derived)]
129+
#[configurable(metadata(docs::advanced))]
130+
#[serde(default)]
131+
pub compression: Compression,
126132
}
127133

128134
impl_generate_config_from_default!(RemoteWriteConfig);
129135

136+
/// Supported compression types for Prometheus Remote Write.
137+
#[configurable_component]
138+
#[derive(Clone, Copy, Debug, Derivative)]
139+
#[derivative(Default)]
140+
#[serde(rename_all = "lowercase")]
141+
pub enum Compression {
142+
/// Snappy.
143+
#[derivative(Default)]
144+
Snappy,
145+
146+
/// Gzip.
147+
Gzip,
148+
149+
/// Zstandard.
150+
Zstd,
151+
}
152+
153+
const fn convert_compression_to_content_encoding(compression: Compression) -> &'static str {
154+
match compression {
155+
Compression::Snappy => "snappy",
156+
Compression::Gzip => "gzip",
157+
Compression::Zstd => "zstd",
158+
}
159+
}
160+
130161
#[async_trait::async_trait]
131162
impl SinkConfig for RemoteWriteConfig {
132163
async fn build(
@@ -181,6 +212,7 @@ impl SinkConfig for RemoteWriteConfig {
181212
aws_region,
182213
credentials_provider,
183214
http_auth,
215+
compression: self.compression,
184216
});
185217

186218
let healthcheck = healthcheck(client.clone(), Arc::clone(&http_request_builder)).boxed();
@@ -190,6 +222,7 @@ impl SinkConfig for RemoteWriteConfig {
190222
buckets,
191223
quantiles,
192224
http_request_builder,
225+
compression: self.compression,
193226
};
194227

195228
let sink = {
@@ -277,6 +310,7 @@ struct RemoteWriteService {
277310
buckets: Vec<f64>,
278311
quantiles: Vec<f64>,
279312
http_request_builder: Arc<HttpRequestBuilder>,
313+
compression: Compression,
280314
}
281315

282316
impl RemoteWriteService {
@@ -312,7 +346,7 @@ impl Service<PartitionInnerBuffer<Vec<Metric>, PartitionKey>> for RemoteWriteSer
312346
fn call(&mut self, buffer: PartitionInnerBuffer<Vec<Metric>, PartitionKey>) -> Self::Future {
313347
let (events, key) = buffer.into_parts();
314348
let body = self.encode_events(events);
315-
let body = snap_block(body);
349+
let body = compress_block(self.compression, body);
316350

317351
let client = self.client.clone();
318352
let request_builder = Arc::clone(&self.http_request_builder);
@@ -344,6 +378,7 @@ pub struct HttpRequestBuilder {
344378
pub aws_region: Option<Region>,
345379
pub http_auth: Option<Auth>,
346380
pub credentials_provider: Option<SharedCredentialsProvider>,
381+
pub compression: Compression,
347382
}
348383

349384
impl HttpRequestBuilder {
@@ -353,11 +388,13 @@ impl HttpRequestBuilder {
353388
body: Vec<u8>,
354389
tenant_id: Option<String>,
355390
) -> Result<Request<hyper::Body>, crate::Error> {
391+
let content_encoding = convert_compression_to_content_encoding(self.compression);
392+
356393
let mut builder = http::Request::builder()
357394
.method(method)
358395
.uri(self.endpoint.clone())
359396
.header("X-Prometheus-Remote-Write-Version", "0.1.0")
360-
.header("Content-Encoding", "snappy")
397+
.header("Content-Encoding", content_encoding)
361398
.header("Content-Type", "application/x-protobuf");
362399

363400
if let Some(tenant_id) = &tenant_id {
@@ -380,10 +417,22 @@ impl HttpRequestBuilder {
380417
}
381418
}
382419

383-
fn snap_block(data: Bytes) -> Vec<u8> {
384-
snap::raw::Encoder::new()
385-
.compress_vec(&data)
386-
.expect("Out of memory")
420+
fn compress_block(compression: Compression, data: Bytes) -> Vec<u8> {
421+
match compression {
422+
Compression::Snappy => snap::raw::Encoder::new()
423+
.compress_vec(&data)
424+
.expect("snap compression failed, please report"),
425+
Compression::Gzip => {
426+
let mut buf = Vec::new();
427+
flate2::read::GzEncoder::new(data.as_ref(), flate2::Compression::default())
428+
.read_to_end(&mut buf)
429+
.expect("gzip compression failed, please report");
430+
buf
431+
}
432+
Compression::Zstd => {
433+
zstd::encode_all(data.as_ref(), 0).expect("zstd compression failed, please report")
434+
}
435+
}
387436
}
388437

389438
async fn sign_request(

website/cue/reference/components/sinks/base/prometheus_remote_write.cue

+12
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,18 @@ base: components: sinks: prometheus_remote_write: configuration: {
223223
items: type: float: {}
224224
}
225225
}
226+
compression: {
227+
description: "Supported compression types for Prometheus Remote Write."
228+
required: false
229+
type: string: {
230+
default: "snappy"
231+
enum: {
232+
gzip: "Gzip."
233+
snappy: "Snappy."
234+
zstd: "Zstandard."
235+
}
236+
}
237+
}
226238
default_namespace: {
227239
description: """
228240
The default namespace for any metrics sent.

website/cue/reference/components/sinks/prometheus_remote_write.cue

+9
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,14 @@ components: sinks: prometheus_remote_write: {
100100
values for each name, Vector will only send the last value specified.
101101
"""
102102
}
103+
compression_schemes: {
104+
title: "Compression schemes"
105+
body: """
106+
Officially according to the [Prometheus Remote-Write specification](\(urls.prometheus_remote_write_spec)),
107+
the only supported compression scheme is [Snappy](\(urls.snappy)). However,
108+
there are a number of other implementations that do support other schemes. Thus
109+
Vector also supports using Gzip and Zstd.
110+
"""
111+
}
103112
}
104113
}

website/cue/reference/urls.cue

+1
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ urls: {
412412
prometheus_remote_integrations: "https://prometheus.io/docs/operating/integrations/#remote-endpoints-and-storage"
413413
prometheus_remote_write: "https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write"
414414
prometheus_remote_write_protocol: "https://docs.google.com/document/d/1LPhVRSFkGNSuU1fBd81ulhsCPR4hkSZyyBj1SZ8fWOM/edit#heading=h.n0d0vphea3fe"
415+
prometheus_remote_write_spec: "https://prometheus.io/docs/concepts/remote_write_spec/#protocol"
415416
protobuf: "https://developers.google.com/protocol-buffers"
416417
pulsar: "https://pulsar.apache.org/"
417418
pulsar_protocol: "https://pulsar.apache.org/docs/en/develop-binary-protocol/"

0 commit comments

Comments
 (0)