Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
db9f4ca
wip commit
tobz Jan 19, 2023
e5280d9
wip
tobz Jan 20, 2023
a22763e
massive rework
tobz Jan 30, 2023
0ab950b
Merge branch 'master' into tobz/rewrite-statsd-sink
tobz Jan 30, 2023
bacf1ff
add example metadata
tobz Jan 30, 2023
a17e839
port doc examples + keepalive for TCP
tobz Jan 30, 2023
8609e9f
Merge branch 'master' into tobz/rewrite-statsd-sink
tobz Feb 16, 2023
a08bc84
start refactoring based on PR feedback
tobz Feb 16, 2023
b32e933
Merge branch 'master' into tobz/rewrite-statsd-sink
tobz Feb 17, 2023
6037898
lot o cleanup
tobz Feb 17, 2023
f28379f
Merge branch 'master' into tobz/rewrite-statsd-sink
tobz Feb 22, 2023
cd9fe58
start futzing with an opaque wrapper for tcp/udp/udx
tobz Feb 22, 2023
8c1dd18
more
tobz Feb 23, 2023
36f5627
Merge branch 'master' into tobz/rewrite-statsd-sink
tobz Apr 11, 2023
577efa9
a bunch of rework to simplify the newer stuff
tobz Apr 11, 2023
f67a09e
revert unrelated changes to DD metrics sink
tobz Apr 11, 2023
f0f531b
fix tests + make encoding more efficient
tobz Apr 13, 2023
667ce41
clippy lint + trying to sort of socket2 stuff for cross-platform
tobz Apr 14, 2023
2144849
upgrade to tokio 1.27.0 + cleanup socket asfd/asrawfd stuff
tobz Apr 17, 2023
78e633b
Merge branch 'master' into tobz/rewrite-statsd-sink
tobz Apr 17, 2023
fe9a495
always include the unix related internal events
tobz Apr 17, 2023
392c4d7
fix booboos
tobz Apr 17, 2023
fce04a2
make generated docs line up
tobz Apr 17, 2023
332dff2
sighhhh
tobz Apr 17, 2023
7664aa7
bring in TLS support for TCP service
tobz Apr 18, 2023
35cde29
Merge branch 'master' into tobz/rewrite-statsd-sink
tobz Apr 18, 2023
292b171
set a default unix mode to avoid breaking change with addition of uni…
tobz Apr 19, 2023
1373f1e
Merge branch 'master' into tobz/rewrite-statsd-sink
tobz May 24, 2023
74d9bff
consolidate hostandport desc + remove unused UdpService
tobz May 24, 2023
f6d7292
some PR cleanup
tobz May 24, 2023
be7c5ef
fix fmt
tobz May 24, 2023
d35bcf4
fix handling of encoding request splits + add more accurate batch siz…
tobz May 25, 2023
43b3c3e
add missing file
tobz May 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/vector-common/src/internal_event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ impl From<&'static str> for Protocol {
}
}

impl From<Protocol> for SharedString {
fn from(value: Protocol) -> Self {
value.0
}
}

/// Macro to take care of some of the repetitive boilerplate in implementing a registered event. See
/// the other events in this module for examples of how to use this.
///
Expand Down
2 changes: 1 addition & 1 deletion src/internal_events/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub enum SocketMode {
}

