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

add request to transaction #439

Merged
merged 6 commits into from Mar 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,17 @@
# Changelog

## Unreleased

**Features**:

- Request data can now be attached to Transactions and Spans via `set_transaction`. ([#439](https://github.com/getsentry/sentry-rust/pull/439))
Copy link
Member

Choose a reason for hiding this comment

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

Looks like a typo, that should be set_request ;-)


**Thank you**:

Features, fixes and improvements in this release have been contributed by:

- [@jessfraz](https://github.com/jessfraz)

## 0.25.0

**Breaking Changes**:
Expand Down
51 changes: 51 additions & 0 deletions sentry-core/src/performance.rs
Expand Up @@ -202,6 +202,14 @@ impl TransactionOrSpan {
}
}

/// Set the HTTP request information for this Transaction/Span.
pub fn set_request(&self, request: protocol::Request) {
match self {
TransactionOrSpan::Transaction(transaction) => transaction.set_request(request),
TransactionOrSpan::Span(span) => span.set_request(request),
}
}

/// Returns the headers needed for distributed tracing.
pub fn iter_headers(&self) -> TraceHeadersIter {
match self {
Expand Down Expand Up @@ -355,6 +363,14 @@ impl Transaction {
inner.context.status = Some(status);
}

/// Set the HTTP request information for this Transaction.
pub fn set_request(&self, request: protocol::Request) {
let mut inner = self.inner.lock().unwrap();
if let Some(transaction) = inner.transaction.as_mut() {
transaction.request = Some(request);
}
}

/// Returns the headers needed for distributed tracing.
pub fn iter_headers(&self) -> TraceHeadersIter {
let inner = self.inner.lock().unwrap();
Expand Down Expand Up @@ -454,6 +470,41 @@ impl Span {
span.status = Some(status);
}

/// Set the HTTP request information for this Span.
pub fn set_request(&self, request: protocol::Request) {
let mut span = self.span.lock().unwrap();
// Extract values from the request to be used as data in the span.
if let Some(method) = request.method {
span.data.insert("method".into(), method.into());
}
if let Some(url) = request.url {
span.data.insert("url".into(), url.to_string().into());
}
if let Some(data) = request.data {
if let Ok(data) = serde_json::from_str::<serde_json::Value>(&data) {
span.data.insert("data".into(), data);
} else {
span.data.insert("data".into(), data.into());
}
}
if let Some(query_string) = request.query_string {
span.data.insert("query_string".into(), query_string.into());
}
if let Some(cookies) = request.cookies {
span.data.insert("cookies".into(), cookies.into());
}
if !request.headers.is_empty() {
if let Ok(headers) = serde_json::to_value(request.headers) {
span.data.insert("headers".into(), headers);
}
}
if !request.env.is_empty() {
if let Ok(env) = serde_json::to_value(request.env) {
span.data.insert("env".into(), env);
}
}
}

/// Returns the headers needed for distributed tracing.
pub fn iter_headers(&self) -> TraceHeadersIter {
let span = self.span.lock().unwrap();
Expand Down
7 changes: 6 additions & 1 deletion sentry-types/src/protocol/v7.rs
Expand Up @@ -15,7 +15,7 @@ use std::ops;
use std::str;
use std::time::SystemTime;

use ::debugid::{CodeId, DebugId};
use self::debugid::{CodeId, DebugId};
use serde::Serializer;
use serde::{Deserialize, Serialize};
use thiserror::Error;
Expand Down Expand Up @@ -1942,6 +1942,9 @@ pub struct Transaction<'a> {
/// Optional contexts.
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub contexts: Map<String, Context>,
/// Optionally HTTP request data to be sent along.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub request: Option<Request>,
}

impl<'a> Default for Transaction<'a> {
Expand All @@ -1959,6 +1962,7 @@ impl<'a> Default for Transaction<'a> {
start_timestamp: SystemTime::now(),
spans: Default::default(),
contexts: Default::default(),
request: Default::default(),
}
}
}
Expand All @@ -1984,6 +1988,7 @@ impl<'a> Transaction<'a> {
start_timestamp: self.start_timestamp,
spans: self.spans,
contexts: self.contexts,
request: self.request,
}
}

Expand Down
14 changes: 14 additions & 0 deletions sentry/examples/performance-demo.rs
@@ -1,6 +1,8 @@
use std::thread;
use std::time::Duration;

use sentry::protocol::Request;

// cargo run --example performance-demo
fn main() {
let _sentry = sentry::init(sentry::ClientOptions {
Expand All @@ -12,6 +14,12 @@ fn main() {

let transaction =
sentry::start_transaction(sentry::TransactionContext::new("transaction", "root span"));
let tx_request = Request {
url: Some("https://honk.beep".parse().unwrap()),
method: Some("GET".to_string()),
..Request::default()
};
transaction.set_request(tx_request);
sentry::configure_scope(|scope| scope.set_span(Some(transaction.clone().into())));

main_span1();
Expand Down Expand Up @@ -76,6 +84,12 @@ where
sentry::start_transaction(ctx).into()
}
};
let span_request = Request {
url: Some("https://beep.beep".parse().unwrap()),
method: Some("GET".to_string()),
..Request::default()
};
span1.set_request(span_request);
sentry::configure_scope(|scope| scope.set_span(Some(span1.clone())));

let rv = f();
Expand Down
10 changes: 9 additions & 1 deletion sentry/tests/test_tracing.rs
@@ -1,7 +1,7 @@
#![cfg(feature = "test")]

use log_ as log;
use sentry::protocol::{Context, Value};
use sentry::protocol::{Context, Request, Value};
use tracing_ as tracing;
use tracing_subscriber::prelude::*;

Expand Down Expand Up @@ -146,6 +146,13 @@ fn test_set_transaction() {
|| {
let ctx = sentry::TransactionContext::new("old name", "ye, whatever");
let trx = sentry::start_transaction(ctx);
let request = Request {
url: Some("https://honk.beep".parse().unwrap()),
method: Some("GET".to_string()),
..Request::default()
};
trx.set_request(request);

sentry::configure_scope(|scope| scope.set_span(Some(trx.clone().into())));

sentry::configure_scope(|scope| scope.set_transaction(Some("new name")));
Expand All @@ -164,4 +171,5 @@ fn test_set_transaction() {
};

assert_eq!(transaction.name.as_deref().unwrap(), "new name");
assert!(transaction.request.is_some());
}