Skip to content

Commit

Permalink
Merge branch 'master' into ref/service-shared-response
Browse files Browse the repository at this point in the history
* master:
  ref(system): Introduce a generic recipient type (#1622)
  feat(transaction): Normalize transaction name (#1621)
  feat(server): Track metrics for OpenTelemetry events (#1618)
  bug(replays): Increase reserved space in payload chunks (#1601)
  feat(protocol): Add OpenTelemetry Context (#1617)
  • Loading branch information
jan-auer committed Nov 24, 2022
2 parents 2634214 + 6addb56 commit 483337c
Show file tree
Hide file tree
Showing 14 changed files with 592 additions and 48 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
**Features**:

- Dynamic sampling is now based on the volume received by Relay by default and does not include the original volume dropped by client-side sampling in SDKs. This is required for the final dynamic sampling feature in the latest Sentry plans. ([#1591](https://github.com/getsentry/relay/pull/1591))
- Add OpenTelemetry Context ([#1617](https://github.com/getsentry/relay/pull/1617))

**Internal**:

- Emit a `service.back_pressure` metric that measures internal back pressure by service. ([#1583](https://github.com/getsentry/relay/pull/1583))
- Track metrics for OpenTelemetry events. ([#1618](https://github.com/getsentry/relay/pull/1618))
- Normalize transaction name for URLs transaction source, by replacing UUIDs, SHAs and numerical IDs in transaction names by placeholders. ([#1621](https://github.com/getsentry/relay/pull/1621))

## 22.11.0

Expand Down
1 change: 1 addition & 0 deletions relay-cabi/src/processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ pub unsafe extern "C" fn relay_store_normalizer_normalize_event(
measurements_config: None, // only supported in relay
breakdowns_config: None, // only supported in relay
normalize_user_agent: config.normalize_user_agent,
normalize_transaction_name: false, // only supported in relay
is_renormalize: config.is_renormalize.unwrap_or(false),
};
light_normalize_event(&mut event, &light_normalization_config)?;
Expand Down
5 changes: 5 additions & 0 deletions relay-general/src/protocol/contexts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ mod runtime;
pub use runtime::*;
mod trace;
pub use trace::*;
mod otel;
pub use otel::*;

use crate::types::{Annotated, FromValue, Object, Value};

Expand Down Expand Up @@ -51,6 +53,8 @@ pub enum Context {
Reprocessing(Box<ReprocessingContext>),
/// Response information.
Response(Box<ResponseContext>),
/// OpenTelemetry information
Otel(Box<OtelContext>),
/// Additional arbitrary fields for forwards compatibility.
#[metastructure(fallback_variant)]
Other(#[metastructure(pii = "true")] Object<Value>),
Expand All @@ -72,6 +76,7 @@ impl Context {
Context::Trace(_) => Some(TraceContext::default_key()),
Context::Monitor(_) => Some(MonitorContext::default_key()),
Context::Response(_) => Some(ResponseContext::default_key()),
Context::Otel(_) => Some(OtelContext::default_key()),
Context::Other(_) => None,
}
}
Expand Down
146 changes: 146 additions & 0 deletions relay-general/src/protocol/contexts/otel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
use crate::types::{Annotated, Object, Value};

/// OpenTelemetry Context
///
/// If an event has this context, it was generated from an OpenTelemetry signal (trace, metric, log).
#[derive(Clone, Debug, Default, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
#[cfg_attr(feature = "jsonschema", derive(JsonSchema))]
pub struct OtelContext {
/// Attributes of the OpenTelemetry span that maps to a Sentry event.
///
/// <https://github.com/open-telemetry/opentelemetry-proto/blob/724e427879e3d2bae2edc0218fff06e37b9eb46e/opentelemetry/proto/trace/v1/trace.proto#L174-L186>
#[metastructure(pii = "maybe", bag_size = "large")]
attributes: Annotated<Object<Value>>,

/// Information about an OpenTelemetry resource.
///
/// <https://github.com/open-telemetry/opentelemetry-proto/blob/724e427879e3d2bae2edc0218fff06e37b9eb46e/opentelemetry/proto/resource/v1/resource.proto>
#[metastructure(pii = "maybe", bag_size = "large")]
resource: Annotated<Object<Value>>,

/// Additional arbitrary fields for forwards compatibility.
#[metastructure(additional_properties, retain = "true", pii = "maybe")]
pub other: Object<Value>,
}

impl OtelContext {
/// The key under which a runtime context is generally stored (in `Contexts`).
pub fn default_key() -> &'static str {
"otel"
}
}

#[cfg(test)]
mod tests {
use crate::protocol::Context;

use super::*;

#[test]
pub(crate) fn test_otel_context_roundtrip() {
let json = r#"{
"attributes": {
"app.payment.amount": 394.25,
"rpc.grpc.status_code": "1",
"rpc.method": "Charge",
"rpc.service": "hipstershop.PaymentService",
"rpc.system": "grpc"
},
"resource": {
"process.command": "/usr/src/app/index.js",
"process.command_line": "/usr/local/bin/node /usr/src/app/index.js",
"process.executable.name": "node",
"process.pid": 1,
"process.runtime.description": "Node.js",
"process.runtime.name": "nodejs",
"process.runtime.version": "16.18.0",
"service.name": "paymentservice",
"telemetry.sdk.language": "nodejs",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.7.0"
},
"other": "value",
"type": "otel"
}"#;
let context = Annotated::new(Context::Otel(Box::new(OtelContext {
attributes: Annotated::new(Object::from([
(
"app.payment.amount".to_string(),
Annotated::new(Value::F64(394.25)),
),
(
"rpc.grpc.status_code".to_string(),
Annotated::new(Value::String("1".to_string())),
),
(
"rpc.method".to_string(),
Annotated::new(Value::String("Charge".to_string())),
),
(
"rpc.service".to_string(),
Annotated::new(Value::String("hipstershop.PaymentService".to_string())),
),
(
"rpc.system".to_string(),
Annotated::new(Value::String("grpc".to_string())),
),
])),
resource: Annotated::new(Object::from([
(
"process.command".to_string(),
Annotated::new(Value::String("/usr/src/app/index.js".to_string())),
),
(
"process.command_line".to_string(),
Annotated::new(Value::String(
"/usr/local/bin/node /usr/src/app/index.js".to_string(),
)),
),
(
"process.executable.name".to_string(),
Annotated::new(Value::String("node".to_string())),
),
("process.pid".to_string(), Annotated::new(Value::I64(1))),
(
"process.runtime.description".to_string(),
Annotated::new(Value::String("Node.js".to_string())),
),
(
"process.runtime.name".to_string(),
Annotated::new(Value::String("nodejs".to_string())),
),
(
"process.runtime.version".to_string(),
Annotated::new(Value::String("16.18.0".to_string())),
),
(
"service.name".to_string(),
Annotated::new(Value::String("paymentservice".to_string())),
),
(
"telemetry.sdk.language".to_string(),
Annotated::new(Value::String("nodejs".to_string())),
),
(
"telemetry.sdk.name".to_string(),
Annotated::new(Value::String("opentelemetry".to_string())),
),
(
"telemetry.sdk.version".to_string(),
Annotated::new(Value::String("1.7.0".to_string())),
),
])),
other: {
let mut map = Object::new();
map.insert(
"other".to_string(),
Annotated::new(Value::String("value".to_string())),
);
map
},
})));

assert_eq!(context, Annotated::from_json(json).unwrap());
assert_eq!(json, context.to_json_pretty().unwrap());
}
}
1 change: 1 addition & 0 deletions relay-general/src/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod event_error;
mod geo;
mod legacy;
mod normalize;
mod regexes;
mod remove_other;
mod schema;
mod transactions;
Expand Down
5 changes: 4 additions & 1 deletion relay-general/src/store/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,7 @@ pub struct LightNormalizationConfig<'a> {
pub measurements_config: Option<&'a MeasurementsConfig>,
pub breakdowns_config: Option<&'a BreakdownsConfig>,
pub normalize_user_agent: Option<bool>,
pub normalize_transaction_name: bool,
pub is_renormalize: bool,
}

Expand All @@ -679,7 +680,9 @@ pub fn light_normalize_event(
// (internally noops for non-transaction events).
// TODO: Parts of this processor should probably be a filter so we
// can revert some changes to ProcessingAction
transactions::TransactionsProcessor.process_event(event, meta, ProcessingState::root())?;
let mut transactions_processor =
transactions::TransactionsProcessor::new(config.normalize_transaction_name);
transactions_processor.process_event(event, meta, ProcessingState::root())?;

// Check for required and non-empty values
schema::SchemaProcessor.process_event(event, meta, ProcessingState::root())?;
Expand Down
60 changes: 60 additions & 0 deletions relay-general/src/store/regexes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use once_cell::sync::Lazy;
use regex::Regex;

/// Contains multiple capture groups which will be used as a replace placeholder.
///
/// This regex is inspired by one used for grouping:
/// <https://github.com/getsentry/sentry/blob/6ba59023a78bfe033e48ea4e035b64710a905c6b/src/sentry/grouping/strategies/message.py#L16-L97>
pub static TRANSACTION_NAME_NORMALIZER_REGEX: Lazy<Regex> = Lazy::new(|| {
Regex::new(
r#"
(?x)
(?P<uuid>
\b
[0-9a-fA-F]{8}-
[0-9a-fA-F]{4}-
[0-9a-fA-F]{4}-
[0-9a-fA-F]{4}-
[0-9a-fA-F]{12}
\b
) |
(?P<sha1>
\b[0-9a-fA-F]{40}\b
) |
(?P<md5>
\b[0-9a-fA-F]{32}\b
) |
(?P<date>
(?:
(?:\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|
(?:\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|
(?:\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))
) |
(?:
\b(?:(Sun|Mon|Tue|Wed|Thu|Fri|Sat)\s+)?
(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+
(?:[\d]{1,2})\s+
(?:[\d]{2}:[\d]{2}:[\d]{2})\s+
[\d]{4}
) |
(?:
\b(?:(Sun|Mon|Tue|Wed|Thu|Fri|Sat),\s+)?
(?:0[1-9]|[1-2]?[\d]|3[01])\s+
(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+
(?:19[\d]{2}|[2-9][\d]{3})\s+
(?:2[0-3]|[0-1][\d]):([0-5][\d])
(?::(60|[0-5][\d]))?\s+
(?:[-\+][\d]{2}[0-5][\d]|(?:UT|GMT|(?:E|C|M|P)(?:ST|DT)|[A-IK-Z]))
)
) |
(?P<hex>
\b0[xX][0-9a-fA-F]+\b
) |
(?P<int>
\b\d{2,}\b
)
"#,
)
.unwrap()
});
Loading

0 comments on commit 483337c

Please sign in to comment.