github.com/newrelic/go-agent@v3.26.0+incompatible/internal/slow_queries_test.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package internal 5 6 import ( 7 "math/rand" 8 "strconv" 9 "strings" 10 "testing" 11 "time" 12 ) 13 14 func TestEmptySlowQueriesData(t *testing.T) { 15 slows := newSlowQueries(maxHarvestSlowSQLs) 16 js, err := slows.Data("agentRunID", time.Now()) 17 if nil != js || nil != err { 18 t.Error(string(js), err) 19 } 20 } 21 22 func TestSlowQueriesBasic(t *testing.T) { 23 acfg := CreateAttributeConfig(sampleAttributeConfigInput, true) 24 attr := NewAttributes(acfg) 25 attr.Agent.Add(attributeRequestURI, "/zip/zap", nil) 26 txnEvent := TxnEvent{ 27 FinalName: "WebTransaction/Go/hello", 28 Duration: 3 * time.Second, 29 Attrs: attr, 30 BetterCAT: BetterCAT{ 31 Enabled: false, 32 }, 33 } 34 35 txnSlows := newSlowQueries(maxTxnSlowQueries) 36 qParams, err := vetQueryParameters(map[string]interface{}{ 37 strings.Repeat("X", attributeKeyLengthLimit+1): "invalid-key", 38 "invalid-value": struct{}{}, 39 "valid": 123, 40 }) 41 if nil == err { 42 t.Error("expected error") 43 } 44 txnSlows.observeInstance(slowQueryInstance{ 45 Duration: 2 * time.Second, 46 DatastoreMetric: "Datastore/statement/MySQL/users/INSERT", 47 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 48 Host: "db-server-1", 49 PortPathOrID: "3306", 50 DatabaseName: "production", 51 StackTrace: nil, 52 QueryParameters: qParams, 53 }) 54 harvestSlows := newSlowQueries(maxHarvestSlowSQLs) 55 harvestSlows.Merge(txnSlows, txnEvent) 56 js, err := harvestSlows.Data("agentRunID", time.Now()) 57 expect := CompactJSONString(`[[ 58 [ 59 "WebTransaction/Go/hello", 60 "/zip/zap", 61 3722056893, 62 "INSERT INTO users (name, age) VALUES ($1, $2)", 63 "Datastore/statement/MySQL/users/INSERT", 64 1, 65 2000, 66 2000, 67 2000, 68 { 69 "host":"db-server-1", 70 "port_path_or_id":"3306", 71 "database_name":"production", 72 "query_parameters":{ 73 "valid":123 74 } 75 } 76 ] 77 ]]`) 78 if nil != err { 79 t.Error(err) 80 } 81 if string(js) != expect { 82 t.Error(string(js), expect) 83 } 84 } 85 86 func TestSlowQueriesExcludeURI(t *testing.T) { 87 c := sampleAttributeConfigInput 88 c.Attributes.Exclude = []string{"request.uri"} 89 acfg := CreateAttributeConfig(c, true) 90 attr := NewAttributes(acfg) 91 attr.Agent.Add(attributeRequestURI, "/zip/zap", nil) 92 txnEvent := TxnEvent{ 93 FinalName: "WebTransaction/Go/hello", 94 Duration: 3 * time.Second, 95 Attrs: attr, 96 BetterCAT: BetterCAT{ 97 Enabled: false, 98 }, 99 } 100 txnSlows := newSlowQueries(maxTxnSlowQueries) 101 qParams, err := vetQueryParameters(map[string]interface{}{ 102 strings.Repeat("X", attributeKeyLengthLimit+1): "invalid-key", 103 "invalid-value": struct{}{}, 104 "valid": 123, 105 }) 106 if nil == err { 107 t.Error("expected error") 108 } 109 txnSlows.observeInstance(slowQueryInstance{ 110 Duration: 2 * time.Second, 111 DatastoreMetric: "Datastore/statement/MySQL/users/INSERT", 112 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 113 Host: "db-server-1", 114 PortPathOrID: "3306", 115 DatabaseName: "production", 116 StackTrace: nil, 117 QueryParameters: qParams, 118 }) 119 harvestSlows := newSlowQueries(maxHarvestSlowSQLs) 120 harvestSlows.Merge(txnSlows, txnEvent) 121 js, err := harvestSlows.Data("agentRunID", time.Now()) 122 expect := CompactJSONString(`[[ 123 [ 124 "WebTransaction/Go/hello", 125 "", 126 3722056893, 127 "INSERT INTO users (name, age) VALUES ($1, $2)", 128 "Datastore/statement/MySQL/users/INSERT", 129 1, 130 2000, 131 2000, 132 2000, 133 { 134 "host":"db-server-1", 135 "port_path_or_id":"3306", 136 "database_name":"production", 137 "query_parameters":{ 138 "valid":123 139 } 140 } 141 ] 142 ]]`) 143 if nil != err { 144 t.Error(err) 145 } 146 if string(js) != expect { 147 t.Error(string(js), expect) 148 } 149 } 150 151 func TestSlowQueriesAggregation(t *testing.T) { 152 max := 50 153 slows := make([]slowQueryInstance, 3*max) 154 for i := 0; i < max; i++ { 155 num := i + 1 156 str := strconv.Itoa(num) 157 duration := time.Duration(num) * time.Second 158 slow := slowQueryInstance{ 159 DatastoreMetric: "Datastore/" + str, 160 ParameterizedQuery: str, 161 } 162 slow.Duration = duration 163 slow.TxnEvent = TxnEvent{ 164 FinalName: "Txn/0" + str, 165 } 166 slows[i*3+0] = slow 167 slow.Duration = duration + (100 * time.Second) 168 slow.TxnEvent = TxnEvent{ 169 FinalName: "Txn/1" + str, 170 } 171 slows[i*3+1] = slow 172 slow.Duration = duration + (200 * time.Second) 173 slow.TxnEvent = TxnEvent{ 174 FinalName: "Txn/2" + str, 175 } 176 slows[i*3+2] = slow 177 } 178 sq := newSlowQueries(10) 179 seed := int64(99) // arbitrary fixed seed 180 r := rand.New(rand.NewSource(seed)) 181 perm := r.Perm(max * 3) 182 for _, idx := range perm { 183 sq.observeInstance(slows[idx]) 184 } 185 js, err := sq.Data("agentRunID", time.Now()) 186 expect := CompactJSONString(`[[ 187 ["Txn/241","",2296612630,"41","Datastore/41",1,241000,241000,241000,{}], 188 ["Txn/242","",2279835011,"42","Datastore/42",2,384000,142000,242000,{}], 189 ["Txn/243","",2263057392,"43","Datastore/43",2,386000,143000,243000,{}], 190 ["Txn/244","",2380500725,"44","Datastore/44",3,432000,44000,244000,{}], 191 ["Txn/247","",2330167868,"47","Datastore/47",2,394000,147000,247000,{}], 192 ["Txn/245","",2363723106,"45","Datastore/45",2,290000,45000,245000,{}], 193 ["Txn/250","",2212577440,"50","Datastore/50",1,250000,250000,250000,{}], 194 ["Txn/246","",2346945487,"46","Datastore/46",2,392000,146000,246000,{}], 195 ["Txn/249","",2430833582,"49","Datastore/49",3,447000,49000,249000,{}], 196 ["Txn/248","",2447611201,"48","Datastore/48",3,444000,48000,248000,{}] 197 ]]`) 198 if nil != err { 199 t.Error(err) 200 } 201 if string(js) != expect { 202 t.Error(string(js), expect) 203 } 204 } 205 206 func TestSlowQueriesBetterCAT(t *testing.T) { 207 acfg := CreateAttributeConfig(sampleAttributeConfigInput, true) 208 attr := NewAttributes(acfg) 209 attr.Agent.Add(attributeRequestURI, "/zip/zap", nil) 210 txnEvent := TxnEvent{ 211 FinalName: "WebTransaction/Go/hello", 212 Duration: 3 * time.Second, 213 Attrs: attr, 214 BetterCAT: BetterCAT{ 215 Enabled: true, 216 ID: "txn-id", 217 Priority: 0.5, 218 }, 219 } 220 221 txnEvent.BetterCAT.Inbound = &Payload{ 222 payloadCaller: payloadCaller{ 223 TransportType: "HTTP", 224 Type: "Browser", 225 App: "caller-app", 226 Account: "caller-account", 227 }, 228 ID: "caller-id", 229 TransactionID: "caller-parent-id", 230 TracedID: "trace-id", 231 TransportDuration: 2 * time.Second, 232 } 233 234 txnSlows := newSlowQueries(maxTxnSlowQueries) 235 qParams, err := vetQueryParameters(map[string]interface{}{ 236 strings.Repeat("X", attributeKeyLengthLimit+1): "invalid-key", 237 "invalid-value": struct{}{}, 238 "valid": 123, 239 }) 240 if nil == err { 241 t.Error("expected error") 242 } 243 txnSlows.observeInstance(slowQueryInstance{ 244 Duration: 2 * time.Second, 245 DatastoreMetric: "Datastore/statement/MySQL/users/INSERT", 246 ParameterizedQuery: "INSERT INTO users (name, age) VALUES ($1, $2)", 247 Host: "db-server-1", 248 PortPathOrID: "3306", 249 DatabaseName: "production", 250 StackTrace: nil, 251 QueryParameters: qParams, 252 }) 253 harvestSlows := newSlowQueries(maxHarvestSlowSQLs) 254 harvestSlows.Merge(txnSlows, txnEvent) 255 js, err := harvestSlows.Data("agentRunID", time.Now()) 256 expect := CompactJSONString(`[[ 257 [ 258 "WebTransaction/Go/hello", 259 "/zip/zap", 260 3722056893, 261 "INSERT INTO users (name, age) VALUES ($1, $2)", 262 "Datastore/statement/MySQL/users/INSERT", 263 1, 264 2000, 265 2000, 266 2000, 267 { 268 "host":"db-server-1", 269 "port_path_or_id":"3306", 270 "database_name":"production", 271 "query_parameters":{"valid":123}, 272 "parent.type": "Browser", 273 "parent.app": "caller-app", 274 "parent.account": "caller-account", 275 "parent.transportType": "HTTP", 276 "parent.transportDuration": 2, 277 "guid":"txn-id", 278 "traceId":"trace-id", 279 "priority":0.500000, 280 "sampled":false 281 } 282 ] 283 ]]`) 284 if nil != err { 285 t.Error(err) 286 } 287 if string(js) != expect { 288 t.Error(string(js), expect) 289 } 290 }