1
- import { getMainCarrier , Hub } from '@sentry/hub' ;
1
+ import { getActiveDomain , getMainCarrier , Hub } from '@sentry/hub' ;
2
+ import { Handlers } from '@sentry/node' ;
2
3
import { SampleContext , TransactionContext } from '@sentry/types' ;
3
- import { hasTracingEnabled , logger } from '@sentry/utils' ;
4
+ import { hasTracingEnabled , isInstanceOf , isNodeEnv , logger } from '@sentry/utils' ;
5
+ import * as http from 'http' ; // TODO - is this okay, or do we need to export the type we need from our node SDK?
4
6
5
7
import { registerErrorInstrumentation } from './errors' ;
6
8
import { IdleTransaction } from './idletransaction' ;
@@ -76,13 +78,53 @@ function sample<T extends Transaction>(hub: Hub, transaction: T, sampleContext:
76
78
77
79
return transaction ;
78
80
}
81
+ /**
82
+ * Gets the correct context to pass to the tracesSampler, based on the environment (i.e., which SDK is being used)
83
+ *
84
+ * @returns A SampleContext object
85
+ */
86
+ function getDefaultSampleContext ( ) : SampleContext {
87
+ const defaultSampleContext : SampleContext = { } ;
88
+
89
+ if ( isNodeEnv ( ) ) {
90
+ // look at koa TODO
91
+ const domain = getActiveDomain ( ) ;
92
+ if ( domain ) {
93
+ // TODO is the below true?
94
+ // for all node servers that we currently support, we store the incoming request object (which is an instance of
95
+ // http.IncomingMessage) on the domain the domain is stored as an array, so our only way to find the request is to
96
+ // iterate through the array and compare types
97
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
98
+ const request = domain . members . find ( ( member : any ) => isInstanceOf ( member , http . IncomingMessage ) ) ;
99
+ if ( request ) {
100
+ defaultSampleContext . request = Handlers . extractRequestData ( request ) ;
101
+ }
102
+ }
103
+ }
104
+
105
+ // we must be in browser-js (or some derivative thereof)
106
+ else {
107
+ // we take a copy of the location object rather than just a reference to it in case there's a navigation in the
108
+ // instant between when the transaction starts and when the sampler is called
109
+ defaultSampleContext . location = { ...window . location } ;
110
+ }
111
+
112
+ return defaultSampleContext ;
113
+ }
79
114
80
115
/**
81
- * {@see Hub.startTransaction }
116
+ * Creates a new transaction and adds a sampling decision if it doesn't yet have one.
117
+ *
118
+ * The Hub.startTransaction method delegates to this method to do its work, passing the Hub instance in as `this`.
119
+ * Exists as a separate function so that it can be injected into the class as an "extension method."
120
+ *
121
+ * @returns The new transaction
122
+ *
123
+ * @see {@link Hub.startTransaction }
82
124
*/
83
125
function startTransaction ( this : Hub , context : TransactionContext , sampleContext ?: SampleContext ) : Transaction {
84
126
const transaction = new Transaction ( context , this ) ;
85
- return sample ( this , transaction , sampleContext ) ;
127
+ return sample ( this , transaction , { ... getDefaultSampleContext ( ) , ... sampleContext } ) ;
86
128
}
87
129
88
130
/**
@@ -96,7 +138,7 @@ export function startIdleTransaction(
96
138
sampleContext ?: SampleContext ,
97
139
) : IdleTransaction {
98
140
const transaction = new IdleTransaction ( context , hub , idleTimeout , onScope ) ;
99
- return sample ( hub , transaction , sampleContext ) ;
141
+ return sample ( hub , transaction , { ... getDefaultSampleContext ( ) , ... sampleContext } ) ;
100
142
}
101
143
102
144
/**
0 commit comments