Skip to content

Commit e3fcb42

Browse files
authored
Merge pull request #47 from frigus02/compression
gzip compression for requests
2 parents f6a61a1 + 732ae20 commit e3fcb42

File tree

8 files changed

+40
-5
lines changed

8 files changed

+40
-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: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use crate::{models::Envelope, Error, HttpClient};
22
use bytes::Bytes;
3+
use flate2::{write::GzEncoder, Compression};
34
use http::{Request, Response, Uri};
45
use serde::Deserialize;
56
#[cfg(feature = "metrics")]
67
use std::io::Read;
8+
use std::io::Write;
79

810
const STATUS_OK: u16 = 200;
911
const STATUS_PARTIAL_CONTENT: u16 = 206;
@@ -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,20 @@ 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+
// Weirdly gzip_encoder.write_all(serde_json::to_vec()) seems to be faster than
88+
// serde_json::to_writer(gzip_encoder). In a local test operating on items that result in
89+
// ~13MiB of JSON, this is what I've seen:
90+
// gzip_encoder.write_all(serde_json::to_vec()): 159ms
91+
// serde_json::to_writer(gzip_encoder): 247ms
92+
let serialized = serde_json::to_vec(&items).map_err(Error::UploadSerializeRequest)?;
93+
let mut gzip_encoder = GzEncoder::new(Vec::new(), Compression::default());
94+
gzip_encoder
95+
.write_all(&serialized)
96+
.map_err(Error::UploadCompressRequest)?;
97+
gzip_encoder.finish().map_err(Error::UploadCompressRequest)
98+
}
99+
82100
fn handle_response(response: Response<Bytes>) -> Result<(), Error> {
83101
match response.status().as_u16() {
84102
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)