Skip to content

Commit

Permalink
Add Tags and Fields enums. (#8)
Browse files Browse the repository at this point in the history
This changeset adds the tags and fields enums as they are
currently represented in the java implementation.

Completes #7
  • Loading branch information
daschl authored Mar 3, 2018
1 parent d745d6a commit 87fb663
Show file tree
Hide file tree
Showing 3 changed files with 326 additions and 1 deletion.
120 changes: 120 additions & 0 deletions opentracing-api/src/field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
use std::fmt;
use std::error::Error;
use std::str::FromStr;

const FIELD_ERROR_KIND: &str = "error.kind";
const FIELD_ERROR_OBJECT: &str = "error.object";
const FIELD_EVENT: &str = "event";
const FIELD_MESSAGE: &str = "message";
const FIELD_STACK: &str = "stack";

/// The following log fields are recommended for instrumentors who are trying to capture more
/// information about a logged event. Tracers may expose additional features based on these
/// standardized data points.
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub enum Fields {
/// The type or "kind" of an error (only for event="error" logs). E.g., "Exception", "OSError".
ErrorKind,
/// The actual Throwable/Exception/Error object instance itself.
ErrorObject,
/// A stable identifier for some notable moment in the lifetime of a Span. For instance, a mutex
/// lock acquisition or release or the sorts of lifetime events in a browser page load described
/// in the Performance.timing specification. E.g., from Zipkin, "cs", "sr", "ss", or "cr". Or,
/// more generally, "initialized" or "timed out". For errors, "error".
Event,
/// A concise, human-readable, one-line message explaining the event. E.g., "Could not connect
/// to backend", "Cache invalidation succeeded".
Message,
/// A stack trace in platform-conventional format; may or may not pertain to an error.
Stack,
}

impl Fields {
/// Returns the string representation for the enum reference variant.
pub fn as_str(&self) -> &'static str {
match *self {
Fields::ErrorKind => FIELD_ERROR_KIND,
Fields::ErrorObject => FIELD_ERROR_OBJECT,
Fields::Event => FIELD_EVENT,
Fields::Message => FIELD_MESSAGE,
Fields::Stack => FIELD_STACK,
}
}
}

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

impl FromStr for Fields {
type Err = ParseFieldsError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
FIELD_ERROR_KIND => Ok(Fields::ErrorKind),
FIELD_ERROR_OBJECT => Ok(Fields::ErrorObject),
FIELD_EVENT => Ok(Fields::Event),
FIELD_MESSAGE => Ok(Fields::Message),
FIELD_STACK => Ok(Fields::Stack),
_ => Err(ParseFieldsError::UnknownField),
}
}
}

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

