github.com/kiali/kiali@v1.84.0/graph/telemetry/istio/appender/aggregate_node_test.go (about) 1 package appender 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/prometheus/common/model" 8 "github.com/stretchr/testify/assert" 9 10 "github.com/kiali/kiali/config" 11 "github.com/kiali/kiali/graph" 12 ) 13 14 func TestNamespacesGraphWithServiceInjection(t *testing.T) { 15 assert := assert.New(t) 16 17 q0 := `round(sum(rate(istio_requests_total{reporter="destination",source_workload_namespace!="bookinfo",destination_service_namespace="bookinfo",request_operation!="unknown"}[60s])) by (source_cluster,source_workload_namespace,source_workload,source_canonical_service,source_canonical_revision,destination_cluster,destination_service_namespace,destination_service,destination_service_name,destination_workload_namespace,destination_workload,destination_canonical_service,destination_canonical_revision,request_protocol,response_code,grpc_response_status,response_flags,request_operation) > 0,0.001)` 18 v0 := model.Vector{} 19 20 q1 := `round(sum(rate(istio_requests_total{reporter="destination",source_workload_namespace="bookinfo",request_operation!="unknown"}[60s])) by (source_cluster,source_workload_namespace,source_workload,source_canonical_service,source_canonical_revision,destination_cluster,destination_service_namespace,destination_service,destination_service_name,destination_workload_namespace,destination_workload,destination_canonical_service,destination_canonical_revision,request_protocol,response_code,grpc_response_status,response_flags,request_operation) > 0,0.001)` 21 q1m0 := model.Metric{ 22 "source_cluster": config.DefaultClusterID, 23 "source_workload_namespace": "bookinfo", 24 "source_workload": "productpage-v1", 25 "source_canonical_service": "productpage", 26 "source_canonical_revision": "v1", 27 "destination_cluster": config.DefaultClusterID, 28 "destination_service_namespace": "bookinfo", 29 "destination_service": "reviews.bookinfo.svc.cluster.local", 30 "destination_service_name": "reviews", 31 "destination_workload_namespace": "bookinfo", 32 "destination_workload": "reviews-v1", 33 "destination_canonical_service": "reviews", 34 "destination_canonical_revision": "v1", 35 "response_code": "200", 36 "response_flags": "", 37 "request_protocol": "http", 38 "request_operation": "Top"} 39 q1m1 := model.Metric{ 40 "source_cluster": config.DefaultClusterID, 41 "source_workload_namespace": "bookinfo", 42 "source_workload": "productpage-v1", 43 "source_canonical_service": "productpage", 44 "source_canonical_revision": "v1", 45 "destination_cluster": config.DefaultClusterID, 46 "destination_service_namespace": "bookinfo", 47 "destination_service": "reviews.bookinfo.svc.cluster.local", 48 "destination_service_name": "reviews", 49 "destination_workload_namespace": "bookinfo", 50 "destination_workload": "reviews-v1", 51 "destination_canonical_service": "reviews", 52 "destination_canonical_revision": "v1", 53 "response_code": "200", 54 "response_flags": "", 55 "request_protocol": "http", 56 "request_operation": "All"} 57 v1 := model.Vector{ 58 &model.Sample{ 59 Metric: q1m0, 60 Value: 70}, 61 &model.Sample{ 62 Metric: q1m1, 63 Value: 30}} 64 65 client, api, err := setupMocked() 66 if err != nil { 67 t.Error(err) 68 return 69 } 70 mockQuery(api, q0, &v0) 71 mockQuery(api, q1, &v1) 72 73 trafficMap := aggregateNodeTestTraffic(true) 74 ppID, _, _ := graph.Id(config.DefaultClusterID, "bookinfo", "productpage", "bookinfo", "productpage-v1", "productpage", "v1", graph.GraphTypeVersionedApp) 75 pp, ok := trafficMap[ppID] 76 assert.Equal(true, ok) 77 assert.Equal(1, len(pp.Edges)) 78 assert.Equal(graph.NodeTypeService, pp.Edges[0].Dest.NodeType) 79 80 duration, _ := time.ParseDuration("60s") 81 appender := AggregateNodeAppender{ 82 Aggregate: "request_operation", 83 GraphType: graph.GraphTypeVersionedApp, 84 InjectServiceNodes: true, 85 Namespaces: map[string]graph.NamespaceInfo{ 86 "bookinfo": { 87 Name: "bookinfo", 88 Duration: duration, 89 }, 90 }, 91 QueryTime: time.Now().Unix(), 92 Rates: graph.RequestedRates{ 93 Grpc: graph.RateRequests, 94 Http: graph.RateRequests, 95 Tcp: graph.RateTotal, 96 }, 97 } 98 99 appender.appendGraph(trafficMap, "bookinfo", client) 100 101 pp, ok = trafficMap[ppID] 102 assert.Equal(true, ok) 103 assert.Equal(2, len(pp.Edges)) 104 assert.Equal(graph.NodeTypeAggregate, pp.Edges[0].Dest.NodeType) 105 assert.Equal(graph.NodeTypeAggregate, pp.Edges[1].Dest.NodeType) 106 107 topReviews := pp.Edges[0].Dest 108 if "Top" != topReviews.Metadata[graph.AggregateValue] { 109 topReviews = pp.Edges[1].Dest 110 } 111 assert.Equal("request_operation", topReviews.Metadata[graph.Aggregate]) 112 assert.Equal("Top", topReviews.Metadata[graph.AggregateValue]) 113 assert.Equal("reviews", topReviews.App) 114 assert.Equal("reviews", topReviews.Service) 115 assert.Equal(1, len(topReviews.Edges)) 116 assert.Equal(graph.NodeTypeService, topReviews.Edges[0].Dest.NodeType) 117 118 allReviews := pp.Edges[1].Dest 119 if "All" != allReviews.Metadata[graph.AggregateValue] { 120 allReviews = pp.Edges[0].Dest 121 } 122 assert.Equal("request_operation", allReviews.Metadata[graph.Aggregate]) 123 assert.Equal("All", allReviews.Metadata[graph.AggregateValue]) 124 assert.Equal("reviews", allReviews.App) 125 assert.Equal("reviews", allReviews.Service) 126 assert.Equal(1, len(allReviews.Edges)) 127 assert.Equal(graph.NodeTypeService, allReviews.Edges[0].Dest.NodeType) 128 129 assert.Equal(topReviews.Edges[0].Dest.ID, allReviews.Edges[0].Dest.ID) 130 131 reviewsService := topReviews.Edges[0].Dest 132 assert.Equal(graph.NodeTypeService, reviewsService.NodeType) 133 assert.Equal("reviews", reviewsService.Service) 134 assert.Equal(1, len(reviewsService.Edges)) 135 136 reviews := reviewsService.Edges[0].Dest 137 assert.Equal("reviews", reviews.App) 138 assert.Equal("v1", reviews.Version) 139 } 140 141 func TestNamespacesGraphNoServiceInjection(t *testing.T) { 142 assert := assert.New(t) 143 144 q0 := `round(sum(rate(istio_requests_total{reporter="destination",source_workload_namespace!="bookinfo",destination_service_namespace="bookinfo",request_operation!="unknown"}[60s])) by (source_cluster,source_workload_namespace,source_workload,source_canonical_service,source_canonical_revision,destination_cluster,destination_service_namespace,destination_service,destination_service_name,destination_workload_namespace,destination_workload,destination_canonical_service,destination_canonical_revision,request_protocol,response_code,grpc_response_status,response_flags,request_operation) > 0,0.001)` 145 v0 := model.Vector{} 146 147 q1 := `round(sum(rate(istio_requests_total{reporter="destination",source_workload_namespace="bookinfo",request_operation!="unknown"}[60s])) by (source_cluster,source_workload_namespace,source_workload,source_canonical_service,source_canonical_revision,destination_cluster,destination_service_namespace,destination_service,destination_service_name,destination_workload_namespace,destination_workload,destination_canonical_service,destination_canonical_revision,request_protocol,response_code,grpc_response_status,response_flags,request_operation) > 0,0.001)` 148 q1m0 := model.Metric{ 149 "source_cluster": config.DefaultClusterID, 150 "source_workload_namespace": "bookinfo", 151 "source_workload": "productpage-v1", 152 "source_canonical_service": "productpage", 153 "source_canonical_revision": "v1", 154 "destination_cluster": config.DefaultClusterID, 155 "destination_service_namespace": "bookinfo", 156 "destination_service": "reviews.bookinfo.svc.cluster.local", 157 "destination_service_name": "reviews", 158 "destination_workload_namespace": "bookinfo", 159 "destination_workload": "reviews-v1", 160 "destination_canonical_service": "reviews", 161 "destination_canonical_revision": "v1", 162 "response_code": "200", 163 "response_flags": "", 164 "request_protocol": "http", 165 "request_operation": "Top"} 166 q1m1 := model.Metric{ 167 "source_cluster": config.DefaultClusterID, 168 "source_workload_namespace": "bookinfo", 169 "source_workload": "productpage-v1", 170 "source_canonical_service": "productpage", 171 "source_canonical_revision": "v1", 172 "destination_cluster": config.DefaultClusterID, 173 "destination_service_namespace": "bookinfo", 174 "destination_service": "reviews.bookinfo.svc.cluster.local", 175 "destination_service_name": "reviews", 176 "destination_workload_namespace": "bookinfo", 177 "destination_workload": "reviews-v1", 178 "destination_canonical_service": "reviews", 179 "destination_canonical_revision": "v1", 180 "response_code": "200", 181 "response_flags": "", 182 "request_protocol": "http", 183 "request_operation": "All"} 184 v1 := model.Vector{ 185 &model.Sample{ 186 Metric: q1m0, 187 Value: 70}, 188 &model.Sample{ 189 Metric: q1m1, 190 Value: 30}} 191 192 client, api, err := setupMocked() 193 if err != nil { 194 t.Error(err) 195 return 196 } 197 mockQuery(api, q0, &v0) 198 mockQuery(api, q1, &v1) 199 200 trafficMap := aggregateNodeTestTraffic(false) 201 ppID, _, _ := graph.Id(config.DefaultClusterID, "bookinfo", "productpage", "bookinfo", "productpage-v1", "productpage", "v1", graph.GraphTypeVersionedApp) 202 pp, ok := trafficMap[ppID] 203 assert.Equal(true, ok) 204 assert.Equal(1, len(pp.Edges)) 205 assert.Equal(graph.NodeTypeApp, pp.Edges[0].Dest.NodeType) 206 207 duration, _ := time.ParseDuration("60s") 208 appender := AggregateNodeAppender{ 209 Aggregate: "request_operation", 210 GraphType: graph.GraphTypeVersionedApp, 211 InjectServiceNodes: false, 212 Namespaces: map[string]graph.NamespaceInfo{ 213 "bookinfo": { 214 Name: "bookinfo", 215 Duration: duration, 216 }, 217 }, 218 QueryTime: time.Now().Unix(), 219 Rates: graph.RequestedRates{ 220 Grpc: graph.RateRequests, 221 Http: graph.RateRequests, 222 Tcp: graph.RateTotal, 223 }} 224 225 appender.appendGraph(trafficMap, "bookinfo", client) 226 227 pp, ok = trafficMap[ppID] 228 assert.Equal(true, ok) 229 assert.Equal(2, len(pp.Edges)) 230 assert.Equal(graph.NodeTypeAggregate, pp.Edges[0].Dest.NodeType) 231 assert.Equal(graph.NodeTypeAggregate, pp.Edges[1].Dest.NodeType) 232 233 topReviews := pp.Edges[0].Dest 234 if "Top" != topReviews.Metadata[graph.AggregateValue] { 235 topReviews = pp.Edges[1].Dest 236 } 237 assert.Equal("request_operation", topReviews.Metadata[graph.Aggregate]) 238 assert.Equal("Top", topReviews.Metadata[graph.AggregateValue]) 239 assert.Equal("", topReviews.App) 240 assert.Equal(1, len(topReviews.Edges)) 241 assert.Equal(graph.NodeTypeApp, topReviews.Edges[0].Dest.NodeType) 242 243 allReviews := pp.Edges[1].Dest 244 if "All" != allReviews.Metadata[graph.AggregateValue] { 245 allReviews = pp.Edges[0].Dest 246 } 247 assert.Equal("request_operation", allReviews.Metadata[graph.Aggregate]) 248 assert.Equal("All", allReviews.Metadata[graph.AggregateValue]) 249 assert.Equal("", allReviews.App) 250 assert.Equal(1, len(allReviews.Edges)) 251 assert.Equal(graph.NodeTypeApp, allReviews.Edges[0].Dest.NodeType) 252 253 assert.Equal(topReviews.Edges[0].Dest.ID, allReviews.Edges[0].Dest.ID) 254 255 reviews := topReviews.Edges[0].Dest 256 assert.Equal(graph.NodeTypeApp, reviews.NodeType) 257 assert.Equal("reviews", reviews.App) 258 assert.Equal(0, len(reviews.Edges)) 259 } 260 261 func TestNodeGraphWithServiceInjection(t *testing.T) { 262 assert := assert.New(t) 263 264 q0 := `round(sum(rate(istio_requests_total{reporter="destination",destination_service_namespace="bookinfo",request_operation="Top",destination_service_name="reviews"}[60s])) by (source_cluster,source_workload_namespace,source_workload,source_canonical_service,source_canonical_revision,destination_cluster,destination_service_namespace,destination_service,destination_service_name,destination_workload_namespace,destination_workload,destination_canonical_service,destination_canonical_revision,request_protocol,response_code,grpc_response_status,response_flags,request_operation) > 0,0.001)` 265 q0m0 := model.Metric{ 266 "source_cluster": config.DefaultClusterID, 267 "source_workload_namespace": "bookinfo", 268 "source_workload": "productpage-v1", 269 "source_canonical_service": "productpage", 270 "source_canonical_revision": "v1", 271 "destination_cluster": config.DefaultClusterID, 272 "destination_service_namespace": "bookinfo", 273 "destination_service": "reviews.bookinfo.svc.cluster.local", 274 "destination_service_name": "reviews", 275 "destination_workload_namespace": "bookinfo", 276 "destination_workload": "reviews-v1", 277 "destination_canonical_service": "reviews", 278 "destination_canonical_revision": "v1", 279 "response_code": "200", 280 "response_flags": "", 281 "request_protocol": "http", 282 "request_operation": "Top"} 283 v0 := model.Vector{ 284 &model.Sample{ 285 Metric: q0m0, 286 Value: 70}} 287 288 client, api, err := setupMocked() 289 if err != nil { 290 t.Error(err) 291 return 292 } 293 mockQuery(api, q0, &v0) 294 295 trafficMap := aggregateNodeTestTraffic(true) 296 ppID, _, _ := graph.Id(config.DefaultClusterID, "bookinfo", "productpage", "bookinfo", "productpage-v1", "productpage", "v1", graph.GraphTypeVersionedApp) 297 pp, ok := trafficMap[ppID] 298 assert.Equal(true, ok) 299 assert.Equal(1, len(pp.Edges)) 300 assert.Equal(graph.NodeTypeService, pp.Edges[0].Dest.NodeType) 301 302 duration, _ := time.ParseDuration("60s") 303 appender := AggregateNodeAppender{ 304 Aggregate: "request_operation", 305 AggregateValue: "Top", 306 GraphType: graph.GraphTypeVersionedApp, 307 InjectServiceNodes: true, 308 Namespaces: map[string]graph.NamespaceInfo{ 309 "bookinfo": { 310 Name: "bookinfo", 311 Duration: duration, 312 }, 313 }, 314 QueryTime: time.Now().Unix(), 315 Rates: graph.RequestedRates{ 316 Grpc: graph.RateRequests, 317 Http: graph.RateRequests, 318 Tcp: graph.RateTotal, 319 }, 320 Service: "reviews", 321 } 322 323 appender.appendNodeGraph(trafficMap, "bookinfo", client) 324 325 pp, ok = trafficMap[ppID] 326 assert.Equal(true, ok) 327 assert.Equal(1, len(pp.Edges)) 328 assert.Equal(graph.NodeTypeAggregate, pp.Edges[0].Dest.NodeType) 329 330 topReviews := pp.Edges[0].Dest 331 assert.Equal("Top", topReviews.Metadata[graph.AggregateValue]) 332 assert.Equal("request_operation", topReviews.Metadata[graph.Aggregate]) 333 assert.Equal("Top", topReviews.Metadata[graph.AggregateValue]) 334 assert.Equal("reviews", topReviews.App) 335 assert.Equal(1, len(topReviews.Edges)) 336 assert.Equal(graph.NodeTypeService, topReviews.Edges[0].Dest.NodeType) 337 338 reviewsService := topReviews.Edges[0].Dest 339 assert.Equal(graph.NodeTypeService, reviewsService.NodeType) 340 assert.Equal("reviews", reviewsService.Service) 341 assert.Equal(1, len(reviewsService.Edges)) 342 343 reviews := reviewsService.Edges[0].Dest 344 assert.Equal("reviews", reviews.App) 345 assert.Equal("v1", reviews.Version) 346 } 347 348 func TestNamespacesGraphWithServiceInjectionSkipRates(t *testing.T) { 349 assert := assert.New(t) 350 351 q0 := `round(sum(rate(istio_requests_total{reporter="destination",source_workload_namespace!="bookinfo",destination_service_namespace="bookinfo",request_operation!="unknown"}[60s])) by (source_cluster,source_workload_namespace,source_workload,source_canonical_service,source_canonical_revision,destination_cluster,destination_service_namespace,destination_service,destination_service_name,destination_workload_namespace,destination_workload,destination_canonical_service,destination_canonical_revision,request_protocol,response_code,grpc_response_status,response_flags,request_operation) > 0,0.001)` 352 v0 := model.Vector{} 353 354 q1 := `round(sum(rate(istio_requests_total{reporter="destination",source_workload_namespace="bookinfo",request_operation!="unknown"}[60s])) by (source_cluster,source_workload_namespace,source_workload,source_canonical_service,source_canonical_revision,destination_cluster,destination_service_namespace,destination_service,destination_service_name,destination_workload_namespace,destination_workload,destination_canonical_service,destination_canonical_revision,request_protocol,response_code,grpc_response_status,response_flags,request_operation) > 0,0.001)` 355 q1m0 := model.Metric{ 356 "source_cluster": config.DefaultClusterID, 357 "source_workload_namespace": "bookinfo", 358 "source_workload": "productpage-v1", 359 "source_canonical_service": "productpage", 360 "source_canonical_revision": "v1", 361 "destination_cluster": config.DefaultClusterID, 362 "destination_service_namespace": "bookinfo", 363 "destination_service": "reviews.bookinfo.svc.cluster.local", 364 "destination_service_name": "reviews", 365 "destination_workload_namespace": "bookinfo", 366 "destination_workload": "reviews-v1", 367 "destination_canonical_service": "reviews", 368 "destination_canonical_revision": "v1", 369 "response_code": "200", 370 "response_flags": "", 371 "request_protocol": "http", 372 "request_operation": "Top"} 373 q1m1 := model.Metric{ 374 "source_cluster": config.DefaultClusterID, 375 "source_workload_namespace": "bookinfo", 376 "source_workload": "productpage-v1", 377 "source_canonical_service": "productpage", 378 "source_canonical_revision": "v1", 379 "destination_cluster": config.DefaultClusterID, 380 "destination_service_namespace": "bookinfo", 381 "destination_service": "reviews.bookinfo.svc.cluster.local", 382 "destination_service_name": "reviews", 383 "destination_workload_namespace": "bookinfo", 384 "destination_workload": "reviews-v1", 385 "destination_canonical_service": "reviews", 386 "destination_canonical_revision": "v1", 387 "response_code": "200", 388 "response_flags": "", 389 "request_protocol": "http", 390 "request_operation": "All"} 391 v1 := model.Vector{ 392 &model.Sample{ 393 Metric: q1m0, 394 Value: 70}, 395 &model.Sample{ 396 Metric: q1m1, 397 Value: 30}} 398 399 client, api, err := setupMocked() 400 if err != nil { 401 t.Error(err) 402 return 403 } 404 mockQuery(api, q0, &v0) 405 mockQuery(api, q1, &v1) 406 407 trafficMap := aggregateNodeTestTraffic(true) 408 ppID, _, _ := graph.Id(config.DefaultClusterID, "bookinfo", "productpage", "bookinfo", "productpage-v1", "productpage", "v1", graph.GraphTypeVersionedApp) 409 pp, ok := trafficMap[ppID] 410 assert.Equal(true, ok) 411 assert.Equal(1, len(pp.Edges)) 412 assert.Equal(graph.NodeTypeService, pp.Edges[0].Dest.NodeType) 413 414 duration, _ := time.ParseDuration("60s") 415 appender := AggregateNodeAppender{ 416 Aggregate: "request_operation", 417 GraphType: graph.GraphTypeVersionedApp, 418 InjectServiceNodes: true, 419 Namespaces: map[string]graph.NamespaceInfo{ 420 "bookinfo": { 421 Name: "bookinfo", 422 Duration: duration, 423 }, 424 }, 425 QueryTime: time.Now().Unix(), 426 Rates: graph.RequestedRates{ 427 Grpc: graph.RateRequests, 428 Http: graph.RateNone, 429 Tcp: graph.RateTotal, 430 }, 431 } 432 433 appender.appendGraph(trafficMap, "bookinfo", client) 434 435 pp, ok = trafficMap[ppID] 436 assert.Equal(true, ok) 437 assert.Equal(1, len(pp.Edges)) 438 assert.Equal(graph.NodeTypeService, pp.Edges[0].Dest.NodeType) 439 440 reviewsService := pp.Edges[0].Dest 441 assert.Equal(graph.NodeTypeService, reviewsService.NodeType) 442 assert.Equal("reviews", reviewsService.Service) 443 assert.Equal(1, len(reviewsService.Edges)) 444 445 reviews := reviewsService.Edges[0].Dest 446 assert.Equal("reviews", reviews.App) 447 assert.Equal("v1", reviews.Version) 448 } 449 450 func TestNodeGraphNoServiceInjection(t *testing.T) { 451 assert := assert.New(t) 452 453 q0 := `round(sum(rate(istio_requests_total{reporter="destination",destination_service_namespace="bookinfo",request_operation="Top"}[60s])) by (source_cluster,source_workload_namespace,source_workload,source_canonical_service,source_canonical_revision,destination_cluster,destination_service_namespace,destination_service,destination_service_name,destination_workload_namespace,destination_workload,destination_canonical_service,destination_canonical_revision,request_protocol,response_code,grpc_response_status,response_flags,request_operation) > 0,0.001)` 454 q0m0 := model.Metric{ 455 "source_cluster": config.DefaultClusterID, 456 "source_workload_namespace": "bookinfo", 457 "source_workload": "productpage-v1", 458 "source_canonical_service": "productpage", 459 "source_canonical_revision": "v1", 460 "destination_cluster": config.DefaultClusterID, 461 "destination_service_namespace": "bookinfo", 462 "destination_service": "reviews.bookinfo.svc.cluster.local", 463 "destination_service_name": "reviews", 464 "destination_workload_namespace": "bookinfo", 465 "destination_workload": "reviews-v1", 466 "destination_canonical_service": "reviews", 467 "destination_canonical_revision": "v1", 468 "response_code": "200", 469 "response_flags": "", 470 "request_protocol": "http", 471 "request_operation": "Top"} 472 v0 := model.Vector{ 473 &model.Sample{ 474 Metric: q0m0, 475 Value: 70}} 476 477 client, api, err := setupMocked() 478 if err != nil { 479 t.Error(err) 480 return 481 } 482 mockQuery(api, q0, &v0) 483 484 trafficMap := aggregateNodeTestTraffic(false) 485 ppID, _, _ := graph.Id(config.DefaultClusterID, "bookinfo", "productpage", "bookinfo", "productpage-v1", "productpage", "v1", graph.GraphTypeVersionedApp) 486 pp, ok := trafficMap[ppID] 487 assert.Equal(true, ok) 488 assert.Equal(1, len(pp.Edges)) 489 assert.Equal(graph.NodeTypeApp, pp.Edges[0].Dest.NodeType) 490 491 duration, _ := time.ParseDuration("60s") 492 appender := AggregateNodeAppender{ 493 Aggregate: "request_operation", 494 AggregateValue: "Top", 495 GraphType: graph.GraphTypeVersionedApp, 496 InjectServiceNodes: false, 497 Namespaces: map[string]graph.NamespaceInfo{ 498 "bookinfo": { 499 Name: "bookinfo", 500 Duration: duration, 501 }, 502 }, 503 QueryTime: time.Now().Unix(), 504 Rates: graph.RequestedRates{ 505 Grpc: graph.RateRequests, 506 Http: graph.RateRequests, 507 Tcp: graph.RateTotal, 508 }, 509 } 510 511 appender.appendNodeGraph(trafficMap, "bookinfo", client) 512 513 pp, ok = trafficMap[ppID] 514 assert.Equal(true, ok) 515 assert.Equal(1, len(pp.Edges)) 516 assert.Equal(graph.NodeTypeAggregate, pp.Edges[0].Dest.NodeType) 517 518 topReviews := pp.Edges[0].Dest 519 assert.Equal("Top", topReviews.Metadata[graph.AggregateValue]) 520 assert.Equal("request_operation", topReviews.Metadata[graph.Aggregate]) 521 assert.Equal("Top", topReviews.Metadata[graph.AggregateValue]) 522 assert.Equal("", topReviews.App) 523 assert.Equal(1, len(topReviews.Edges)) 524 assert.Equal(graph.NodeTypeApp, topReviews.Edges[0].Dest.NodeType) 525 526 reviews := topReviews.Edges[0].Dest 527 assert.Equal("reviews", reviews.App) 528 assert.Equal("v1", reviews.Version) 529 } 530 531 func TestNodeGraphWithServiceInjectionSkipRates(t *testing.T) { 532 assert := assert.New(t) 533 534 q0 := `round(sum(rate(istio_requests_total{reporter="destination",destination_service_namespace="bookinfo",request_operation="Top",destination_service_name="reviews"}[60s])) by (source_cluster,source_workload_namespace,source_workload,source_canonical_service,source_canonical_revision,destination_cluster,destination_service_namespace,destination_service,destination_service_name,destination_workload_namespace,destination_workload,destination_canonical_service,destination_canonical_revision,request_protocol,response_code,grpc_response_status,response_flags,request_operation) > 0,0.001)` 535 q0m0 := model.Metric{ 536 "source_cluster": config.DefaultClusterID, 537 "source_workload_namespace": "bookinfo", 538 "source_workload": "productpage-v1", 539 "source_canonical_service": "productpage", 540 "source_canonical_revision": "v1", 541 "destination_cluster": config.DefaultClusterID, 542 "destination_service_namespace": "bookinfo", 543 "destination_service": "reviews.bookinfo.svc.cluster.local", 544 "destination_service_name": "reviews", 545 "destination_workload_namespace": "bookinfo", 546 "destination_workload": "reviews-v1", 547 "destination_canonical_service": "reviews", 548 "destination_canonical_revision": "v1", 549 "response_code": "200", 550 "response_flags": "", 551 "request_protocol": "http", 552 "request_operation": "Top"} 553 v0 := model.Vector{ 554 &model.Sample{ 555 Metric: q0m0, 556 Value: 70}} 557 558 client, api, err := setupMocked() 559 if err != nil { 560 t.Error(err) 561 return 562 } 563 mockQuery(api, q0, &v0) 564 565 trafficMap := aggregateNodeTestTraffic(true) 566 ppID, _, _ := graph.Id(config.DefaultClusterID, "bookinfo", "productpage", "bookinfo", "productpage-v1", "productpage", "v1", graph.GraphTypeVersionedApp) 567 pp, ok := trafficMap[ppID] 568 assert.Equal(true, ok) 569 assert.Equal(1, len(pp.Edges)) 570 assert.Equal(graph.NodeTypeService, pp.Edges[0].Dest.NodeType) 571 572 duration, _ := time.ParseDuration("60s") 573 appender := AggregateNodeAppender{ 574 Aggregate: "request_operation", 575 AggregateValue: "Top", 576 GraphType: graph.GraphTypeVersionedApp, 577 InjectServiceNodes: true, 578 Namespaces: map[string]graph.NamespaceInfo{ 579 "bookinfo": { 580 Name: "bookinfo", 581 Duration: duration, 582 }, 583 }, 584 QueryTime: time.Now().Unix(), 585 Rates: graph.RequestedRates{ 586 Grpc: graph.RateRequests, 587 Http: graph.RateNone, 588 Tcp: graph.RateTotal, 589 }, 590 Service: "reviews", 591 } 592 593 appender.appendNodeGraph(trafficMap, "bookinfo", client) 594 595 pp, ok = trafficMap[ppID] 596 assert.Equal(true, ok) 597 assert.Equal(1, len(pp.Edges)) 598 assert.Equal(graph.NodeTypeService, pp.Edges[0].Dest.NodeType) 599 600 reviewsService := pp.Edges[0].Dest 601 assert.Equal(graph.NodeTypeService, reviewsService.NodeType) 602 assert.Equal("reviews", reviewsService.Service) 603 assert.Equal(1, len(reviewsService.Edges)) 604 605 reviews := reviewsService.Edges[0].Dest 606 assert.Equal("reviews", reviews.App) 607 assert.Equal("v1", reviews.Version) 608 } 609 610 func aggregateNodeTestTraffic(injectServices bool) graph.TrafficMap { 611 productpage, _ := graph.NewNode(config.DefaultClusterID, "bookinfo", "productpage", "bookinfo", "productpage-v1", "productpage", "v1", graph.GraphTypeVersionedApp) 612 reviews, _ := graph.NewNode(config.DefaultClusterID, "bookinfo", "reviews", "bookinfo", "reviews-v1", "reviews", "v1", graph.GraphTypeVersionedApp) 613 reviewsService, _ := graph.NewNode(config.DefaultClusterID, "bookinfo", "reviews", "", "", "", "", graph.GraphTypeVersionedApp) 614 615 trafficMap := graph.NewTrafficMap() 616 trafficMap[productpage.ID] = productpage 617 trafficMap[reviews.ID] = reviews 618 if injectServices { 619 trafficMap[reviewsService.ID] = reviewsService 620 productpage.AddEdge(reviewsService) 621 reviewsService.AddEdge(reviews) 622 } else { 623 productpage.AddEdge(reviews) 624 } 625 626 return trafficMap 627 }