mirror of
https://github.com/neondatabase/neon.git
synced 2026-05-31 03:50:37 +00:00
feat(proxy): add direction and private link id to billing export (#10925)
ref: https://github.com/neondatabase/cloud/issues/23385 Adds a direction flag as well as private-link ID to the traffic reporting pipeline. We do not yet actually count ingress, but we include the flag anyway. I have additionally moved vpce_id string parsing earlier, since we expect it to be utf8 (ascii).
This commit is contained in:
@@ -75,10 +75,7 @@ impl PoolingBackend {
|
||||
let extra = ctx.extra();
|
||||
let incoming_endpoint_id = match extra {
|
||||
None => String::new(),
|
||||
Some(ConnectionInfoExtra::Aws { vpce_id }) => {
|
||||
// Convert the vcpe_id to a string
|
||||
String::from_utf8(vpce_id.to_vec()).unwrap_or_default()
|
||||
}
|
||||
Some(ConnectionInfoExtra::Aws { vpce_id }) => vpce_id.to_string(),
|
||||
Some(ConnectionInfoExtra::Azure { link_id }) => link_id.to_string(),
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ use clashmap::ClashMap;
|
||||
use parking_lot::RwLock;
|
||||
use postgres_client::ReadyForQueryStatus;
|
||||
use rand::Rng;
|
||||
use smol_str::ToSmolStr;
|
||||
use tracing::{debug, info, Span};
|
||||
|
||||
use super::backend::HttpConnError;
|
||||
@@ -19,8 +20,9 @@ use crate::auth::backend::ComputeUserInfo;
|
||||
use crate::context::RequestContext;
|
||||
use crate::control_plane::messages::{ColdStartInfo, MetricsAuxInfo};
|
||||
use crate::metrics::{HttpEndpointPoolsGuard, Metrics};
|
||||
use crate::protocol2::ConnectionInfoExtra;
|
||||
use crate::types::{DbName, EndpointCacheKey, RoleName};
|
||||
use crate::usage_metrics::{Ids, MetricCounter, USAGE_METRICS};
|
||||
use crate::usage_metrics::{Ids, MetricCounter, TrafficDirection, USAGE_METRICS};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct ConnInfo {
|
||||
@@ -473,7 +475,9 @@ where
|
||||
.http_pool_opened_connections
|
||||
.get_metric()
|
||||
.dec_by(clients_removed as i64);
|
||||
info!("pool: performed global pool gc. removed {clients_removed} clients, total number of clients in pool is {size}");
|
||||
info!(
|
||||
"pool: performed global pool gc. removed {clients_removed} clients, total number of clients in pool is {size}"
|
||||
);
|
||||
}
|
||||
let removed = current_len - new_len;
|
||||
|
||||
@@ -635,15 +639,28 @@ impl<C: ClientInnerExt> Client<C> {
|
||||
(&mut inner.inner, Discard { conn_info, pool })
|
||||
}
|
||||
|
||||
pub(crate) fn metrics(&self) -> Arc<MetricCounter> {
|
||||
pub(crate) fn metrics(
|
||||
&self,
|
||||
direction: TrafficDirection,
|
||||
ctx: &RequestContext,
|
||||
) -> Arc<MetricCounter> {
|
||||
let aux = &self
|
||||
.inner
|
||||
.as_ref()
|
||||
.expect("client inner should not be removed")
|
||||
.aux;
|
||||
|
||||
let private_link_id = match ctx.extra() {
|
||||
None => None,
|
||||
Some(ConnectionInfoExtra::Aws { vpce_id }) => Some(vpce_id.clone()),
|
||||
Some(ConnectionInfoExtra::Azure { link_id }) => Some(link_id.to_smolstr()),
|
||||
};
|
||||
|
||||
USAGE_METRICS.register(Ids {
|
||||
endpoint_id: aux.endpoint_id,
|
||||
branch_id: aux.branch_id,
|
||||
direction,
|
||||
private_link_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -700,7 +717,9 @@ impl<C: ClientInnerExt> Discard<'_, C> {
|
||||
pub(crate) fn discard(&mut self) {
|
||||
let conn_info = &self.conn_info;
|
||||
if std::mem::take(self.pool).strong_count() > 0 {
|
||||
info!("pool: throwing away connection '{conn_info}' because connection is potentially in a broken state");
|
||||
info!(
|
||||
"pool: throwing away connection '{conn_info}' because connection is potentially in a broken state"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::sync::{Arc, Weak};
|
||||
use hyper::client::conn::http2;
|
||||
use hyper_util::rt::{TokioExecutor, TokioIo};
|
||||
use parking_lot::RwLock;
|
||||
use smol_str::ToSmolStr;
|
||||
use tokio::net::TcpStream;
|
||||
use tracing::{debug, error, info, info_span, Instrument};
|
||||
|
||||
@@ -16,8 +17,9 @@ use super::conn_pool_lib::{
|
||||
use crate::context::RequestContext;
|
||||
use crate::control_plane::messages::{ColdStartInfo, MetricsAuxInfo};
|
||||
use crate::metrics::{HttpEndpointPoolsGuard, Metrics};
|
||||
use crate::protocol2::ConnectionInfoExtra;
|
||||
use crate::types::EndpointCacheKey;
|
||||
use crate::usage_metrics::{Ids, MetricCounter, USAGE_METRICS};
|
||||
use crate::usage_metrics::{Ids, MetricCounter, TrafficDirection, USAGE_METRICS};
|
||||
|
||||
pub(crate) type Send = http2::SendRequest<hyper::body::Incoming>;
|
||||
pub(crate) type Connect =
|
||||
@@ -264,11 +266,24 @@ impl<C: ClientInnerExt + Clone> Client<C> {
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
pub(crate) fn metrics(&self) -> Arc<MetricCounter> {
|
||||
pub(crate) fn metrics(
|
||||
&self,
|
||||
direction: TrafficDirection,
|
||||
ctx: &RequestContext,
|
||||
) -> Arc<MetricCounter> {
|
||||
let aux = &self.inner.aux;
|
||||
|
||||
let private_link_id = match ctx.extra() {
|
||||
None => None,
|
||||
Some(ConnectionInfoExtra::Aws { vpce_id }) => Some(vpce_id.clone()),
|
||||
Some(ConnectionInfoExtra::Azure { link_id }) => Some(link_id.to_smolstr()),
|
||||
};
|
||||
|
||||
USAGE_METRICS.register(Ids {
|
||||
endpoint_id: aux.endpoint_id,
|
||||
branch_id: aux.branch_id,
|
||||
direction,
|
||||
private_link_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ use crate::metrics::{HttpDirection, Metrics};
|
||||
use crate::proxy::{run_until_cancelled, NeonOptions};
|
||||
use crate::serverless::backend::HttpConnError;
|
||||
use crate::types::{DbName, RoleName};
|
||||
use crate::usage_metrics::{MetricCounter, MetricCounterRecorder};
|
||||
use crate::usage_metrics::{MetricCounter, MetricCounterRecorder, TrafficDirection};
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@@ -209,7 +209,7 @@ fn get_conn_info(
|
||||
}
|
||||
}
|
||||
Some(url::Host::Ipv4(_) | url::Host::Ipv6(_)) | None => {
|
||||
return Err(ConnInfoError::MissingHostname)
|
||||
return Err(ConnInfoError::MissingHostname);
|
||||
}
|
||||
};
|
||||
ctx.set_endpoint_id(endpoint.clone());
|
||||
@@ -745,7 +745,7 @@ async fn handle_db_inner(
|
||||
}
|
||||
};
|
||||
|
||||
let metrics = client.metrics();
|
||||
let metrics = client.metrics(TrafficDirection::Egress, ctx);
|
||||
|
||||
let len = json_output.len();
|
||||
let response = response
|
||||
@@ -818,7 +818,7 @@ async fn handle_auth_broker_inner(
|
||||
.expect("all headers and params received via hyper should be valid for request");
|
||||
|
||||
// todo: map body to count egress
|
||||
let _metrics = client.metrics();
|
||||
let _metrics = client.metrics(TrafficDirection::Egress, ctx);
|
||||
|
||||
Ok(client
|
||||
.inner
|
||||
@@ -1118,10 +1118,10 @@ enum Discard<'a> {
|
||||
}
|
||||
|
||||
impl Client {
|
||||
fn metrics(&self) -> Arc<MetricCounter> {
|
||||
fn metrics(&self, direction: TrafficDirection, ctx: &RequestContext) -> Arc<MetricCounter> {
|
||||
match self {
|
||||
Client::Remote(client) => client.metrics(),
|
||||
Client::Local(local_client) => local_client.metrics(),
|
||||
Client::Remote(client) => client.metrics(direction, ctx),
|
||||
Client::Local(local_client) => local_client.metrics(direction, ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user