You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2020/03/03 08:33:03 UTC
[skywalking-rust] branch context-manager updated: Support context
manager APIs.
This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch context-manager
in repository https://gitbox.apache.org/repos/asf/skywalking-rust.git
The following commit(s) were added to refs/heads/context-manager by this push:
new aa97baf Support context manager APIs.
aa97baf is described below
commit aa97bafb87c3e7cb9c34b64cc1eb9212d52802a4
Author: Wu Sheng <wu...@foxmail.com>
AuthorDate: Tue Mar 3 16:32:50 2020 +0800
Support context manager APIs.
---
README.md | 30 +++++--
core/src/skywalking/agent/context_manager.rs | 113 +++++++++++++++++++++++++--
2 files changed, 130 insertions(+), 13 deletions(-)
diff --git a/README.md b/README.md
index efef7df..f9ca49d 100644
--- a/README.md
+++ b/README.md
@@ -37,23 +37,43 @@ manipulate the RPC header/metadata to make the key/value sent to the server side
## Extractable
Extractable is used(optional) when the entry span creates. The Extractable fetches the value of the given key from the propagated
-context. Typically, Extractable implementation would read the RPC header/metadata, which sent from the client side.
+context. Typically, Extractable implementation would read the RPC header/metadata, which sent from the client side.
# APIs
-## Tracing Core APIs
+## High-Level APIs
+High level APIs are targeting convenient usages. These APIs use the ThreadLocal to propagate the context, so users could
+create span at any moment, and the context will finish automatically once the first created span of this thread stopped.
+
+```rust
+ContextManager::tracing_entry("op1", Some(&injector), |mut span| {
+ // Use span freely in this closure
+ // Span's start/end time is set automatically with this closure start/end(s).
+ span.tag(Tag::new(String::from("tag1"), String::from("value1")));
+
+ ContextManager::tracing_exit("op2", "127.0.0.1:8080", Some(&extractor), |mut span| {
+ span.set_component_id(33);
+ });
+
+ ContextManager::tracing_local("op3", |mut span| {});
+});
+```
+
+## Low-Level Core APIs
Tracing core APIs are 100% manual control tracing APIs. Users could use them to trace any process by following SkyWalking
core concepts.
+Low Level APIs request users to create and hold the context and span by the codes manually.
+
```rust
-let mut context = TracingContext::new(&reporter).unwrap();
-let span1 = context.create_entry_span("op1", None, Some(&MockerHeader {}));
+let mut context = TracingContext::new(reporter.service_instance_id()).unwrap();
+let span1 = context.create_entry_span("op1", None, Some(&dyn injector));
{
assert_eq!(span1.span_id(), 0);
let mut span2 = context.create_local_span("op2", Some(&span1));
span2.tag(Tag::new(String::from("tag1"), String::from("value1")));
{
assert_eq!(span2.span_id(), 1);
- let mut span3 = context.create_exit_span("op3", Some(&span2), "127.0.0.1:8080", Some(&HeaderCarrier {}));
+ let mut span3 = context.create_exit_span("op3", Some(&span2), "127.0.0.1:8080", Some(&dyn extractor));
assert_eq!(span3.span_id(), 2);
context.finish_span(span3);
diff --git a/core/src/skywalking/agent/context_manager.rs b/core/src/skywalking/agent/context_manager.rs
index a492e42..d361b46 100644
--- a/core/src/skywalking/agent/context_manager.rs
+++ b/core/src/skywalking/agent/context_manager.rs
@@ -18,7 +18,7 @@ use std::rc::Rc;
use lazy_static::lazy_static;
use crate::skywalking::agent::reporter::Reporter;
-use crate::skywalking::core::{Context, ContextListener, Extractable, Span, TracingContext};
+use crate::skywalking::core::{Context, ContextListener, Extractable, Injectable, Span, TracingContext};
use crate::skywalking::core::span::TracingSpan;
thread_local!( static CTX: RefCell<CurrentTracingContext> = RefCell::new(CurrentTracingContext::new()));
@@ -32,22 +32,91 @@ pub struct ContextManager {}
impl ContextManager {
pub fn tracing_entry<F>(operation_name: &str, extractor: Option<&dyn Extractable>, f: F)
- where F: FnOnce(Box<dyn Span>) -> Box<dyn Span> {
+ where F: FnOnce(&mut Box<dyn Span>) {
CTX.with(|context| {
- let span = context.borrow_mut().create_entry_span(operation_name, context.borrow().parent_span_id(), extractor);
+ let span;
+ {
+ // Borrow mut ref has to end in this specific scope, as the context is nested used in f<F>
+ let mut mut_context = context.borrow_mut();
+ let parent_span_id = mut_context.parent_span_id();
+ span = mut_context.create_entry_span(operation_name, parent_span_id, extractor);
+ }
match span {
None => {}
- Some(s) => {
- let s = f(s);
+ Some(mut s) => {
+ s.start();
+ f(s.borrow_mut());
+ s.end();
let is_first_span = s.span_id() == 0;
- context.borrow_mut().finish_span(s);
+ let mut mut_context = context.borrow_mut();
+ mut_context.finish_span(s);
if is_first_span {
- context.borrow_mut().finish();
+ mut_context.finish();
}
}
+ };
+ });
+ }
+
+ pub fn tracing_exit<F>(operation_name: &str, peer: &str, injector: Option<&dyn Injectable>, f: F)
+ where F: FnOnce(&mut Box<dyn Span>) {
+ CTX.with(|context| {
+ let span;
+ {
+ // Borrow mut ref has to end in this specific scope, as the context is nested used in f<F>
+ let mut mut_context = context.borrow_mut();
+ let parent_span_id = mut_context.parent_span_id();
+ span = mut_context.create_exit_span(operation_name, parent_span_id, peer, injector);
}
+ match span {
+ None => {}
+ Some(mut s) => {
+ s.start();
+ f(s.borrow_mut());
+ s.end();
+
+ let is_first_span = s.span_id() == 0;
+
+ let mut mut_context = context.borrow_mut();
+ mut_context.finish_span(s);
+
+ if is_first_span {
+ mut_context.finish();
+ }
+ }
+ };
+ });
+ }
+
+ pub fn tracing_local<F>(operation_name: &str, f: F)
+ where F: FnOnce(&mut Box<dyn Span>) {
+ CTX.with(|context| {
+ let span;
+ {
+ // Borrow mut ref has to end in this specific scope, as the context is nested used in f<F>
+ let mut mut_context = context.borrow_mut();
+ let parent_span_id = mut_context.parent_span_id();
+ span = mut_context.create_local(operation_name, parent_span_id);
+ }
+ match span {
+ None => {}
+ Some(mut s) => {
+ s.start();
+ f(s.borrow_mut());
+ s.end();
+
+ let is_first_span = s.span_id() == 0;
+
+ let mut mut_context = context.borrow_mut();
+ mut_context.finish_span(s);
+
+ if is_first_span {
+ mut_context.finish();
+ }
+ }
+ };
});
}
}
@@ -87,6 +156,28 @@ impl CurrentTracingContext {
}
}
+ fn create_exit_span(&mut self, operation_name: &str, parent_span_id: Option<i32>, peer: &str, injector: Option<&dyn Injectable>) -> Option<Box<dyn Span>> {
+ match self.option.borrow_mut() {
+ None => { None }
+ Some(wx) => {
+ let span = wx.context.create_exit_span(operation_name, parent_span_id, peer, injector);
+ wx.span_stack.push(span.span_id());
+ Some(span)
+ }
+ }
+ }
+
+ fn create_local(&mut self, operation_name: &str, parent_span_id: Option<i32>) -> Option<Box<dyn Span>> {
+ match self.option.borrow_mut() {
+ None => { None }
+ Some(wx) => {
+ let span = wx.context.create_local_span(operation_name, parent_span_id);
+ wx.span_stack.push(span.span_id());
+ Some(span)
+ }
+ }
+ }
+
fn finish_span(&mut self, span: Box<dyn Span>) {
match self.option.borrow_mut() {
None => {}
@@ -114,6 +205,7 @@ impl CurrentTracingContext {
None => {}
Some(wx) => {
let tracingContext = &wx.context;
+
wx.span_stack.clear();
// TODO: Transfer tracingContext to protobuf
@@ -133,7 +225,12 @@ mod context_tests {
fn test_context_manager() {
ContextManager::tracing_entry("op1", None, |mut span| {
span.tag(Tag::new(String::from("tag1"), String::from("value1")));
- span
+
+ ContextManager::tracing_exit("op2", "127.0.0.1:8080", None, |mut span| {
+ span.set_component_id(33);
+ });
+
+ ContextManager::tracing_local("op3", |mut span| {});
});
}