Add more comments, and span.log to the core API.
diff --git a/tracing-core/src/context.rs b/tracing-core/src/context.rs
index e9f1de5..0a03203 100644
--- a/tracing-core/src/context.rs
+++ b/tracing-core/src/context.rs
@@ -1,14 +1,18 @@
-use std::rc::Rc;
-
-use crate::{ID, Reporter, Span, TracingSpan};
+use crate::{ContextListener, ID, Span};
use crate::id::IDGenerator;
+use crate::span::TracingSpan;
/// Context represents the context of a tracing process.
/// All new span belonging to this tracing context should be created through this context.
pub trait Context {
+ /// Create an entry span belonging this context
fn create_entry_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span>;
+ /// Create an exit span belonging this context
fn create_exit_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span>;
+ /// Create an local span belonging this context
fn create_local_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span>;
+ /// Finish the given span. The span is only being accept if it belongs to this context.
+ /// Return err if the span was created by another context.
fn finish_span(&mut self, span: Box<dyn Span>);
}
@@ -23,7 +27,7 @@
impl TracingContext {
/// Create a new instance
- pub fn new(reporter: &dyn Reporter) -> Option<TracingContext> {
+ pub fn new(reporter: &dyn ContextListener) -> Option<TracingContext> {
let instance_id = reporter.service_instance_id();
match instance_id {
None => { None }
@@ -79,11 +83,10 @@
#[cfg(test)]
mod context_tests {
- use std::rc::Rc;
use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender};
- use crate::{Context, Reporter, TracingContext};
+ use crate::{Context, ContextListener, Tag, TracingContext};
#[test]
fn test_context_stack() {
@@ -92,7 +95,8 @@
let span1 = context.create_entry_span(String::from("op1"), None);
{
assert_eq!(span1.span_id(), 0);
- let span2 = context.create_entry_span(String::from("op2"), Some(&span1));
+ let mut span2 = context.create_entry_span(String::from("op2"), Some(&span1));
+ span2.tag(Tag::new(String::from("tag1"), String::from("value1")));
{
assert_eq!(span2.span_id(), 1);
let mut span3 = context.create_entry_span(String::from("op3"), Some(&span2));
@@ -132,7 +136,7 @@
}
}
- impl Reporter for MockReporter {
+ impl ContextListener for MockReporter {
fn service_instance_id(&self) -> Option<i32> {
Some(1)
}
@@ -144,7 +148,7 @@
struct MockRegisterPending {}
- impl Reporter for MockRegisterPending {
+ impl ContextListener for MockRegisterPending {
fn service_instance_id(&self) -> Option<i32> {
None
}
diff --git a/tracing-core/src/report_bridge.rs b/tracing-core/src/context_listener.rs
similarity index 95%
rename from tracing-core/src/report_bridge.rs
rename to tracing-core/src/context_listener.rs
index d07e9bc..73cfbad 100644
--- a/tracing-core/src/report_bridge.rs
+++ b/tracing-core/src/context_listener.rs
@@ -4,7 +4,7 @@
/// Register implementation communicate with the SkyWalking OAP backend.
/// It does metadata register, traces report, and runtime status report or interaction.
-pub trait Reporter {
+pub trait ContextListener {
/// Return the registered service id
/// If haven't registered successfully, return None.
fn service_instance_id(&self) -> Option<i32>;
diff --git a/tracing-core/src/lib.rs b/tracing-core/src/lib.rs
index 46fecbd..789c12a 100644
--- a/tracing-core/src/lib.rs
+++ b/tracing-core/src/lib.rs
@@ -1,14 +1,14 @@
pub use context::Context;
pub use context::TracingContext;
+pub use context_listener::ContextListener;
pub use id::ID;
-pub use report_bridge::Reporter;
pub use span::Span;
-pub use span::TracingSpan;
pub use tag::Tag;
pub mod span;
pub mod context;
pub mod tag;
pub mod id;
-pub mod report_bridge;
+pub mod context_listener;
+pub mod log;
diff --git a/tracing-core/src/log.rs b/tracing-core/src/log.rs
new file mode 100644
index 0000000..aa14245
--- /dev/null
+++ b/tracing-core/src/log.rs
@@ -0,0 +1,50 @@
+/// Log represents an event happened during the span duration.
+/// It is much heavier than tag. Usually this is only used in the error case to log the detailed error message.
+/// Log Entity is a creation once object. Can't be change once it is created.
+pub struct LogEvent {
+ timestamp: i64,
+ /// Any extra fields to describe the event.
+ fields: Box<[EventField]>,
+}
+
+pub struct EventField {
+ name: String,
+ value: String,
+}
+
+impl LogEvent {
+ pub fn new(timestamp: i64, fields: Box<[EventField]>) -> Self {
+ LogEvent {
+ timestamp,
+ fields,
+ }
+ }
+}
+
+impl EventField {
+ pub fn new(name: String, value: String) -> Self {
+ EventField {
+ name,
+ value,
+ }
+ }
+}
+
+#[cfg(test)]
+mod log_tests {
+ use crate::log::{EventField, LogEvent};
+
+ #[test]
+ fn test_log_new() {
+ let fields = [
+ { EventField::new(String::from("event1"), String::from("event description")) },
+ { EventField::new(String::from("event2"), String::from("event description")) },
+ ];
+ let event = LogEvent::new(123, Box::new(fields));
+ assert_eq!(event.timestamp, 123);
+ assert_eq!(event.fields.len(), 2);
+ assert_eq!(event.fields[0].name, "event1");
+ assert_eq!(event.fields[1].value, "event description");
+ }
+}
+
diff --git a/tracing-core/src/span.rs b/tracing-core/src/span.rs
index b42f3ad..47f1bae 100644
--- a/tracing-core/src/span.rs
+++ b/tracing-core/src/span.rs
@@ -1,21 +1,42 @@
use std::time::SystemTime;
+use crate::log::LogEvent;
use crate::Tag;
/// Span is one of the tracing concept, representing a time duration.
-/// Typically, it represent a method invocation or a RPC.
+/// Span typically used in the certain scope, Typically, it represent a method invocation or a RPC.
pub trait Span {
+ /// Start the span with the current system time
fn start(&mut self);
+ /// Start the span by using given time point.
fn start_with_timestamp(&mut self, timestamp: SystemTime);
- fn is_entry(&self) -> bool;
- fn is_exit(&self) -> bool;
- fn span_id(&self) -> i32;
+ /// Add a new tag to the span
fn tag(&mut self, tag: Tag);
- /// End means sealing the end time.
- /// Still need to call Context::archive
+ /// Add a log event to the span
+ fn log(&mut self, log: LogEvent);
+ /// Indicate error occurred during the span execution.
+ fn error_occurred(&mut self);
+ /// Set the component id represented by this span.
+ /// Component id is pre-definition in the SkyWalking OAP backend component-libraries.yml file.
+ /// Read [Component library settings](https://github.com/apache/skywalking/blob/master/docs/en/guides/Component-library-settings.md) documentation for more details
+ fn set_component_id(&mut self, component_id: i32);
+ /// End the span with the current system time.
+ /// End just means sealing the end time, still need to call Context::finish_span to officially finish span and archive it for further reporting.
fn end(&mut self);
+ /// End the span by using given time point.
+ /// End just means sealing the end time, still need to call Context::finish_span to officially finish span and archive it for further reporting.
fn end_with_timestamp(&mut self, timestamp: SystemTime);
- fn is_ended(&mut self) -> bool;
+
+ /// All following are status reading methods.
+
+ /// Return true if the span has been set end time
+ fn is_ended(&self) -> bool;
+ /// Return true if the span is an entry span
+ fn is_entry(&self) -> bool;
+ /// Return true if the span is an exit span
+ fn is_exit(&self) -> bool;
+ /// Return span id.
+ fn span_id(&self) -> i32;
/// Return the replicated existing tags.
fn tags(&self) -> Vec<Tag>;
}
@@ -41,8 +62,10 @@
/// Component id is defined in the main repo to represent the library kind.
component_id: Option<i32>,
tags: Vec<Tag>,
+ logs: Vec<LogEvent>,
}
+/// Tracing Span is only created inside TracingContext.
impl TracingSpan {
/// Create a new entry span
pub fn new_entry_span(operation_name: String, span_id: i32, parent_span_id: i32) -> Box<dyn Span> {
@@ -78,6 +101,7 @@
error_occurred: false,
component_id: None,
tags: Vec::new(),
+ logs: Vec::new(),
}
}
}
@@ -97,22 +121,22 @@
} as u64;
}
- fn is_entry(&self) -> bool {
- self.is_entry
- }
-
- fn is_exit(&self) -> bool {
- self.is_exit
- }
-
- fn span_id(&self) -> i32 {
- self.span_id
- }
-
fn tag(&mut self, tag: Tag) {
self.tags.push(tag);
}
+ fn log(&mut self, log: LogEvent) {
+ self.logs.push(log);
+ }
+
+ fn error_occurred(&mut self) {
+ self.error_occurred = true;
+ }
+
+ fn set_component_id(&mut self, component_id: i32) {
+ self.component_id = Some(component_id);
+ }
+
fn end(&mut self) {
self.end_time = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
Ok(n) => { n.as_millis() }
@@ -127,10 +151,22 @@
} as u64;
}
- fn is_ended(&mut self) -> bool {
+ fn is_ended(&self) -> bool {
self.end_time != 0
}
+ fn is_entry(&self) -> bool {
+ self.is_entry
+ }
+
+ fn is_exit(&self) -> bool {
+ self.is_exit
+ }
+
+ fn span_id(&self) -> i32 {
+ self.span_id
+ }
+
fn tags(&self) -> Vec<Tag> {
let mut tags = Vec::new();
for t in &self.tags {
@@ -142,15 +178,14 @@
#[cfg(test)]
mod span_tests {
- use std::rc::Rc;
use std::time::SystemTime;
- use crate::{Context, Reporter, Tag, TracingContext};
+ use crate::log::{EventField, LogEvent};
use crate::span::*;
+ use crate::Tag;
#[test]
fn test_span_new() {
- let mut context = TracingContext::new(&MockRegister {}).unwrap();
let mut span = TracingSpan::_new(String::from("op1"), 0, -1);
assert_eq!(span.parent_span_id, -1);
assert_eq!(span.span_id, 0);
@@ -168,14 +203,12 @@
#[test]
fn test_new_entry_span() {
- let context = TracingContext::new(&MockRegister {}).unwrap();
let span = TracingSpan::new_entry_span(String::from("op1"), 0, 1);
assert_eq!(span.is_entry(), true)
}
#[test]
fn test_span_with_tags() {
- let context = TracingContext::new(&MockRegister {}).unwrap();
let mut span = TracingSpan::new_entry_span(String::from("op1"), 0, 1);
span.tag(Tag::new(String::from("tag1"), String::from("value1")));
span.tag(Tag::new(String::from("tag2"), String::from("value2")));
@@ -185,16 +218,16 @@
assert_eq!(tags.get(0).unwrap().key(), "tag1")
}
- struct MockRegister {}
+ #[test]
+ fn test_span_with_logs() {
+ let mut span = TracingSpan::_new(String::from("op1"), 0, -1);
- impl Reporter for MockRegister {
- fn service_instance_id(&self) -> Option<i32> {
- Some(1)
- }
+ span.log(LogEvent::new(123, Box::new([
+ { EventField::new(String::from("event1"), String::from("event description")) },
+ { EventField::new(String::from("event2"), String::from("event description")) },
+ ])));
- fn report_trace(&self, finished_context: TracingContext) {
- unimplemented!()
- }
+ assert_eq!(span.logs.len(), 1);
}
}
diff --git a/tracing-core/src/tag.rs b/tracing-core/src/tag.rs
index 112aebb..45f668c 100644
--- a/tracing-core/src/tag.rs
+++ b/tracing-core/src/tag.rs
@@ -1,3 +1,6 @@
+/// Tag is a key value pair to represent an supplementary instruction for the span.
+/// Common and most widely used tags could be found here,
+/// https://github.com/apache/skywalking/blob/master/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java.
#[derive(Clone, Hash)]
pub struct Tag {
key: String,