Skip to content

Commit

Permalink
Merge pull request #34 from dwdking/dwdking/default-tags
Browse files Browse the repository at this point in the history
Adding default tags to Options and Client and sending the default tags with each metric and event
  • Loading branch information
mcasper authored Apr 13, 2022
2 parents 2a4283d + 90f844d commit c2e1bfa
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 17 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ let default_options = Options::default();
let default_client = Client::new(default_options).unwrap();

// Binds to 127.0.0.1:9000 for transmitting and sends to 10.1.2.3:8125, with a
// namespace of "analytics".
let custom_options = Options::new("127.0.0.1:9000", "10.1.2.3:8125", "analytics");
// namespace of "analytics", and a default tag of "region:west".
let custom_options = Options::new("127.0.0.1:9000", "10.1.2.3:8125", "analytics", "region:west");
let custom_client = Client::new(custom_options).unwrap();
```

Expand Down
41 changes: 33 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
//!
//! // Binds to 127.0.0.1:9000 for transmitting and sends to 10.1.2.3:8125, with a
//! // namespace of "analytics".
//! let custom_options = Options::new("127.0.0.1:9000", "10.1.2.3:8125", "analytics");
//! let custom_options = Options::new("127.0.0.1:9000", "10.1.2.3:8125", "analytics", vec!(String::new()));
//! let custom_client = Client::new(custom_options).unwrap();
//! ```
//!
Expand Down Expand Up @@ -73,7 +73,7 @@
extern crate chrono;

use chrono::Utc;
use std::net::UdpSocket;
use std::{net::UdpSocket};
use std::borrow::Cow;

mod error;
Expand All @@ -96,6 +96,8 @@ pub struct Options {
pub to_addr: String,
/// A namespace to prefix all metrics with, joined with a '.'.
pub namespace: String,
/// Default tags to include with every request.
pub default_tags: Vec<String>
}

impl Default for Options {
Expand All @@ -113,6 +115,7 @@ impl Default for Options {
/// from_addr: "127.0.0.1:0".into(),
/// to_addr: "127.0.0.1:8125".into(),
/// namespace: String::new(),
/// default_tags: vec!()
/// },
/// options
/// )
Expand All @@ -122,6 +125,7 @@ impl Default for Options {
from_addr: "127.0.0.1:0".into(),
to_addr: "127.0.0.1:8125".into(),
namespace: String::new(),
default_tags: vec!()
}
}

Expand All @@ -135,13 +139,14 @@ impl Options {
/// ```
/// use dogstatsd::Options;
///
/// let options = Options::new("127.0.0.1:9000", "127.0.0.1:9001", "");
/// let options = Options::new("127.0.0.1:9000", "127.0.0.1:9001", "", vec!(String::new()));
/// ```
pub fn new(from_addr: &str, to_addr: &str, namespace: &str) -> Self {
pub fn new(from_addr: &str, to_addr: &str, namespace: &str, default_tags: Vec<String>) -> Self {
Options {
from_addr: from_addr.into(),
to_addr: to_addr.into(),
namespace: namespace.into(),
default_tags: default_tags
}
}
}
Expand All @@ -153,14 +158,16 @@ pub struct Client {
from_addr: String,
to_addr: String,
namespace: String,
default_tags: Vec<u8>
}

impl PartialEq for Client {
fn eq(&self, other: &Self) -> bool {
// Ignore `socket`, which will never be the same
self.from_addr == other.from_addr &&
self.to_addr == other.to_addr &&
self.namespace == other.namespace
self.namespace == other.namespace &&
self.default_tags == other.default_tags
}
}

Expand All @@ -180,6 +187,7 @@ impl Client {
from_addr: options.from_addr,
to_addr: options.to_addr,
namespace: options.namespace,
default_tags: options.default_tags.join(",").into_bytes()
})
}

