@@ -11,6 +11,7 @@ const helper = require('../../lib/agent_helper')
11
11
12
12
const agent = helper . instrumentMockedAgent ( )
13
13
const cassandra = require ( 'cassandra-driver' )
14
+ const { findSegment } = require ( '../../lib/metrics_helper' )
14
15
15
16
// constants for keyspace and table creation
16
17
const KS = 'test'
@@ -25,6 +26,26 @@ const client = new cassandra.Client({
25
26
localDataCenter : 'datacenter1'
26
27
} )
27
28
29
+ const colValArr = [ 'Jim' , 'Bob' , 'Joe' ]
30
+ const pkValArr = [ 111 , 222 , 333 ]
31
+ let insQuery = 'INSERT INTO ' + KS + '.' + FAM + ' (' + PK + ',' + COL
32
+ insQuery += ') VALUES(?, ?);'
33
+
34
+ const insArr = [
35
+ { query : insQuery , params : [ pkValArr [ 0 ] , colValArr [ 0 ] ] } ,
36
+ { query : insQuery , params : [ pkValArr [ 1 ] , colValArr [ 1 ] ] } ,
37
+ { query : insQuery , params : [ pkValArr [ 2 ] , colValArr [ 2 ] ] }
38
+ ]
39
+
40
+ const hints = [
41
+ [ 'int' , 'varchar' ] ,
42
+ [ 'int' , 'varchar' ] ,
43
+ [ 'int' , 'varchar' ]
44
+ ]
45
+
46
+ let selQuery = 'SELECT * FROM ' + KS + '.' + FAM + ' WHERE '
47
+ selQuery += PK + ' = 111;'
48
+
28
49
/**
29
50
* Deletion of testing keyspace if already exists,
30
51
* then recreation of a testable keyspace and table
@@ -33,7 +54,7 @@ const client = new cassandra.Client({
33
54
* @param Callback function to set off running the tests
34
55
*/
35
56
36
- async function cassSetup ( runTest ) {
57
+ async function cassSetup ( ) {
37
58
const setupClient = new cassandra . Client ( {
38
59
contactPoints : [ params . cassandra_host ] ,
39
60
protocolOptions : params . cassandra_port ,
@@ -66,146 +87,151 @@ async function cassSetup(runTest) {
66
87
await runCommand ( famCreate )
67
88
68
89
setupClient . shutdown ( )
69
- runTest ( )
70
90
}
71
91
72
92
test ( 'Cassandra instrumentation' , { timeout : 5000 } , async function testInstrumentation ( t ) {
73
- t . plan ( 1 )
74
- await cassSetup ( runTest )
75
-
76
- function runTest ( ) {
77
- t . test ( 'executeBatch' , function ( t ) {
78
- t . notOk ( agent . getTransaction ( ) , 'no transaction should be in play' )
79
- helper . runInTransaction ( agent , function transactionInScope ( tx ) {
80
- const transaction = agent . getTransaction ( )
81
- t . ok ( transaction , 'transaction should be visible' )
82
- t . equal ( tx , transaction , 'We got the same transaction' )
83
- const colValArr = [ 'Jim' , 'Bob' , 'Joe' ]
84
- const pkValArr = [ 111 , 222 , 333 ]
85
- let insQuery = 'INSERT INTO ' + KS + '.' + FAM + ' (' + PK + ',' + COL
86
- insQuery += ') VALUES(?, ?);'
87
-
88
- const insArr = [
89
- { query : insQuery , params : [ pkValArr [ 0 ] , colValArr [ 0 ] ] } ,
90
- { query : insQuery , params : [ pkValArr [ 1 ] , colValArr [ 1 ] ] } ,
91
- { query : insQuery , params : [ pkValArr [ 2 ] , colValArr [ 2 ] ] }
92
- ]
93
-
94
- const hints = [
95
- [ 'int' , 'varchar' ] ,
96
- [ 'int' , 'varchar' ] ,
97
- [ 'int' , 'varchar' ]
98
- ]
99
-
100
- client . batch ( insArr , { hints : hints } , function done ( error , ok ) {
93
+ t . before ( async function ( ) {
94
+ await cassSetup ( )
95
+ } )
96
+
97
+ t . teardown ( function tearDown ( ) {
98
+ helper . unloadAgent ( agent )
99
+ client . shutdown ( )
100
+ } )
101
+
102
+ t . afterEach ( ( ) => {
103
+ agent . queries . clear ( )
104
+ agent . metrics . clear ( )
105
+ } )
106
+
107
+ t . test ( 'executeBatch - callback style' , function ( t ) {
108
+ t . notOk ( agent . getTransaction ( ) , 'no transaction should be in play' )
109
+ helper . runInTransaction ( agent , function transactionInScope ( tx ) {
110
+ const transaction = agent . getTransaction ( )
111
+ t . ok ( transaction , 'transaction should be visible' )
112
+ t . equal ( tx , transaction , 'We got the same transaction' )
113
+
114
+ client . batch ( insArr , { hints : hints } , function done ( error , ok ) {
115
+ if ( error ) {
116
+ t . error ( error )
117
+ return t . end ( )
118
+ }
119
+
120
+ t . ok ( agent . getTransaction ( ) , 'transaction should still be visible' )
121
+ t . ok ( ok , 'everything should be peachy after setting' )
122
+
123
+ client . execute ( selQuery , function ( error , value ) {
101
124
if ( error ) {
102
- t . fail ( error )
103
- return t . end ( )
125
+ return t . error ( error )
104
126
}
105
127
106
- t . ok ( agent . getTransaction ( ) , 'transaction should still be visible' )
107
- t . ok ( ok , 'everything should be peachy after setting' )
108
-
109
- let selQuery = 'SELECT * FROM ' + KS + '.' + FAM + ' WHERE '
110
- selQuery += PK + ' = 111;'
111
- client . execute ( selQuery , function ( error , value ) {
112
- if ( error ) {
113
- return t . fail ( error )
114
- }
128
+ t . ok ( agent . getTransaction ( ) , 'transaction should still still be visible' )
129
+ t . equal ( value . rows [ 0 ] [ COL ] , colValArr [ 0 ] , 'Cassandra client should still work' )
130
+
131
+ t . equal (
132
+ transaction . trace . root . children . length ,
133
+ 1 ,
134
+ 'there should be only one child of the root'
135
+ )
136
+ verifyTrace ( t , transaction . trace , KS + '.' + FAM )
137
+ transaction . end ( )
138
+ checkMetric ( t )
139
+ t . end ( )
140
+ } )
141
+ } )
142
+ } )
143
+ } )
115
144
145
+ t . test ( 'executeBatch - promise style' , function ( t ) {
146
+ t . notOk ( agent . getTransaction ( ) , 'no transaction should be in play' )
147
+ helper . runInTransaction ( agent , function transactionInScope ( tx ) {
148
+ const transaction = agent . getTransaction ( )
149
+ t . ok ( transaction , 'transaction should be visible' )
150
+ t . equal ( tx , transaction , 'We got the same transaction' )
151
+
152
+ client . batch ( insArr , { hints : hints } ) . then ( function ( ) {
153
+ client
154
+ . execute ( selQuery )
155
+ . then ( ( result ) => {
116
156
t . ok ( agent . getTransaction ( ) , 'transaction should still still be visible' )
117
- t . equal ( value . rows [ 0 ] [ COL ] , colValArr [ 0 ] , 'Cassandra client should still work' )
118
-
119
- const trace = transaction . trace
120
- t . ok ( trace , 'trace should exist' )
121
- t . ok ( trace . root , 'root element should exist' )
122
-
123
- t . equal ( trace . root . children . length , 1 , 'there should be only one child of the root' )
124
-
125
- const setSegment = trace . root . children [ 0 ]
126
- t . ok ( setSegment , 'trace segment for insert should exist' )
127
- if ( setSegment ) {
128
- t . equal (
129
- setSegment . name ,
130
- 'Datastore/statement/Cassandra/test.testFamily/insert/batch' ,
131
- 'should register the executeBatch'
132
- )
133
- t . ok (
134
- setSegment . children . length >= 2 ,
135
- 'set should have atleast a dns lookup and callback child'
136
- )
137
-
138
- const setSegmentAttributes = setSegment . getAttributes ( )
139
- t . equal ( setSegmentAttributes . product , 'Cassandra' , 'should set product attribute' )
140
- t . equal ( setSegmentAttributes . port_path_or_id , '9042' , 'should set port attribute' )
141
- t . equal (
142
- setSegmentAttributes . database_name ,
143
- 'test' ,
144
- 'should set database_name attribute'
145
- )
146
- t . equal (
147
- setSegmentAttributes . host ,
148
- agent . config . getHostnameSafe ( ) ,
149
- 'should set host attribute'
150
- )
151
-
152
- const childIndex = setSegment . children . length - 1
153
- const getSegment = setSegment . children [ childIndex ] . children [ 0 ]
154
- t . ok ( getSegment , 'trace segment for select should exist' )
155
- if ( getSegment ) {
156
- t . equal (
157
- getSegment . name ,
158
- 'Datastore/statement/Cassandra/test.testFamily/select' ,
159
- 'should register the execute'
160
- )
161
-
162
- t . ok ( getSegment . children . length >= 1 , 'get should have a callback segment' )
163
-
164
- const getSegmentAttributes = getSegment . getAttributes ( )
165
- t . equal (
166
- getSegmentAttributes . product ,
167
- 'Cassandra' ,
168
- 'get should set product attribute'
169
- )
170
- t . equal (
171
- getSegmentAttributes . port_path_or_id ,
172
- '9042' ,
173
- 'get should set port attribute'
174
- )
175
- t . equal (
176
- getSegmentAttributes . database_name ,
177
- 'test' ,
178
- 'get should set database_name attribute'
179
- )
180
- t . equal (
181
- getSegmentAttributes . host ,
182
- agent . config . getHostnameSafe ( ) ,
183
- 'get should set host attribute'
184
- )
185
-
186
- t . ok ( getSegment . timer . hrDuration , 'trace segment should have ended' )
187
- }
188
- }
189
-
157
+ t . equal ( result . rows [ 0 ] [ COL ] , colValArr [ 0 ] , 'Cassandra client should still work' )
158
+
159
+ t . equal (
160
+ transaction . trace . root . children . length ,
161
+ 2 ,
162
+ 'there should be two children of the root'
163
+ )
164
+ verifyTrace ( t , transaction . trace , KS + '.' + FAM )
190
165
transaction . end ( )
191
- checkMetric ( 'Datastore/operation/Cassandra/insert' , 1 )
192
- checkMetric ( 'Datastore/allWeb' , 2 )
193
- checkMetric ( 'Datastore/Cassandra/allWeb' , 2 )
194
- checkMetric ( 'Datastore/Cassandra/all' , 2 )
195
- checkMetric ( 'Datastore/all' , 2 )
196
- checkMetric ( 'Datastore/statement/Cassandra/test.testFamily/insert' , 1 )
197
- checkMetric ( 'Datastore/operation/Cassandra/select' , 1 )
198
- checkMetric ( 'Datastore/statement/Cassandra/test.testFamily/select' , 1 )
199
-
166
+ checkMetric ( t )
167
+ } )
168
+ . catch ( ( error ) => {
169
+ t . error ( error )
170
+ } )
171
+ . finally ( ( ) => {
200
172
t . end ( )
201
173
} )
174
+ } )
175
+ } )
176
+ } )
177
+
178
+ t . test ( 'executeBatch - slow query' , function ( t ) {
179
+ t . notOk ( agent . getTransaction ( ) , 'no transaction should be in play' )
180
+ helper . runInTransaction ( agent , function transactionInScope ( tx ) {
181
+ // enable slow queries
182
+ agent . config . transaction_tracer . explain_threshold = 1
183
+ agent . config . transaction_tracer . record_sql = 'raw'
184
+ agent . config . slow_sql . enabled = true
185
+
186
+ const transaction = agent . getTransaction ( )
187
+ t . ok ( transaction , 'transaction should be visible' )
188
+ t . equal ( tx , transaction , 'We got the same transaction' )
189
+
190
+ client . batch ( insArr , { hints : hints } , function done ( error , ok ) {
191
+ if ( error ) {
192
+ t . error ( error )
193
+ return t . end ( )
194
+ }
195
+
196
+ const slowQuery = 'SELECT * FROM ' + KS + '.' + FAM
197
+ t . ok ( agent . getTransaction ( ) , 'transaction should still be visible' )
198
+ t . ok ( ok , 'everything should be peachy after setting' )
199
+
200
+ client . execute ( slowQuery , function ( error ) {
201
+ if ( error ) {
202
+ return t . error ( error )
203
+ }
204
+
205
+ verifyTrace ( t , transaction . trace , KS + '.' + FAM )
206
+ transaction . end ( )
207
+ t . ok ( agent . queries . samples . size > 0 , 'there should be a slow query' )
208
+ checkMetric ( t )
209
+ t . end ( )
202
210
} )
203
211
} )
212
+ } )
213
+ } )
204
214
205
- function checkMetric ( name , count , scoped ) {
206
- const agentMetrics = agent . metrics . _metrics
207
- const metric = agentMetrics [ scoped ? 'scoped' : 'unscoped' ] [ name ]
208
- t . ok ( metric , 'metric "' + name + '" should exist' )
215
+ function checkMetric ( t , scoped ) {
216
+ const agentMetrics = agent . metrics . _metrics
217
+
218
+ const expected = {
219
+ 'Datastore/operation/Cassandra/insert' : 1 ,
220
+ 'Datastore/allWeb' : 2 ,
221
+ 'Datastore/Cassandra/allWeb' : 2 ,
222
+ 'Datastore/Cassandra/all' : 2 ,
223
+ 'Datastore/all' : 2 ,
224
+ 'Datastore/statement/Cassandra/test.testFamily/insert' : 1 ,
225
+ 'Datastore/operation/Cassandra/select' : 1 ,
226
+ 'Datastore/statement/Cassandra/test.testFamily/select' : 1
227
+ }
228
+
229
+ for ( const expectedMetric in expected ) {
230
+ if ( expected . hasOwnProperty ( expectedMetric ) ) {
231
+ const count = expected [ expectedMetric ]
232
+
233
+ const metric = agentMetrics [ scoped ? 'scoped' : 'unscoped' ] [ expectedMetric ]
234
+ t . ok ( metric , 'metric "' + expectedMetric + '" should exist' )
209
235
if ( ! metric ) {
210
236
return
211
237
}
@@ -217,11 +243,54 @@ test('Cassandra instrumentation', { timeout: 5000 }, async function testInstrume
217
243
t . ok ( metric . max , 'should have set max' )
218
244
t . ok ( metric . sumOfSquares , 'should have set sumOfSquares' )
219
245
}
220
- } )
246
+ }
247
+ }
221
248
222
- t . teardown ( function tearDown ( ) {
223
- helper . unloadAgent ( agent )
224
- client . shutdown ( )
225
- } )
249
+ function verifyTrace ( t , trace , table ) {
250
+ t . ok ( trace , 'trace should exist' )
251
+ t . ok ( trace . root , 'root element should exist' )
252
+
253
+ const setSegment = findSegment (
254
+ trace . root ,
255
+ 'Datastore/statement/Cassandra/' + table + '/insert/batch'
256
+ )
257
+
258
+ t . ok ( setSegment , 'trace segment for insert should exist' )
259
+
260
+ if ( setSegment ) {
261
+ verifyTraceSegment ( t , setSegment , 'insert/batch' )
262
+
263
+ t . ok (
264
+ setSegment . children . length >= 2 ,
265
+ 'set should have at least a dns lookup and callback/promise child'
266
+ )
267
+
268
+ const getSegment = findSegment (
269
+ trace . root ,
270
+ 'Datastore/statement/Cassandra/' + table + '/select'
271
+ )
272
+ t . ok ( getSegment , 'trace segment for select should exist' )
273
+
274
+ if ( getSegment ) {
275
+ verifyTraceSegment ( t , getSegment , 'select' )
276
+
277
+ t . ok ( getSegment . children . length >= 1 , 'get should have a callback/promise segment' )
278
+ t . ok ( getSegment . timer . hrDuration , 'trace segment should have ended' )
279
+ }
280
+ }
281
+ }
282
+
283
+ function verifyTraceSegment ( t , segment , queryType ) {
284
+ t . equal (
285
+ segment . name ,
286
+ 'Datastore/statement/Cassandra/' + KS + '.' + FAM + '/' + queryType ,
287
+ 'should register the execute'
288
+ )
289
+
290
+ const segmentAttributes = segment . getAttributes ( )
291
+ t . equal ( segmentAttributes . product , 'Cassandra' , 'should set product attribute' )
292
+ t . equal ( segmentAttributes . port_path_or_id , '9042' , 'should set port attribute' )
293
+ t . equal ( segmentAttributes . database_name , 'test' , 'should set database_name attribute' )
294
+ t . equal ( segmentAttributes . host , agent . config . getHostnameSafe ( ) , 'should set host attribute' )
226
295
}
227
296
} )
0 commit comments