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| {});
         });
     }