Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Span #12

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions opentracing-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#![doc(html_root_url = "https://docs.rs/opentracing-api/0.1.0")]

mod context;
mod tag;
mod field;
mod reference;
mod span;
mod tag;

pub use context::SpanContext;
pub use tag::{ParseTagsError, Tags};
pub use field::{Fields, ParseFieldsError};
pub use reference::{ParseReferencesError, References};
pub use span::{FinishedSpan, Span};
pub use tag::{ParseTagsError, TagValue, Tags};
102 changes: 102 additions & 0 deletions opentracing-api/src/reference.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use std::fmt;
use std::error::Error;
use std::str::FromStr;

const REF_CHILD_OF: &str = "child_of";
const REF_FOLLOWS_FROM: &str = "follows_from";

/// References provide a namespace for official OpenTracing reference types.
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub enum References {
/// See http://opentracing.io/spec/#causal-span-references for
/// more information about ChildOf references.
ChildOf,
/// See http://opentracing.io/spec/#causal-span-references for
/// more information about FollowsFrom references.
FollowsFrom,
}

impl References {
/// Returns the string representation for the enum reference variant.
pub fn as_str(&self) -> &'static str {
match *self {
References::ChildOf => REF_CHILD_OF,
References::FollowsFrom => REF_FOLLOWS_FROM,
}
}
}

impl fmt::Display for References {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}

impl FromStr for References {
type Err = ParseReferencesError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
REF_CHILD_OF => Ok(References::ChildOf),
REF_FOLLOWS_FROM => Ok(References::FollowsFrom),
_ => Err(ParseReferencesError::UnknownReference),
}
}
}

/// Describes errors which can happen while parsing into the `References` enum.
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub enum ParseReferencesError {
/// The provided reference is not known.
UnknownReference,
}

impl Error for ParseReferencesError {
fn description(&self) -> &str {
match *self {
ParseReferencesError::UnknownReference => "Unknown Reference",
}
}

fn cause(&self) -> Option<&Error> {
None
}
}

impl fmt::Display for ParseReferencesError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.description())
}
}

#[cfg(test)]
mod tests {

use super::*;

#[test]
fn test_reference_as_str() {
assert_eq!("child_of", References::ChildOf.as_str());
assert_eq!("follows_from", References::FollowsFrom.as_str());
}

#[test]
fn test_reference_as_string() {
assert_eq!(String::from("child_of"), References::ChildOf.to_string());
assert_eq!(
String::from("follows_from"),
References::FollowsFrom.to_string()
);
}

#[test]
fn test_reference_from_string() {
assert_eq!(Ok(References::ChildOf), References::from_str("child_of"));
assert_eq!(Ok(References::FollowsFrom), "follows_from".parse());
assert_eq!(
Err(ParseReferencesError::UnknownReference),
References::from_str("some_other_field")
);
}

}
83 changes: 83 additions & 0 deletions opentracing-api/src/span.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use SpanContext;
use TagValue;

/// The `Span` represents the OpenTracing specification's Span contract.
pub trait Span<'a> {
/// The associated `SpanContext`.
type Context: SpanContext<'a>;

/// Retrieve the associated `SpanContext`.
///
/// This may be called any time, including after `finish`.
fn context(&self) -> &Self::Context;

/// Sets a key:value tag on the `Span`.
fn set_tag<S>(&mut self, key: S, value: TagValue)
where
S: Into<String>;

/// Allows to unset a tag based on the given key. Noop if
/// it doesn't exist.
fn unset_tag<S>(&mut self, key: S)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not technically part of the spec and I did not see it in the Java interface.
Should this be provided by implementations rather then the interface?

where
S: Into<String>;

/// Returns a tag value if set, none otherwise
fn tag<S>(&self, key: S) -> Option<&TagValue>
where
S: Into<String>;

/// Record an event at the current walltime timestamp.
fn log(&mut self, event: String);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With regards to the event type: what if it was any serde::Serialize type?

fn log<E>(&mut self, event: E)
where
    E: serde::Serialize;

Alternatively we can do what slog does and define an Event trait with an interface tailored to use by tracers.
Common types in the standard library would get an implementation of Event and users can implement it for any other type then need to log.


/// Record an event at the given walltime timestamp.
fn log_at(&mut self, timestamp: u64, event: String);

/// Sets a baggage item in the Span (and its SpanContext) as a key/value pair.
fn set_baggage_item<S>(&mut self, key: S, value: String)
where
S: Into<String>;

/// Allows to unset a baggage item based on the given key. Noop if
/// it doesn't exist.
fn unset_baggage_item<S>(&mut self, key: S)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.
I'm not sure we should add non-standard features to the core interface.

where
S: Into<String>;

/// the value of the baggage item identified by the given key, or None if no such item
/// could be found.
fn baggage_item<S>(&self, key: S) -> Option<&String>
where
S: Into<String>;

/// Sets the string name for the logical operation this span represents.
fn set_operation_name<S>(&mut self, name: S)
where
S: Into<String>;

/// Returns the operation name if set, None otherwise.
fn operation_name(&self) -> &String;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be Option<&String>?


/// Sets the end timestamp to now and finishes (records) the span.
fn finish(self) -> FinishedSpan<Self::Context>;

/// Sets an explicit end timestamp and finishes (records) the span.
fn finish_at(self, timestamp: u64) -> FinishedSpan<Self::Context>;
}

pub struct FinishedSpan<C> {
context: C,
}

impl<'a, C> FinishedSpan<C>
where
C: SpanContext<'a>,
{
pub fn new(context: C) -> Self {
FinishedSpan { context }
}

pub fn context(&self) -> &C {
&self.context
}
}
20 changes: 20 additions & 0 deletions opentracing-api/src/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,26 @@ impl fmt::Display for ParseTagsError {
}
}

/// Tags Values per spec can be Strings, Booleans or Numerics.
///
/// Note that isize and usize are not included here since they
/// are only meant to be used as pointers-sized types only.
#[derive(Clone, PartialEq, PartialOrd, Debug)]
pub enum TagValue {
String(String),
Boolean(bool),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
F32(f32),
F64(f64),
}

#[cfg(test)]
mod tests {

Expand Down
Loading