impl Error for ParseFieldsError {
fn description(&self) -> &str {
match *self {
ParseFieldsError::UnknownField => "Unknown Field",
}
}

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

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

#[cfg(test)]
mod tests {

use super::*;

#[test]
fn test_field_as_str() {
assert_eq!("error.kind", Fields::ErrorKind.as_str());
assert_eq!("error.object", Fields::ErrorObject.as_str());
assert_eq!("event", Fields::Event.as_str());
assert_eq!("message", Fields::Message.as_str());
assert_eq!("stack", Fields::Stack.as_str());
}

#[test]
fn test_field_as_string() {
assert_eq!(String::from("error.kind"), Fields::ErrorKind.to_string());
}

#[test]
fn test_field_from_string() {
assert_eq!(Ok(Fields::Event), Fields::from_str("event"));
assert_eq!(Ok(Fields::Message), "message".parse());
assert_eq!(
Err(ParseFieldsError::UnknownField),
Fields::from_str("some_other_field")
);
}

}
8 changes: 7 additions & 1 deletion opentracing-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
#![doc(html_root_url = "https://docs.rs/opentracing-api/0.1.0")]
#![doc(html_root_url = "https://docs.rs/opentracing-api/0.1.0")]

mod tag;
mod field;

pub use tag::{Tags, ParseTagsError};
pub use field::{Fields, ParseFieldsError};
199 changes: 199 additions & 0 deletions opentracing-api/src/tag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
use std::fmt;
use std::error::Error;
use std::str::FromStr;

const TAG_SPAN_KIND_CLIENT: &str = "client";
const TAG_SPAN_KIND_SERVER: &str = "server";
const TAG_SPAN_KIND_PRODUCER: &str = "producer";
const TAG_SPAN_KIND_CONSUMER: &str = "consumer";
const TAG_HTTP_URL: &str = "http.url";
const TAG_HTTP_STATUS_CODE: &str = "http.status_code";
const TAG_HTTP_METHOD: &str = "http.method";
const TAG_PEER_IPV4: &str = "peer.ipv4";
const TAG_PEER_IPV6: &str = "peer.ipv6";
const TAG_PEER_SERVICE: &str = "peer.service";
const TAG_PEER_HOSTNAME: &str = "peer.hostname";
const TAG_PEER_PORT: &str = "peer.port";
const TAG_SAMPLING_PRIORITY: &str = "sampling.priority";
const TAG_SPAN_KIND: &str = "span.kind";
const TAG_COMPONENT: &str = "component";
const TAG_ERROR: &str = "error";
const TAG_DB_TYPE: &str = "db.type";
const TAG_DB_INSTANCE: &str = "db.instance";
const TAG_DB_USER: &str = "db.user";
const TAG_DB_STATEMENT: &str = "db.statement";
const TAG_MSGBUS_DEST: &str = "message_bus.destination";

/// The following span tags are recommended for instrumentors who are trying to capture more
/// semantic information about the spans. Tracers may expose additional features based on these
/// standardized data points. Tag names follow a general structure of namespacing.
///
/// See also [Semantic Conventions](https://github.com/opentracing/specification/blob/master/semantic_conventions.md)
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub enum Tags {
/// A constant for setting the span kind to indicate that it represents a client span.
SpanKindClient,
/// A constant for setting the span kind to indicate that it represents a server span.
SpanKindServer,
/// A constant for setting the span kind to indicate that it represents a producer span,
/// in a messaging scenario.
SpanKindProducer,
/// A constant for setting the span kind to indicate that it represents a consumer span,
/// in a messaging scenario.
SpanKindConsumer,
/// HTTP_URL records the url of the incoming request.
HttpUrl,
/// HTTP_STATUS records the http status code of the response.
HttpStatus,
/// HTTP_METHOD records the http method. Case-insensitive.
HttpMethod,
/// PEER_HOST_IPV4 records IPv4 host address of the peer.
PeerHostIpv4,
/// PEER_HOST_IPV6 records the IPv6 host address of the peer.
PeerHostIpv6,
/// PEER_SERVICE records the service name of the peer.
PeerService,
/// PEER_HOSTNAME records the host name of the peer.
PeerHostname,
/// PEER_PORT records the port number of the peer.
PeerPort,
/// SAMPLING_PRIORITY determines the priority of sampling this Span.
SamplingPriority,
/// SPAN_KIND hints at the relationship between spans, e.g. client/server.
SpanKind,
/// COMPONENT is a low-cardinality identifier of the module, library, or
/// package that is instrumented.
Component,
/// ERROR indicates whether a Span ended in an error state.
Error,
/// DB_TYPE indicates the type of Database.
DbType,
/// DB_INSTANCE indicates the instance name of Database.
DbInstance,
/// DB_USER indicates the user name of Database, e.g. "readonly_user" or
/// "reporting_user"
DbUser,
/// DB_STATEMENT records a database statement for the given database type.
DbStatement,
/// MESSAGE_BUS_DESTINATION records an address at which messages can be
/// exchanged.
MessageBusDestination,
}

impl Tags {
/// Returns the string representation for the enum reference variant.
pub fn as_str(&self) -> &'static str {
match *self {
Tags::SpanKindClient => TAG_SPAN_KIND_CLIENT,
Tags::SpanKindServer => TAG_SPAN_KIND_SERVER,
Tags::SpanKindProducer => TAG_SPAN_KIND_PRODUCER,
Tags::SpanKindConsumer => TAG_SPAN_KIND_CONSUMER,
Tags::HttpUrl => TAG_HTTP_URL,
Tags::HttpStatus => TAG_HTTP_STATUS_CODE,
Tags::HttpMethod => TAG_HTTP_METHOD,
Tags::PeerHostIpv4 => TAG_PEER_IPV4,
Tags::PeerHostIpv6 => TAG_PEER_IPV6,
Tags::PeerService => TAG_PEER_SERVICE,
Tags::PeerHostname => TAG_PEER_HOSTNAME,
Tags::PeerPort => TAG_PEER_PORT,
Tags::SamplingPriority => TAG_SAMPLING_PRIORITY,
Tags::SpanKind => TAG_SPAN_KIND,
Tags::Component => TAG_COMPONENT,
Tags::Error => TAG_ERROR,
Tags::DbType => TAG_DB_TYPE,
Tags::DbInstance => TAG_DB_INSTANCE,
Tags::DbUser => TAG_DB_USER,
Tags::DbStatement => TAG_DB_STATEMENT,
Tags::MessageBusDestination => TAG_MSGBUS_DEST,
}
}
}

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

