@@ -51,6 +51,13 @@ impl Hub {
51
51
52
52
// "Context" Types:
53
53
54
+ /// Arbitrary data passed by the caller, when starting a transaction.
55
+ ///
56
+ /// May be inspected by the user in the `traces_sampler` callback, if set.
57
+ ///
58
+ /// Represents arbitrary JSON data, the top level of which must be a map.
59
+ pub type CustomTransactionContext = serde_json:: Map < String , serde_json:: Value > ;
60
+
54
61
/// The Transaction Context used to start a new Performance Monitoring Transaction.
55
62
///
56
63
/// The Transaction Context defines the metadata for a Performance Monitoring
@@ -63,6 +70,7 @@ pub struct TransactionContext {
63
70
trace_id : protocol:: TraceId ,
64
71
parent_span_id : Option < protocol:: SpanId > ,
65
72
sampled : Option < bool > ,
73
+ custom : Option < CustomTransactionContext > ,
66
74
}
67
75
68
76
impl TransactionContext {
@@ -108,6 +116,7 @@ impl TransactionContext {
108
116
trace_id,
109
117
parent_span_id,
110
118
sampled,
119
+ custom : None ,
111
120
}
112
121
}
113
122
@@ -144,6 +153,7 @@ impl TransactionContext {
144
153
trace_id,
145
154
parent_span_id : Some ( parent_span_id) ,
146
155
sampled,
156
+ custom : None ,
147
157
}
148
158
}
149
159
@@ -169,6 +179,41 @@ impl TransactionContext {
169
179
pub fn operation ( & self ) -> & str {
170
180
& self . op
171
181
}
182
+
183
+ /// Get the custom context of this Transaction.
184
+ pub fn custom ( & self ) -> Option < & CustomTransactionContext > {
185
+ self . custom . as_ref ( )
186
+ }
187
+
188
+ /// Update the custom context of this Transaction.
189
+ ///
190
+ /// For simply adding a key, use the `custom_insert` method.
191
+ pub fn custom_mut ( & mut self ) -> & mut Option < CustomTransactionContext > {
192
+ & mut self . custom
193
+ }
194
+
195
+ /// Inserts a key-value pair into the custom context.
196
+ ///
197
+ /// If the context did not have this key present, None is returned.
198
+ ///
199
+ /// If the context did have this key present, the value is updated, and the old value is returned.
200
+ pub fn custom_insert (
201
+ & mut self ,
202
+ key : String ,
203
+ value : serde_json:: Value ,
204
+ ) -> Option < serde_json:: Value > {
205
+ // Get the custom context
206
+ let mut custom = None ;
207
+ std:: mem:: swap ( & mut self . custom , & mut custom) ;
208
+
209
+ // Initialise the context, if not used yet
210
+ let mut custom = custom. unwrap_or_default ( ) ;
211
+
212
+ // And set our key
213
+ let existing_value = custom. insert ( key, value) ;
214
+ std:: mem:: swap ( & mut self . custom , & mut Some ( custom) ) ;
215
+ existing_value
216
+ }
172
217
}
173
218
174
219
/// A function to be run for each new transaction, to determine the rate at which
@@ -772,5 +817,31 @@ mod tests {
772
817
assert_eq ! ( transaction_sample_rate( Some ( & sampler) , & ctx, 0.3 ) , 0.8 ) ;
773
818
ctx. set_sampled ( None ) ;
774
819
assert_eq ! ( transaction_sample_rate( Some ( & sampler) , & ctx, 0.3 ) , 0.6 ) ;
820
+
821
+ // Can use first-class and custom attributes of the context.
822
+ let sampler = |ctx : & TransactionContext | {
823
+ if ctx. name ( ) == "must-name" || ctx. operation ( ) == "must-operation" {
824
+ return 1.0 ;
825
+ }
826
+
827
+ if let Some ( custom) = ctx. custom ( ) {
828
+ if let Some ( rate) = custom. get ( "rate" ) {
829
+ if let Some ( rate) = rate. as_f64 ( ) {
830
+ return rate as f32 ;
831
+ }
832
+ }
833
+ }
834
+
835
+ 0.1
836
+ } ;
837
+ // First class attributes
838
+ let ctx = TransactionContext :: new ( "noop" , "must-operation" ) ;
839
+ assert_eq ! ( transaction_sample_rate( Some ( & sampler) , & ctx, 0.3 ) , 1.0 ) ;
840
+ let ctx = TransactionContext :: new ( "must-name" , "noop" ) ;
841
+ assert_eq ! ( transaction_sample_rate( Some ( & sampler) , & ctx, 0.3 ) , 1.0 ) ;
842
+ // Custom data payload
843
+ let mut ctx = TransactionContext :: new ( "noop" , "noop" ) ;
844
+ ctx. custom_insert ( "rate" . to_owned ( ) , serde_json:: json!( 0.7 ) ) ;
845
+ assert_eq ! ( transaction_sample_rate( Some ( & sampler) , & ctx, 0.3 ) , 0.7 ) ;
775
846
}
776
847
}
0 commit comments