Skip to content

Commit 56779f4

Browse files
committed
gzip compression for requests
Application Insights supports gzip compression for requests to `POST /v2/track`. When sending lots of telemetry items, network time starts to be the limiting factor and compression helps with this. Gzip compression is turned on by default and cannot be disabled. As far as I can tell this is the same behaviour as the Application Insights .NET SDK. If compression turns out to be an issue for some users, it could be made optional in the future.
1 parent f6a61a1 commit 56779f4

File tree

8 files changed

+32
-5
lines changed

8 files changed

+32
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77

88
## [Unreleased]
99

10+
- Use gzip compression (`Content-Encoding: gzip`) for `POST /v2/track` HTTP request.
11+
1012
## [0.19.0] - 2022-01-23
1113

1214
- Upgrade to `v0.17.0` of `opentelemetry`.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ metrics = ["opentelemetry/metrics", "ureq"]
3434
async-trait = "0.1"
3535
bytes = "1"
3636
chrono = "0.4"
37+
flate2 = "1"
3738
http = "0.2"
3839
once_cell = "1"
3940
opentelemetry = "0.17"

src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,13 @@ pub enum Error {
511511
#[error("serializing upload request failed with {0}")]
512512
UploadSerializeRequest(serde_json::Error),
513513

514+
/// Application Insights telemetry data failed serialize or compress. Telemetry reporting failed
515+
/// because of this.
516+
///
517+
/// Note: This is an error in this crate. If you spot this, please open an issue.
518+
#[error("compressing upload request failed with {0}")]
519+
UploadCompressRequest(std::io::Error),
520+
514521
/// Application Insights telemetry response failed to deserialize from JSON.
515522
///
516523
/// Telemetry reporting may have worked. But since we could not look into the response, we

src/uploader.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::{models::Envelope, Error, HttpClient};
22
use bytes::Bytes;
3+
use flate2::write::GzEncoder;
4+
use flate2::Compression;
35
use http::{Request, Response, Uri};
46
use serde::Deserialize;
57
#[cfg(feature = "metrics")]
@@ -33,9 +35,10 @@ pub(crate) async fn send(
3335
endpoint: &Uri,
3436
items: Vec<Envelope>,
3537
) -> Result<(), Error> {
36-
let payload = serde_json::to_vec(&items).map_err(Error::UploadSerializeRequest)?;
38+
let payload = serialize_request_body(items)?;
3739
let request = Request::post(endpoint)
3840
.header(http::header::CONTENT_TYPE, "application/json")
41+
.header(http::header::CONTENT_ENCODING, "gzip")
3942
.body(payload)
4043
.expect("request should be valid");
4144

@@ -50,11 +53,12 @@ pub(crate) async fn send(
5053
/// Sends a telemetry items to the server.
5154
#[cfg(feature = "metrics")]
5255
pub(crate) fn send_sync(endpoint: &Uri, items: Vec<Envelope>) -> Result<(), Error> {
53-
let payload = serde_json::to_vec(&items).map_err(Error::UploadSerializeRequest)?;
56+
let payload = serialize_request_body(items)?;
5457

5558
// TODO Implement retries
5659
let response = match ureq::post(&endpoint.to_string())
5760
.set(http::header::CONTENT_TYPE.as_str(), "application/json")
61+
.set(http::header::CONTENT_ENCODING.as_str(), "gzip")
5862
.send_bytes(&payload)
5963
{
6064
Ok(response) => response,
@@ -79,6 +83,12 @@ pub(crate) fn send_sync(endpoint: &Uri, items: Vec<Envelope>) -> Result<(), Erro
7983
)
8084
}
8185

86+
fn serialize_request_body(items: Vec<Envelope>) -> Result<Vec<u8>, Error> {
87+
let mut gzip_encoder = GzEncoder::new(Vec::new(), Compression::default());
88+
serde_json::to_writer(&mut gzip_encoder, &items).map_err(Error::UploadSerializeRequest)?;
89+
gzip_encoder.finish().map_err(Error::UploadCompressRequest)
90+
}
91+
8292
fn handle_response(response: Response<Bytes>) -> Result<(), Error> {
8393
match response.status().as_u16() {
8494
STATUS_OK => Ok(()),

tests/http_requests.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ mod tick {
206206
}
207207

208208
mod format {
209+
use flate2::read::GzDecoder;
209210
use http::Request;
210211
use regex::Regex;
211212

@@ -250,7 +251,9 @@ mod format {
250251
}
251252

252253
fn pretty_print_json(body: &[u8]) -> String {
253-
let json: serde_json::Value = serde_json::from_slice(body).expect("body is valid json");
254+
let gzip_decoder = GzDecoder::new(body);
255+
let json: serde_json::Value =
256+
serde_json::from_reader(gzip_decoder).expect("body is valid json");
254257
serde_json::to_string_pretty(&json).unwrap()
255258
}
256259
}

tests/snapshots/http_requests__traces_batch_async_std.snap

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
---
22
source: tests/http_requests.rs
3-
assertion_line: 131
3+
assertion_line: 100
44
expression: traces_batch_async_std
55

66
---
77
POST /v2/track HTTP/1.1
88
host: dc.services.visualstudio.com
99
content-type: application/json
10+
content-encoding: gzip
1011

1112
[
1213
{

tests/snapshots/http_requests__traces_batch_tokio.snap

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
---
22
source: tests/http_requests.rs
3-
assertion_line: 145
3+
assertion_line: 114
44
expression: traces_batch_tokio
55

66
---
77
POST /v2/track HTTP/1.1
88
host: dc.services.visualstudio.com
99
content-type: application/json
10+
content-encoding: gzip
1011

1112
[
1213
{

tests/snapshots/http_requests__traces_simple.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ expression: traces_simple
77
POST /v2/track HTTP/1.1
88
host: dc.services.visualstudio.com
99
content-type: application/json
10+
content-encoding: gzip
1011

1112
[
1213
{
@@ -92,6 +93,7 @@ content-type: application/json
9293
POST /v2/track HTTP/1.1
9394
host: dc.services.visualstudio.com
9495
content-type: application/json
96+
content-encoding: gzip
9597

9698
[
9799
{

0 commit comments

Comments
 (0)