Skip to content

Commit

Permalink
add some API documentation, span description
Browse files Browse the repository at this point in the history
  • Loading branch information
Swatinem committed Jan 3, 2022
1 parent 7ae46b6 commit 3ef3dcd
Showing 1 changed file with 72 additions and 5 deletions.
77 changes: 72 additions & 5 deletions sentry-core/src/performance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ const MAX_SPANS: usize = 1_000;

// global API:

/// Start a new Performance Monitoring Transaction.
///
/// The transaction needs to be explicitly finished via [`Transaction::finish`],
/// otherwise it will be discarded.
/// The transaction itself also represents the root span in the span hierarchy.
/// Child spans can be started with the [`Transaction::start_child`] method.
pub fn start_transaction(ctx: TransactionContext) -> Transaction {
let client = Hub::with_active(|hub| hub.client());
Transaction::new(client, ctx)
Expand All @@ -16,13 +22,20 @@ pub fn start_transaction(ctx: TransactionContext) -> Transaction {
// Hub API:

impl Hub {
/// Start a new Performance Monitoring Transaction.
///
/// See the global [`start_transaction`] for more documentation.
pub fn start_transaction(&self, ctx: TransactionContext) -> Transaction {
Transaction::new(self.client(), ctx)
}
}

// "Context" Types:

/// The Transaction Context used to start a new Performance Monitoring Transaction.
///
/// The Transaction Context defines the metadata for a Performance Monitoring
/// Transaction, and also the connection point for distributed tracing.
#[derive(Debug)]
pub struct TransactionContext {
name: String,
Expand All @@ -32,11 +45,24 @@ pub struct TransactionContext {
}

impl TransactionContext {
/// Creates a new Transaction Context with the given `name` and `op`.
///
/// See <https://docs.sentry.io/platforms/native/enriching-events/transaction-name/>
/// for an explanation of a Transaction's `name`, and
/// <https://develop.sentry.dev/sdk/performance/span-operations/> for conventions
/// around an `operation`'s value.
///
/// See also the [`TransactionContext::continue_from_headers`] function that
/// can be used for distributed tracing.
#[must_use = "this must be used with `start_transaction`"]
pub fn new(name: &str, op: &str) -> Self {
Self::continue_from_headers(name, op, [])
}

/// Creates a new Transaction Context based on the distributed tracing `headers`.
///
/// The `headers` in particular need to include the `sentry-trace` header,
/// which is used to associate the transaction with a distributed trace.
#[must_use = "this must be used with `start_transaction`"]
pub fn continue_from_headers<'a, I: IntoIterator<Item = (&'a str, &'a str)>>(
name: &str,
Expand All @@ -62,13 +88,18 @@ impl TransactionContext {
parent_span_id,
}
}

// TODO: `sampled` flag
}

// global API types:

/// A wrapper that groups a [`Transaction`] and a [`Span`] together.
#[derive(Clone, Debug)]
pub enum TransactionOrSpan {
/// A [`Transaction`].
Transaction(Transaction),
/// A [`Span`].
Span(Span),
}

Expand All @@ -85,18 +116,23 @@ impl From<Span> for TransactionOrSpan {
}

impl TransactionOrSpan {
/// Returns the headers needed for distributed tracing.
pub fn iter_headers(&self) -> TraceHeadersIter {
match self {
TransactionOrSpan::Transaction(transaction) => transaction.iter_headers(),
TransactionOrSpan::Span(span) => span.iter_headers(),
}
}

/// Starts a new child Span with the given `op` and `description`.
///
/// The span must be explicitly finished via [`Span::finish`], as it will
/// otherwise not be sent to Sentry.
#[must_use = "a span must be explicitly closed via `finish()`"]
pub fn start_child(&self, op: &str) -> Span {
pub fn start_child(&self, op: &str, description: &str) -> Span {
match self {
TransactionOrSpan::Transaction(transaction) => transaction.start_child(op),
TransactionOrSpan::Span(span) => span.start_child(op),
TransactionOrSpan::Transaction(transaction) => transaction.start_child(op, description),
TransactionOrSpan::Span(span) => span.start_child(op, description),
}
}

Expand Down Expand Up @@ -128,6 +164,11 @@ struct TransactionInner {

type TransactionArc = Arc<Mutex<TransactionInner>>;

/// A running Performance Monitoring Transaction.
///
/// The transaction needs to be explicitly finished via [`Transaction::finish`],
/// otherwise neither the transaction nor any of its child spans will be sent
/// to Sentry.
#[derive(Clone, Debug)]
pub struct Transaction {
inner: TransactionArc,
Expand Down Expand Up @@ -160,6 +201,7 @@ impl Transaction {
}
}

/// Returns the headers needed for distributed tracing.
pub fn iter_headers(&self) -> TraceHeadersIter {
let inner = self.inner.lock().unwrap();
let trace = SentryTrace(inner.context.trace_id, inner.context.span_id, None);
Expand All @@ -168,6 +210,10 @@ impl Transaction {
}
}

/// Finishes the Transaction.
///
/// This records the end timestamp and sends the transaction together with
/// all finished child spans to Sentry.
pub fn finish(self) {
let mut inner = self.inner.lock().unwrap();
if let Some(mut transaction) = inner.transaction.take() {
Expand All @@ -185,13 +231,17 @@ impl Transaction {
}
}

/// Starts a new child Span with the given `op` and `description`.
///
/// The span must be explicitly finished via [`Span::finish`].
#[must_use = "a span must be explicitly closed via `finish()`"]
pub fn start_child(&self, op: &str) -> Span {
pub fn start_child(&self, op: &str, description: &str) -> Span {
let inner = self.inner.lock().unwrap();
let span = protocol::Span {
trace_id: inner.context.trace_id,
parent_span_id: Some(inner.context.span_id),
op: Some(op.into()),
description: Some(description.into()),
..Default::default()
};
Span {
Expand All @@ -201,20 +251,29 @@ impl Transaction {
}
}

/// A running Performance Monitoring Span.
///
/// The span needs to be explicitly finished via [`Span::finish`], otherwise it
/// will not be sent to Sentry.
#[derive(Clone, Debug)]
pub struct Span {
transaction: TransactionArc,
span: protocol::Span,
}

impl Span {
/// Returns the headers needed for distributed tracing.
pub fn iter_headers(&self) -> TraceHeadersIter {
let trace = SentryTrace(self.span.trace_id, self.span.span_id, None);
TraceHeadersIter {
sentry_trace: Some(trace.to_string()),
}
}

/// Finishes the Span.
///
/// This will record the end timestamp and add the span to the transaction
/// in which it was started.
pub fn finish(mut self) {
self.span.finish();
let mut inner = self.transaction.lock().unwrap();
Expand All @@ -225,12 +284,16 @@ impl Span {
}
}

/// Starts a new child Span with the given `op` and `description`.
///
/// The span must be explicitly finished via [`Span::finish`].
#[must_use = "a span must be explicitly closed via `finish()`"]
pub fn start_child(&self, op: &str) -> Span {
pub fn start_child(&self, op: &str, description: &str) -> Span {
let span = protocol::Span {
trace_id: self.span.trace_id,
parent_span_id: Some(self.span.span_id),
op: Some(op.into()),
description: Some(description.into()),
..Default::default()
};
Span {
Expand All @@ -240,6 +303,10 @@ impl Span {
}
}

/// An Iterator over HTTP header names and values needed for distributed tracing.
///
/// This currently only yields the `sentry-trace` header, but other headers
/// may be added in the future.
pub struct TraceHeadersIter {
sentry_trace: Option<String>,
}
Expand Down

0 comments on commit 3ef3dcd

Please sign in to comment.