Skip to content

Commit

Permalink
fix(gcp_stackdriver_metrics): Fixes GcpSeries serialization format wi…
Browse files Browse the repository at this point in the history
…thout breaking config. (#16394)

* fixes gcp stackdriver monitoring serialization

* adds test for serializing GcpSeries

* code formatting
  • Loading branch information
jasonahills authored Feb 21, 2023
1 parent 2b28408 commit 7cd20be
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 4 deletions.
71 changes: 69 additions & 2 deletions src/sinks/gcp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,25 @@ pub struct GcpPointValue {
pub int64_value: Option<i64>,
}

#[derive(Serialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct GcpMetric {
pub r#type: String,
pub labels: HashMap<String, String>,
}

#[derive(Serialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct GcpResource {
pub r#type: String,
pub labels: HashMap<String, String>,
}

#[derive(Serialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct GcpSerie<'a> {
pub metric: GcpTypedResource,
pub resource: GcpTypedResource,
pub metric: GcpMetric,
pub resource: GcpResource,
pub metric_kind: GcpMetricKind,
pub value_type: GcpValueType,
pub points: &'a [GcpPoint],
Expand Down Expand Up @@ -133,3 +147,56 @@ where
{
serialize_datetime(value.as_ref().expect("always defined"), serializer)
}

#[cfg(test)]
mod tests {
use super::*;

/// Ensures that serialized `GcpSeries` matches the format that GCP expects (https://cloud.google.com/monitoring/api/ref_v3/rest/v3/TimeSeries).
#[test]
fn serialize_gcp_series() {
let end_time = chrono::DateTime::from_utc(
chrono::NaiveDate::from_ymd(2023, 2, 14).and_hms(10, 00, 00),
chrono::Utc,
);
let gcp_series = GcpSeries {
time_series: &[GcpSerie {
metric: GcpMetric {
r#type: "custom.googleapis.com/my_namespace/metrics/my_metric".to_string(),
labels: [(
"my_metric_label".to_string(),
"my_metric_label_value".to_string(),
)]
.into(),
},
resource: GcpResource {
r#type: "my_resource".to_string(),
labels: [(
"my_resource_label".to_string(),
"my_resource_label_value".to_string(),
)]
.into(),
},
metric_kind: GcpMetricKind::Gauge,
value_type: GcpValueType::Int64,
points: &[GcpPoint {
interval: GcpInterval {
start_time: None,
end_time,
},
value: GcpPointValue {
int64_value: Some(10),
},
}],
}],
};

let serialized = serde_json::to_string(&gcp_series).unwrap();

// Convert to `serde_json::Value` so that field order does not matter.
let value: serde_json::Value = serde_json::from_str(&serialized).unwrap();
let expected: serde_json::Value = serde_json::from_str(r#"{"timeSeries":[{"metric":{"type":"custom.googleapis.com/my_namespace/metrics/my_metric","labels":{"my_metric_label":"my_metric_label_value"}},"resource":{"type":"my_resource","labels":{"my_resource_label":"my_resource_label_value"}},"metricKind":"GAUGE","valueType": "INT64","points":[{"interval":{"endTime":"2023-02-14T10:00:00.000000000Z"},"value":{"int64Value":"10"}}]}]}"#).unwrap();

assert_eq!(value, expected);
}
}
4 changes: 2 additions & 2 deletions src/sinks/gcp/stackdriver_metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,11 @@ impl HttpSink for HttpEventSink {

let series = gcp::GcpSeries {
time_series: &[gcp::GcpSerie {
metric: gcp::GcpTypedResource {
metric: gcp::GcpMetric {
r#type: metric_type,
labels: metric_labels,
},
resource: gcp::GcpTypedResource {
resource: gcp::GcpResource {
r#type: self.config.resource.r#type.clone(),
labels: self.config.resource.labels.clone(),
},
Expand Down

0 comments on commit 7cd20be

Please sign in to comment.