impl FromStr for Tags {
type Err = ParseTagsError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
TAG_SPAN_KIND_CLIENT => Ok(Tags::SpanKindClient),
TAG_SPAN_KIND_SERVER => Ok(Tags::SpanKindServer),
TAG_SPAN_KIND_PRODUCER => Ok(Tags::SpanKindProducer),
TAG_SPAN_KIND_CONSUMER => Ok(Tags::SpanKindConsumer),
TAG_HTTP_URL => Ok(Tags::HttpUrl),
TAG_HTTP_STATUS_CODE => Ok(Tags::HttpStatus),
TAG_HTTP_METHOD => Ok(Tags::HttpMethod),
TAG_PEER_IPV4 => Ok(Tags::PeerHostIpv4),
TAG_PEER_IPV6 => Ok(Tags::PeerHostIpv6),
TAG_PEER_SERVICE => Ok(Tags::PeerService),
TAG_PEER_HOSTNAME => Ok(Tags::PeerHostname),
TAG_PEER_PORT => Ok(Tags::PeerPort),
TAG_SAMPLING_PRIORITY => Ok(Tags::SamplingPriority),
TAG_SPAN_KIND => Ok(Tags::SpanKind),
TAG_COMPONENT => Ok(Tags::Component),
TAG_ERROR => Ok(Tags::Error),
TAG_DB_TYPE => Ok(Tags::DbType),
TAG_DB_INSTANCE => Ok(Tags::DbInstance),
TAG_DB_USER => Ok(Tags::DbUser),
TAG_DB_STATEMENT => Ok(Tags::DbStatement),
TAG_MSGBUS_DEST => Ok(Tags::MessageBusDestination),
_ => Err(ParseTagsError::UnknownTag),
}
}
}

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

impl Error for ParseTagsError {
fn description(&self) -> &str {
match *self {
ParseTagsError::UnknownTag => "Unknown Tag",
}
}

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

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

#[cfg(test)]
mod tests {

use super::*;

#[test]
fn test_tag_as_str() {
assert_eq!("client", Tags::SpanKindClient.as_str());
}

#[test]
fn test_tag_as_string() {
assert_eq!(String::from("client"), Tags::SpanKindClient.to_string());
}

#[test]
fn test_tag_from_string() {
assert_eq!(Ok(Tags::Error), Tags::from_str("error"));
assert_eq!(Ok(Tags::PeerHostIpv4), "peer.ipv4".parse());
assert_eq!(
Err(ParseTagsError::UnknownTag),
Tags::from_str("some_other_field")
);
}

}

0 comments on commit 87fb663

Please sign in to comment.