Expand Down Expand Up @@ -424,8 +432,8 @@ impl Client {
where I: IntoIterator<Item=S>,
M: Metric,
S: AsRef<str>,
{
let formatted_metric = format_for_send(metric, &self.namespace, tags);
{
let formatted_metric = format_for_send(metric, &self.namespace, tags, &self.default_tags);
self.socket.send_to(formatted_metric.as_slice(), &self.to_addr)?;
Ok(())
}
Expand All @@ -442,6 +450,7 @@ mod tests {
from_addr: "127.0.0.1:0".into(),
to_addr: "127.0.0.1:8125".into(),
namespace: String::new(),
..Default::default()
};

assert_eq!(expected_options, options)
Expand All @@ -455,6 +464,22 @@ mod tests {
from_addr: "127.0.0.1:0".into(),
to_addr: "127.0.0.1:8125".into(),
namespace: String::new(),
default_tags: String::new().into_bytes()
};

assert_eq!(expected_client, client)
}

#[test]
fn test_new_default_tags() {
let options = Options::new("127.0.0.1:0", "127.0.0.1:8125", "", vec!(String::from("tag1:tag1val")));
let client = Client::new(options).unwrap();
let expected_client = Client {
socket: UdpSocket::bind("127.0.0.1:0").unwrap(),
from_addr: "127.0.0.1:0".into(),
to_addr: "127.0.0.1:8125".into(),
namespace: String::new(),
default_tags: String::from("tag1:tag1val").into_bytes()
};

assert_eq!(expected_client, client)
Expand All @@ -463,7 +488,7 @@ mod tests {
use metrics::GaugeMetric;
#[test]
fn test_send() {
let options = Options::new("127.0.0.1:9001", "127.0.0.1:9002", "");
let options = Options::new("127.0.0.1:9001", "127.0.0.1:9002", "", vec!());
let client = Client::new(options).unwrap();
// Shouldn't panic or error
client.send(&GaugeMetric::new("gauge".into(), "1234".into()), &["tag1", "tag2"]).unwrap();
Expand Down
39 changes: 32 additions & 7 deletions src/metrics.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use chrono::{DateTime, Utc};

pub fn format_for_send<M, I, S>(in_metric: &M, in_namespace: &str, tags: I) -> Vec<u8>
pub fn format_for_send<M, I, S>(in_metric: &M, in_namespace: &str, tags: I, default_tags: &Vec<u8>) -> Vec<u8>
where M: Metric,
I: IntoIterator<Item=S>,
S: AsRef<str>,
Expand All @@ -22,8 +22,9 @@ pub fn format_for_send<M, I, S>(in_metric: &M, in_namespace: &str, tags: I) -> V

let mut tags_iter = tags.into_iter();
let mut next_tag = tags_iter.next();
let has_tags = next_tag.is_some();

if next_tag.is_some() {
if next_tag.is_some() || !default_tags.is_empty() {
buf.extend_from_slice(b"|#");
}

Expand All @@ -37,6 +38,14 @@ pub fn format_for_send<M, I, S>(in_metric: &M, in_namespace: &str, tags: I) -> V
}
}

if !default_tags.is_empty() {
if has_tags {
buf.extend_from_slice(b",")
}

buf.extend_from_slice(&default_tags);
}

buf
}

Expand Down Expand Up @@ -390,31 +399,47 @@ mod tests {
fn test_format_for_send_no_tags() {
assert_eq!(
&b"namespace.foo:1|c"[..],
&format_for_send(&CountMetric::Incr("foo"), "namespace", &[] as &[String])[..]
&format_for_send(&CountMetric::Incr("foo"), "namespace", &[] as &[String], &String::default().into_bytes())[..]
)
}

#[test]
fn test_format_for_send_no_namespace() {
assert_eq!(
&b"foo:1|c|#tag:1,tag:2"[..],
&format_for_send(&CountMetric::Incr("foo"), "", &["tag:1", "tag:2"])[..]
&format_for_send(&CountMetric::Incr("foo"), "", &["tag:1", "tag:2"], &String::default().into_bytes())[..]
)
}

#[test]
fn test_format_for_no_default_tags() {
assert_eq!(
&b"namespace.foo:1|c|#tag:1,tag:2,defaultag:3,seconddefault:4"[..],
&format_for_send(&CountMetric::Incr("foo"), "namespace", &["tag:1", "tag:2"], &String::from("defaultag:3,seconddefault:4").into_bytes())[..]
)
}

#[test]
fn test_format_for_send_everything() {
assert_eq!(
&b"namespace.foo:1|c|#tag:1,tag:2"[..],
&format_for_send(&CountMetric::Incr("foo"), "namespace", &["tag:1", "tag:2"])[..]
&b"namespace.foo:1|c|#tag:1,tag:2,defaultag:3,seconddefault:4"[..],
&format_for_send(&CountMetric::Incr("foo"), "namespace", &["tag:1", "tag:2"], &String::from("defaultag:3,seconddefault:4").into_bytes())[..]
)
}

#[test]
fn test_format_for_send_everything_omit_namespace() {
assert_eq!(
&b"_e{5,4}:title|text|#tag:1,tag:2"[..],
&format_for_send(&Event::new("title".into(), "text".into()), "namespace", &["tag:1", "tag:2"])[..]
&format_for_send(&Event::new("title".into(), "text".into()), "namespace", &["tag:1", "tag:2"], &String::default().into_bytes())[..]
)
}

#[test]
fn test_format_with_only_default_tags() {
assert_eq!(
&b"namespace.foo:1|c|#defaultag:3,seconddefault:4"[..],
&format_for_send(&CountMetric::Incr("foo"), "namespace", &[] as &[String], &String::from("defaultag:3,seconddefault:4").into_bytes())[..]
)
}

Expand Down

0 comments on commit c2e1bfa

Please sign in to comment.