2
0

networkinsight.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package costmodel
  2. import (
  3. "fmt"
  4. "time"
  5. coreenv "github.com/opencost/opencost/core/pkg/env"
  6. "github.com/opencost/opencost/core/pkg/log"
  7. "github.com/opencost/opencost/core/pkg/opencost"
  8. "github.com/opencost/opencost/core/pkg/source"
  9. )
  10. func (cm *CostModel) ComputeNetworkInsights(start, end time.Time) (*opencost.NetworkInsightSet, error) {
  11. log.Debugf("Network Insight compute called on CostModel for window %s", opencost.NewClosedWindow(start, end).String())
  12. // If the duration is short enough, compute the network insight directly
  13. if end.Sub(start) <= cm.BatchDuration {
  14. return cm.GetNetworkInsightSet(start, end)
  15. }
  16. // Incase prometheus max query duration is less than the resolution
  17. // s and e track the coverage of the entire given window over multiple
  18. // internal queries.
  19. s, e := start, start
  20. window := opencost.NewClosedWindow(start, end)
  21. totalNis := opencost.NewNetworkInsightSet(start, end)
  22. for e.Before(end) {
  23. duration := end.Sub(e)
  24. if duration > cm.BatchDuration {
  25. duration = cm.BatchDuration
  26. }
  27. e = s.Add(duration)
  28. nis, err := cm.GetNetworkInsightSet(start, end)
  29. if err != nil {
  30. return &opencost.NetworkInsightSet{}, fmt.Errorf("error computing network insight for %s: %v", window.String(), err)
  31. }
  32. totalNis.Accumulate(nis, []opencost.NetworkInsightProperty{})
  33. s = e
  34. }
  35. return totalNis, fmt.Errorf("unable to query data source for large duration")
  36. }
  37. func (cm *CostModel) GetNetworkInsightSet(start, end time.Time) (*opencost.NetworkInsightSet, error) {
  38. resultingSet := &opencost.NetworkInsightSet{}
  39. resultingSet.Window = opencost.NewClosedWindow(start, end)
  40. querier := cm.DataSource.Metrics()
  41. grp := source.NewQueryGroup()
  42. // Egress Cross Zone
  43. resChNetZoneGiB := source.WithGroup(grp, querier.QueryNetZoneGiB(start, end))
  44. resNetZoneGiB, _ := resChNetZoneGiB.Await()
  45. resChNetZoneCostPerGiB := source.WithGroup(grp, querier.QueryNetZonePricePerGiB(start, end))
  46. resNetZoneCostPerGiB, _ := resChNetZoneCostPerGiB.Await()
  47. // Egress Cross Region
  48. resChNetRegionGiB := source.WithGroup(grp, querier.QueryNetRegionGiB(start, end))
  49. resNetRegionGiB, _ := resChNetRegionGiB.Await()
  50. resChNetRegionCostPerGiB := source.WithGroup(grp, querier.QueryNetRegionPricePerGiB(start, end))
  51. resNetRegionCostPerGiB, _ := resChNetRegionCostPerGiB.Await()
  52. // Egress Internet
  53. resChNetInternetGiB := source.WithGroup(grp, querier.QueryNetInternetServiceGiB(start, end))
  54. resNetInternetGiB, _ := resChNetInternetGiB.Await()
  55. resChNetInternetCostPerGiB := source.WithGroup(grp, querier.QueryNetInternetPricePerGiB(start, end))
  56. resNetInternetCostPerGiB, _ := resChNetInternetCostPerGiB.Await()
  57. // Ingress Cross Zone
  58. resChIngNetZoneGiB := source.WithGroup(grp, querier.QueryNetZoneIngressGiB(start, end))
  59. resIngNetZoneGiB, _ := resChIngNetZoneGiB.Await()
  60. // There's no prometheus cost at the moment for Ingress
  61. resIngNetZoneCostPerGiB := []*source.NetworkPricePerGiBResult{}
  62. // Ingress Cross Region
  63. resChIngNetRegionGiB := source.WithGroup(grp, querier.QueryNetRegionIngressGiB(start, end))
  64. resIngNetRegionGiB, _ := resChIngNetRegionGiB.Await()
  65. // There's no prometheus cost at the moment for Ingress
  66. resIngNetRegionCostPerGiB := []*source.NetworkPricePerGiBResult{}
  67. // Ingress Internet
  68. resChIngNetInternetGiB := source.WithGroup(grp, querier.QueryNetInternetServiceIngressGiB(start, end))
  69. resIngNetInternetGiB, _ := resChIngNetInternetGiB.Await()
  70. // There's no prometheus cost at the moment for Ingress
  71. resIngNetInternetCostPerGiB := []*source.NetworkPricePerGiBResult{}
  72. // apply Egress cross zone network details
  73. applyNetworkCosts(resultingSet, resNetZoneGiB, resNetZoneCostPerGiB, opencost.NetworkTrafficTypeCrossZone, opencost.NetworkTrafficDirectionEgress)
  74. // apply Egress cross region network details
  75. applyNetworkCosts(resultingSet, resNetRegionGiB, resNetRegionCostPerGiB, opencost.NetworkTrafficTypeCrossRegion, opencost.NetworkTrafficDirectionEgress)
  76. // apply Egress internet network details
  77. applyNetworkCosts(resultingSet, resNetInternetGiB, resNetInternetCostPerGiB, opencost.NetworkTrafficTypeInternet, opencost.NetworkTrafficDirectionEgress)
  78. // apply Ingress cross zone network details
  79. applyNetworkCosts(resultingSet, resIngNetZoneGiB, resIngNetZoneCostPerGiB, opencost.NetworkTrafficTypeCrossZone, opencost.NetworkTrafficDirectionIngress)
  80. // apply Ingress cross region network details
  81. applyNetworkCosts(resultingSet, resIngNetRegionGiB, resIngNetRegionCostPerGiB, opencost.NetworkTrafficTypeCrossRegion, opencost.NetworkTrafficDirectionIngress)
  82. // apply Ingress internet network details
  83. applyNetworkCosts(resultingSet, resIngNetInternetGiB, resIngNetInternetCostPerGiB, opencost.NetworkTrafficTypeInternet, opencost.NetworkTrafficDirectionIngress)
  84. return resultingSet, nil
  85. }
  86. func applyNetworkCosts(
  87. ns *opencost.NetworkInsightSet,
  88. resNetworkGiB []*source.NetworkGiBResult,
  89. resNetworkCostPerGiB []*source.NetworkPricePerGiBResult,
  90. networkType opencost.NetworkTrafficType,
  91. trafficType opencost.NetworkTrafficDirection,
  92. ) error {
  93. var cost float64
  94. // All ingress cost are comming out empty at the moment?
  95. // do we charge at all here?
  96. if len(resNetworkCostPerGiB) == 0 {
  97. cost = 0
  98. } else {
  99. cost = resNetworkCostPerGiB[0].Data[0].Value
  100. }
  101. for _, res := range resNetworkGiB {
  102. bytes := res.Data[0].Value
  103. // dont really care about bytes <=0
  104. if bytes <= 0 {
  105. continue
  106. }
  107. cluster := res.Cluster
  108. if cluster == "" {
  109. cluster = coreenv.GetClusterID()
  110. }
  111. namespace := res.Namespace
  112. pod := res.Pod
  113. service := res.Service
  114. if service == "" {
  115. service = opencost.NetworkInsightsServiceUnknown
  116. }
  117. totalByteCost := bytes * cost
  118. // sameZone, sameRegion, internet := getNetworkBools(networkType)
  119. nds := make(opencost.NetworkDetailsSet, 1)
  120. nd := &opencost.NetworkDetail{
  121. Cost: totalByteCost,
  122. Bytes: bytes,
  123. EndPoint: service,
  124. TrafficType: networkType,
  125. TrafficDirection: trafficType,
  126. }
  127. nds.Add(nd)
  128. crossZoneCost, crossRegionCost, internetCost, totalCost := getNetworkCost(networkType, totalByteCost)
  129. ni := &opencost.NetworkInsight{
  130. Cluster: cluster,
  131. Namespace: namespace,
  132. Controller: "",
  133. Pod: pod,
  134. Node: "",
  135. Labels: make(map[string]string),
  136. Region: "",
  137. Zone: "",
  138. NetworkTotalCost: totalCost,
  139. NetworkCrossZoneCost: crossZoneCost,
  140. NetworkCrossRegionCost: crossRegionCost,
  141. NetworkInternetCost: internetCost,
  142. NetworkDetails: nds,
  143. }
  144. ns.Insert(ni, []opencost.NetworkInsightProperty{})
  145. }
  146. return nil
  147. }
  148. func getNetworkCost(networkType opencost.NetworkTrafficType, cost float64) (crossZoneCost, crossRegionCost, internetCost, totalCost float64) {
  149. switch networkType {
  150. case opencost.NetworkTrafficTypeCrossZone:
  151. return cost, 0.0, 0.0, cost
  152. case opencost.NetworkTrafficTypeCrossRegion:
  153. return 0.0, cost, 0.0, cost
  154. case opencost.NetworkTrafficTypeInternet:
  155. return 0.0, 0.0, cost, cost
  156. default:
  157. log.Warnf("unknown string passed: %s", networkType)
  158. return 0.0, 0.0, 0.0, 0.0
  159. }
  160. }