Skip to content

Commit cbf1079

Browse files
authored
Add authentication and custom intercept support. (#50)
1 parent 4c61a5b commit cbf1079

File tree

5 files changed

+88
-50
lines changed

5 files changed

+88
-50
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ async fn handle_metric(mut metricer: Metricer) {
144144
async fn main() -> Result<(), Box<dyn Error>> {
145145
// Connect to skywalking oap server.
146146
let reporter = GrpcReporter::connect("http://0.0.0.0:11800").await?;
147+
// Optional authentication, based on backend setting.
148+
let reporter = reporter.with_authentication("<TOKEN>");
147149
148150
// Spawn the reporting in background, with listening the graceful shutdown signal.
149151
let handle = reporter

src/reporter/grpc.rs

Lines changed: 80 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ use tokio::{
4848
};
4949
use tonic::{
5050
async_trait,
51+
metadata::{Ascii, MetadataValue},
52+
service::{interceptor::InterceptedService, Interceptor},
5153
transport::{self, Channel, Endpoint},
54+
Request, Status,
5255
};
5356

5457
/// Special purpose, used for user-defined production operations. Generally, it
@@ -111,13 +114,31 @@ impl CollectItemConsume for mpsc::UnboundedReceiver<CollectItem> {
111114
}
112115
}
113116

117+
type DynInterceptHandler = dyn Fn(Request<()>) -> Result<Request<()>, Status> + Send + Sync;
118+
119+
#[derive(Default, Clone)]
120+
struct CustomInterceptor {
121+
authentication: Option<Arc<String>>,
122+
custom_intercept: Option<Arc<DynInterceptHandler>>,
123+
}
124+
125+
impl Interceptor for CustomInterceptor {
126+
fn call(&mut self, mut request: tonic::Request<()>) -> Result<tonic::Request<()>, Status> {
127+
if let Some(authentication) = &self.authentication {
128+
if let Ok(authentication) = authentication.parse::<MetadataValue<Ascii>>() {
129+
request
130+
.metadata_mut()
131+
.insert("authentication", authentication);
132+
}
133+
}
134+
if let Some(custom_intercept) = &self.custom_intercept {
135+
request = custom_intercept(request)?;
136+
}
137+
Ok(request)
138+
}
139+
}
140+
114141
struct Inner<P, C> {
115-
trace_client: Mutex<TraceSegmentReportServiceClient<Channel>>,
116-
log_client: Mutex<LogReportServiceClient<Channel>>,
117-
meter_client: Mutex<MeterReportServiceClient<Channel>>,
118-
#[cfg(feature = "management")]
119-
#[cfg_attr(docsrs, doc(cfg(feature = "management")))]
120-
management_client: Mutex<ManagementServiceClient<Channel>>,
121142
producer: P,
122143
consumer: Mutex<Option<C>>,
123144
is_reporting: AtomicBool,
@@ -131,6 +152,8 @@ pub type DynErrHandle = dyn Fn(Box<dyn Error>) + Send + Sync + 'static;
131152
pub struct GrpcReporter<P, C> {
132153
inner: Arc<Inner<P, C>>,
133154
err_handle: Arc<Option<Box<DynErrHandle>>>,
155+
channel: Channel,
156+
interceptor: CustomInterceptor,
134157
}
135158

136159
impl GrpcReporter<mpsc::UnboundedSender<CollectItem>, mpsc::UnboundedReceiver<CollectItem>> {
@@ -156,17 +179,14 @@ impl<P: CollectItemProduce, C: CollectItemConsume> GrpcReporter<P, C> {
156179
pub fn new_with_pc(channel: Channel, producer: P, consumer: C) -> Self {
157180
Self {
158181
inner: Arc::new(Inner {
159-
trace_client: Mutex::new(TraceSegmentReportServiceClient::new(channel.clone())),
160-
log_client: Mutex::new(LogReportServiceClient::new(channel.clone())),
161-
#[cfg(feature = "management")]
162-
management_client: Mutex::new(ManagementServiceClient::new(channel.clone())),
163-
meter_client: Mutex::new(MeterReportServiceClient::new(channel)),
164182
producer,
165183
consumer: Mutex::new(Some(consumer)),
166184
is_reporting: Default::default(),
167185
is_closed: Default::default(),
168186
}),
169187
err_handle: Default::default(),
188+
channel,
189+
interceptor: Default::default(),
170190
}
171191
}
172192

@@ -179,6 +199,22 @@ impl<P: CollectItemProduce, C: CollectItemConsume> GrpcReporter<P, C> {
179199
self
180200
}
181201

202+
/// Set the authentication header value. By default, the authentication is
203+
/// not set.
204+
pub fn with_authentication(mut self, authentication: impl Into<String>) -> Self {
205+
self.interceptor.authentication = Some(Arc::new(authentication.into()));
206+
self
207+
}
208+
209+
/// Set the custom intercept. By default, the custom intercept is not set.
210+
pub fn with_custom_intercept(
211+
mut self,
212+
custom_intercept: impl Fn(Request<()>) -> Result<Request<()>, Status> + Send + Sync + 'static,
213+
) -> Self {
214+
self.interceptor.custom_intercept = Some(Arc::new(custom_intercept));
215+
self
216+
}
217+
182218
/// Start to reporting.
183219
///
184220
/// # Panics
@@ -193,9 +229,28 @@ impl<P: CollectItemProduce, C: CollectItemConsume> GrpcReporter<P, C> {
193229
rb: ReporterAndBuffer {
194230
inner: Arc::clone(&self.inner),
195231
status_handle: None,
232+
196233
trace_buffer: Default::default(),
197234
log_buffer: Default::default(),
198235
meter_buffer: Default::default(),
236+
237+
trace_client: TraceSegmentReportServiceClient::with_interceptor(
238+
self.channel.clone(),
239+
self.interceptor.clone(),
240+
),
241+
log_client: LogReportServiceClient::with_interceptor(
242+
self.channel.clone(),
243+
self.interceptor.clone(),
244+
),
245+
meter_client: MeterReportServiceClient::with_interceptor(
246+
self.channel.clone(),
247+
self.interceptor.clone(),
248+
),
249+
#[cfg(feature = "management")]
250+
management_client: ManagementServiceClient::with_interceptor(
251+
self.channel.clone(),
252+
self.interceptor.clone(),
253+
),
199254
},
200255
shutdown_signal: Box::pin(pending()),
201256
consumer: self.inner.consumer.lock().await.take().unwrap(),
@@ -208,6 +263,8 @@ impl<P, C> Clone for GrpcReporter<P, C> {
208263
Self {
209264
inner: self.inner.clone(),
210265
err_handle: self.err_handle.clone(),
266+
channel: self.channel.clone(),
267+
interceptor: self.interceptor.clone(),
211268
}
212269
}
213270
}
@@ -227,9 +284,17 @@ impl<P: CollectItemProduce, C: CollectItemConsume> Report for GrpcReporter<P, C>
227284
struct ReporterAndBuffer<P, C> {
228285
inner: Arc<Inner<P, C>>,
229286
status_handle: Option<Box<dyn Fn(tonic::Status) + Send + 'static>>,
287+
230288
trace_buffer: LinkedList<SegmentObject>,
231289
log_buffer: LinkedList<LogData>,
232290
meter_buffer: LinkedList<MeterData>,
291+
292+
trace_client: TraceSegmentReportServiceClient<InterceptedService<Channel, CustomInterceptor>>,
293+
log_client: LogReportServiceClient<InterceptedService<Channel, CustomInterceptor>>,
294+
meter_client: MeterReportServiceClient<InterceptedService<Channel, CustomInterceptor>>,
295+
#[cfg(feature = "management")]
296+
#[cfg_attr(docsrs, doc(cfg(feature = "management")))]
297+
management_client: ManagementServiceClient<InterceptedService<Channel, CustomInterceptor>>,
233298
}
234299

235300
impl<P: CollectItemProduce, C: CollectItemConsume> ReporterAndBuffer<P, C> {
@@ -248,10 +313,7 @@ impl<P: CollectItemProduce, C: CollectItemConsume> ReporterAndBuffer<P, C> {
248313
#[cfg(feature = "management")]
249314
CollectItem::Instance(item) => {
250315
if let Err(e) = self
251-
.inner
252316
.management_client
253-
.lock()
254-
.await
255317
.report_instance_properties(*item)
256318
.await
257319
{
@@ -262,14 +324,7 @@ impl<P: CollectItemProduce, C: CollectItemConsume> ReporterAndBuffer<P, C> {
262324
}
263325
#[cfg(feature = "management")]
264326
CollectItem::Ping(item) => {
265-
if let Err(e) = self
266-
.inner
267-
.management_client
268-
.lock()
269-
.await
270-
.keep_alive(*item)
271-
.await
272-
{
327+
if let Err(e) = self.management_client.keep_alive(*item).await {
273328
if let Some(status_handle) = &self.status_handle {
274329
status_handle(e);
275330
}
@@ -279,29 +334,15 @@ impl<P: CollectItemProduce, C: CollectItemConsume> ReporterAndBuffer<P, C> {
279334

280335
if !self.trace_buffer.is_empty() {
281336
let buffer = take(&mut self.trace_buffer);
282-
if let Err(e) = self
283-
.inner
284-
.trace_client
285-
.lock()
286-
.await
287-
.collect(stream::iter(buffer))
288-
.await
289-
{
337+
if let Err(e) = self.trace_client.collect(stream::iter(buffer)).await {
290338
if let Some(status_handle) = &self.status_handle {
291339
status_handle(e);
292340
}
293341
}
294342
}
295343
if !self.log_buffer.is_empty() {
296344
let buffer = take(&mut self.log_buffer);
297-
if let Err(e) = self
298-
.inner
299-
.log_client
300-
.lock()
301-
.await
302-
.collect(stream::iter(buffer))
303-
.await
304-
{
345+
if let Err(e) = self.log_client.collect(stream::iter(buffer)).await {
305346
if let Some(status_handle) = &self.status_handle {
306347
status_handle(e);
307348
}
@@ -310,14 +351,7 @@ impl<P: CollectItemProduce, C: CollectItemConsume> ReporterAndBuffer<P, C> {
310351

311352
if !self.meter_buffer.is_empty() {
312353
let buffer = take(&mut self.meter_buffer);
313-
if let Err(e) = self
314-
.inner
315-
.meter_client
316-
.lock()
317-
.await
318-
.collect(stream::iter(buffer))
319-
.await
320-
{
354+
if let Err(e) = self.meter_client.collect(stream::iter(buffer)).await {
321355
if let Some(status_handle) = &self.status_handle {
322356
status_handle(e);
323357
}

src/reporter/print.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ impl PrintReporter {
4040
}
4141

4242
impl Report for PrintReporter {
43+
#[allow(clippy::print_stdout)]
4344
fn report(&self, items: CollectItem) {
4445
match items {
4546
CollectItem::Trace(data) => {

src/skywalking_proto/v3/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
//! Generated code of `skywalking.v3`, by `tonic`.
1818
1919
#![allow(missing_docs)]
20+
#![allow(rustdoc::invalid_html_tags)]
2021

2122
use crate::common::system_time::{fetch_time, TimePeriod};
2223

src/trace/trace_context.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ impl SpanStack {
5252
}
5353

5454
pub(crate) fn with_finalized_mut<T>(&self, f: impl FnOnce(&mut Vec<SpanObject>) -> T) -> T {
55-
f(&mut *self.finalized.try_write().expect(LOCK_MSG))
55+
f(&mut self.finalized.try_write().expect(LOCK_MSG))
5656
}
5757

5858
pub(crate) fn with_active<T>(&self, f: impl FnOnce(&Vec<SpanObject>) -> T) -> T {
59-
f(&*self.active.try_read().expect(LOCK_MSG))
59+
f(&self.active.try_read().expect(LOCK_MSG))
6060
}
6161

6262
pub(crate) fn with_active_mut<T>(&self, f: impl FnOnce(&mut Vec<SpanObject>) -> T) -> T {
63-
f(&mut *self.active.try_write().expect(LOCK_MSG))
63+
f(&mut self.active.try_write().expect(LOCK_MSG))
6464
}
6565

6666
fn pop_active(&self, index: usize) -> Option<SpanObject> {
@@ -184,7 +184,7 @@ impl TracingContext {
184184
}
185185

186186
fn with_spans_mut<T>(&mut self, f: impl FnOnce(&mut Vec<SpanObject>) -> T) -> T {
187-
f(&mut *self.span_stack.finalized.try_write().expect(LOCK_MSG))
187+
f(&mut self.span_stack.finalized.try_write().expect(LOCK_MSG))
188188
}
189189

190190
pub(crate) fn with_active_span_stack<T>(&self, f: impl FnOnce(&Vec<SpanObject>) -> T) -> T {

0 commit comments

Comments
 (0)