impl SocketMode {
const fn as_str(self) -> &'static str {
pub const fn as_str(self) -> &'static str {
match self {
Self::Tcp => "tcp",
Self::Udp => "udp",
Expand Down
2 changes: 1 addition & 1 deletion src/internal_events/statsd_sink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use vector_common::internal_event::{
#[derive(Debug)]
pub struct StatsdInvalidMetricError<'a> {
pub value: &'a MetricValue,
pub kind: &'a MetricKind,
pub kind: MetricKind,
}

impl<'a> InternalEvent for StatsdInvalidMetricError<'a> {
Expand Down
28 changes: 28 additions & 0 deletions src/internal_events/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,34 @@ impl<E: std::fmt::Display> InternalEvent for UnixSocketSendError<'_, E> {
}
}

#[derive(Debug)]
pub struct UnixSendIncompleteError {
Comment thread
spencergilbert marked this conversation as resolved.
pub data_size: usize,
pub sent: usize,
}

impl InternalEvent for UnixSendIncompleteError {
fn emit(self) {
let reason = "Could not send all data in one Unix datagram.";
error!(
message = reason,
data_size = self.data_size,
sent = self.sent,
dropped = self.data_size - self.sent,
error_type = error_type::WRITER_FAILED,
stage = error_stage::SENDING,
internal_log_rate_limit = true,
);
counter!(
"component_errors_total", 1,
"error_type" => error_type::WRITER_FAILED,
"stage" => error_stage::SENDING,
);

emit!(ComponentEventsDropped::<UNINTENTIONAL> { count: 1, reason });
}
}

#[derive(Debug)]
pub struct UnixSocketFileDeleteError<'a> {
pub path: &'a Path,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub mod line_agg;
pub mod list;
#[cfg(any(feature = "sources-nats", feature = "sinks-nats"))]
pub(crate) mod nats;
pub mod net;
#[allow(unreachable_pub)]
pub(crate) mod proto;
pub mod providers;
Expand Down Expand Up @@ -111,7 +112,6 @@ pub mod trace;
#[allow(unreachable_pub)]
pub mod transforms;
pub mod types;
pub mod udp;
pub mod unit_test;
pub(crate) mod utilization;
pub mod validate;
Expand Down
50 changes: 50 additions & 0 deletions src/net.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use std::{io, os::fd::AsRawFd, time::Duration};

use socket2::{SockRef, TcpKeepalive};
use tokio::net::TcpStream;

/// Sets the receive buffer size for a socket.
///
/// This is the equivalent of setting the `SO_RCVBUF` socket setting directly.
///
/// # Errors
///
/// If there is an error setting the receive buffer size on the given socket, or if the value given
/// as the socket is not a valid socket, an error variant will be returned explaining the underlying
/// I/O error.
pub fn set_receive_buffer_size<S>(socket: &S, size: usize) -> io::Result<()>
where
S: AsRawFd,
{
SockRef::from(socket).set_recv_buffer_size(size)
}

/// Sets the send buffer size for a socket.
///
/// This is the equivalent of setting the `SO_SNDBUF` socket setting directly.
///
/// # Errors
///
/// If there is an error setting the send buffer size on the given socket, or if the value given
/// as the socket is not a valid socket, an error variant will be returned explaining the underlying
/// I/O error.
pub fn set_send_buffer_size<S>(socket: &S, size: usize) -> io::Result<()>
where
S: AsRawFd,
{
SockRef::from(socket).set_send_buffer_size(size)
}

/// Sets the TCP keepalive behavior on a socket.
///
/// This is the equivalent of setting the `SO_KEEPALIVE` and `TCP_KEEPALIVE` socket settings
/// directly.
///
/// # Errors
///
/// If there is an error with either enabling keepalive probes or setting the TCP keepalive idle
/// timeout on the given socket, an error variant will be returned explaining the underlying I/O
/// error.
pub fn set_keepalive(socket: &TcpStream, ttl: Duration) -> io::Result<()> {
SockRef::from(socket).set_tcp_keepalive(&TcpKeepalive::new().with_time(ttl))
}
116 changes: 76 additions & 40 deletions src/sinks/datadog/metrics/sink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,17 +179,16 @@ fn collapse_counters_by_series_and_timestamp(mut metrics: Vec<Metric>) -> Vec<Me
let mut idx = 0;
let now_ts = Utc::now().timestamp();

// For each metric, see if it's a counter. If so, we check the rest of the metrics
// _after_ it to see if they share the same series _and_ timestamp, when converted
// to a Unix timestamp. If they match, we take that counter's value and merge it
// with our "current" counter metric, and then drop the secondary one from the
// vector.
// For each metric, see if it's a counter. If so, we check the rest of the metrics _after_ it to
Comment thread
tobz marked this conversation as resolved.
Outdated
// see if they share the same series _and_ timestamp, when converted to a Unix timestamp. If
// they match, we take that counter's value and merge it with our "current" counter metric, and
// then drop the secondary one from the vector.
//
// For any non-counter, we simply ignore it and leave it as-is.
while idx < metrics.len() {
let curr_idx = idx;
let counter_ts = match metrics[curr_idx].value() {
MetricValue::Counter { .. } => metrics[curr_idx]
let outer_idx = idx;
let outer_counter_ts = match metrics[outer_idx].value() {
MetricValue::Counter { .. } => metrics[outer_idx]
.data()
.timestamp()
.map(|dt| dt.timestamp())
Expand All @@ -204,62 +203,75 @@ fn collapse_counters_by_series_and_timestamp(mut metrics: Vec<Metric>) -> Vec<Me
let mut accumulated_value = 0.0;
let mut accumulated_finalizers = EventFinalizers::default();

// Now go through each metric _after_ the current one to see if it matches the
// current metric: is a counter, with the same name and timestamp. If it is, we
// accumulate its value and then remove it.
// Now go through each metric _after_ the current one to see if it matches the current
// metric: is a counter, with the same name and timestamp. If it is, we accumulate its value
// and then remove it.
//
// Otherwise, we skip it.
let mut is_disjoint = false;
let mut should_advance_outer = true;
let mut had_match = false;
let mut inner_idx = curr_idx + 1;
let mut inner_idx = outer_idx + 1;
while inner_idx < metrics.len() {
let mut should_advance = true;
let mut should_advance_inner = true;
if let MetricValue::Counter { value } = metrics[inner_idx].value() {
let other_counter_ts = metrics[inner_idx]
.data()
.timestamp()
.map(|dt| dt.timestamp())
.unwrap_or(now_ts);
if metrics[curr_idx].series() == metrics[inner_idx].series()
&& counter_ts == other_counter_ts
{
let counters_match = {
let outer_counter_series = metrics[outer_idx].series();
let inner_counter_series = metrics[inner_idx].series();
let inner_counter_ts = metrics[inner_idx]
.data()
.timestamp()
.map(|dt| dt.timestamp())
.unwrap_or(now_ts);

outer_counter_series == inner_counter_series
&& outer_counter_ts == inner_counter_ts
};

if counters_match {
had_match = true;

// Collapse this counter by accumulating its value, and its
// finalizers, and removing it from the original vector of metrics.
// Collapse this counter by accumulating its value, and its finalizers, and
// removing it from the original vector of metrics.
accumulated_value += *value;

let mut old_metric = metrics.swap_remove(inner_idx);
accumulated_finalizers.merge(old_metric.metadata_mut().take_finalizers());
should_advance = false;

// We don't advance the inner loop index because since we just moved a
// yet-unseen metric into the slot of the metric we just collapsed, advancing
// past the current inner index would cause the inner loop to never evaluate the
// moved metric.
should_advance_inner = false;
} else {
// We hit a counter that _doesn't_ match, but we can't just skip
// it because we also need to evaluate it against all the
// counters that come after it, so we only increment the index
// for this inner loop.
//
// As well, we mark ourselves to stop incrementing the outer
// index if we find more counters to accumulate, because we've
// hit a disjoint counter here. While we may be continuing to
// shrink the count of remaining metrics from accumulating,
// we have to ensure this counter we just visited is visited by
// the outer loop.
is_disjoint = true;
// We hit a counter that _doesn't_ match, but since we need to ensure we
// evaluate all counters, we stop ourselves from advancing the outer loop index
// for the remainder of the inner loop.
should_advance_outer = false;
}
}

if should_advance {
// If we didn't consume/accumulate a counter in this iteration, we advance our inner
// loop index. Likewise, we can only advance the outer loop index if we advanced the
// inner loop index because we don't want the outer loop to skip any metrics that we
// moved when accumulating.
if should_advance_inner {
inner_idx += 1;

if !is_disjoint {
if should_advance_outer {
// We advance `idx`, which is where `outer_idx` is derived from, rather than
// `outer_idx` directly, since we need `outer_idx` to be stable so that the
// logic below has a stable index to get the mutable reference to the outer
// counter.
idx += 1;
}
}
}

// If we had matches during the accumulator phase, update our original counter.
if had_match {
let metric = metrics.get_mut(curr_idx).expect("current index must exist");
let metric = metrics
.get_mut(outer_idx)
.expect("current index must exist");
match metric.value_mut() {
MetricValue::Counter { value } => {
*value += accumulated_value;
Expand Down Expand Up @@ -373,6 +385,30 @@ mod tests {
assert_eq!(expected, actual);
}

#[test]
fn collapse_identical_metrics_counter_mixed() {
let counter_value = 42.0;
let input = vec![
create_counter("basic1", counter_value),
create_counter("basic2", counter_value),
create_counter("basic3", counter_value),
create_counter("basic1", counter_value),
create_counter("basic4", counter_value),
create_counter("basic3", counter_value),
create_counter("basic1", counter_value),
];

let expected = vec![
create_counter("basic1", counter_value * 3.0),
create_counter("basic2", counter_value),
create_counter("basic3", counter_value * 2.0),
create_counter("basic4", counter_value),
];
let actual = collapse_counters_by_series_and_timestamp(input);

assert_eq!(expected, actual);
}

#[derive(Eq, Ord, PartialEq, PartialOrd)]
struct MetricCollapseSort {
metric_type: &'static str,
Expand Down
Loading