use crate::context::trace_context::TracingContext;
use crate::skywalking_proto::v3::trace_segment_report_service_client::TraceSegmentReportServiceClient;
use crate::skywalking_proto::v3::SegmentObject;
use std::error::Error;
use tokio::sync::mpsc;
use tonic::transport::Channel;
pub type ReporterClient = TraceSegmentReportServiceClient<Channel>;
async fn flush(client: &mut ReporterClient, context: SegmentObject) -> Result<(), tonic::Status> {
let stream = async_stream::stream! {
yield context;
};
match client.collect(stream).await {
Ok(_) => Ok(()),
Err(e) => Err(e),
}
}
pub struct Reporter {
tx: mpsc::Sender<TracingContext>,
shutdown_tx: mpsc::Sender<()>,
}
static CHANNEL_BUF_SIZE: usize = 1024;
impl Reporter {
pub async fn start(address: impl Into<String>) -> Self {
let (tx, mut rx): (mpsc::Sender<TracingContext>, mpsc::Receiver<TracingContext>) =
mpsc::channel(CHANNEL_BUF_SIZE);
let (shutdown_tx, mut shutdown_rx) = mpsc::channel(1);
let mut reporter = ReporterClient::connect(address.into()).await.unwrap();
tokio::spawn(async move {
loop {
tokio::select! {
message = rx.recv() => {
if let Some(message) = message {
flush(&mut reporter, message.convert_segment_object()).await.unwrap();
} else {
break;
}
},
_ = shutdown_rx.recv() => {
break;
}
}
}
rx.close();
while let Some(message) = rx.recv().await {
flush(&mut reporter, message.convert_segment_object())
.await
.unwrap();
}
});
Self { tx, shutdown_tx }
}
pub async fn shutdown(self) -> Result<(), Box<dyn Error>> {
self.shutdown_tx.send(()).await?;
self.shutdown_tx.closed().await;
Ok(())
}
pub fn sender(&self) -> mpsc::Sender<TracingContext> {
self.tx.clone()
}
}