datasource.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. package collector
  2. import (
  3. "context"
  4. "time"
  5. "github.com/julienschmidt/httprouter"
  6. "github.com/opencost/opencost/core/pkg/clustercache"
  7. "github.com/opencost/opencost/core/pkg/clusters"
  8. "github.com/opencost/opencost/core/pkg/diagnostics"
  9. "github.com/opencost/opencost/core/pkg/external"
  10. "github.com/opencost/opencost/core/pkg/log"
  11. "github.com/opencost/opencost/core/pkg/nodestats"
  12. "github.com/opencost/opencost/core/pkg/source"
  13. "github.com/opencost/opencost/core/pkg/storage"
  14. "github.com/opencost/opencost/modules/collector-source/pkg/metric"
  15. "github.com/opencost/opencost/modules/collector-source/pkg/metric/synthetic"
  16. "github.com/opencost/opencost/modules/collector-source/pkg/scrape"
  17. "github.com/opencost/opencost/modules/collector-source/pkg/util"
  18. )
  19. type collectorDataSource struct {
  20. metricsQuerier *collectorMetricsQuerier
  21. clusterMap clusters.ClusterMap
  22. clusterInfo clusters.ClusterInfoProvider
  23. config CollectorConfig
  24. diagnosticsModule *metric.DiagnosticsModule
  25. }
  26. func NewDefaultCollectorDataSource(
  27. clusterUID string,
  28. store storage.Storage,
  29. clusterInfoProvider clusters.ClusterInfoProvider,
  30. clusterCache clustercache.ClusterCache,
  31. statSummaryClient nodestats.StatSummaryClient,
  32. externalLabelProvider external.LabelProvider,
  33. ) source.OpenCostDataSource {
  34. config := NewOpenCostCollectorConfigFromEnv(clusterUID)
  35. return NewCollectorDataSource(
  36. config,
  37. store,
  38. clusterInfoProvider,
  39. clusterCache,
  40. statSummaryClient,
  41. externalLabelProvider,
  42. )
  43. }
  44. func NewCollectorDataSource(
  45. config CollectorConfig,
  46. store storage.Storage,
  47. clusterInfoProvider clusters.ClusterInfoProvider,
  48. clusterCache clustercache.ClusterCache,
  49. statSummaryClient nodestats.StatSummaryClient,
  50. externalLabelProvider external.LabelProvider,
  51. ) source.OpenCostDataSource {
  52. var resolutions []*util.Resolution
  53. for _, resconf := range config.Resolutions {
  54. resolution, err := util.NewResolution(resconf)
  55. if err != nil {
  56. log.Errorf("failed to create resolution %s", err.Error())
  57. continue
  58. }
  59. resolutions = append(resolutions, resolution)
  60. }
  61. repo := metric.NewMetricRepository(
  62. resolutions,
  63. NewOpenCostMetricStore,
  64. )
  65. var updater metric.Updater
  66. updater = repo
  67. if store != nil {
  68. wal, err := metric.NewWalinator(
  69. config.ClusterName,
  70. config.ApplicationName,
  71. store,
  72. resolutions,
  73. updater,
  74. )
  75. if err != nil {
  76. log.Errorf("failed to initialize the walinator: %s", err.Error())
  77. } else {
  78. wal.Start()
  79. updater = wal
  80. }
  81. }
  82. // synthesizer collects specific metric types and generates new metrics to pass
  83. // along with the original metrics into the updater
  84. metricSynthesizer := synthetic.NewMetricSynthesizers(
  85. updater,
  86. synthetic.NewContainerMemoryAllocationSynthesizer(),
  87. synthetic.NewContainerCpuAllocationSynthesizer(),
  88. )
  89. updater = metricSynthesizer
  90. diagnosticsModule := metric.NewDiagnosticsModule()
  91. scrapeController := scrape.NewScrapeController(
  92. config.ClusterUID,
  93. config.ScrapeInterval,
  94. config.NetworkPort,
  95. updater,
  96. clusterInfoProvider,
  97. clusterCache,
  98. statSummaryClient,
  99. externalLabelProvider,
  100. )
  101. scrapeController.Start()
  102. metricQuerier := newCollectorMetricsQuerier(repo, config.Resolutions)
  103. // cluster info provider
  104. clusterInfo := clusterInfoProvider
  105. clusterMap := newCollectorClusterMap(clusterInfo)
  106. return &collectorDataSource{
  107. config: config,
  108. metricsQuerier: metricQuerier,
  109. clusterInfo: clusterInfo,
  110. clusterMap: clusterMap,
  111. diagnosticsModule: diagnosticsModule,
  112. }
  113. }
  114. func (c *collectorDataSource) RegisterEndPoints(router *httprouter.Router) {
  115. }
  116. func (c *collectorDataSource) RegisterDiagnostics(diagService diagnostics.DiagnosticService) {
  117. const CollectorDiagnosticCategory = "collector"
  118. diagnosticDefinitions := c.diagnosticsModule.DiagnosticsDefinitions()
  119. for _, dd := range diagnosticDefinitions {
  120. err := diagService.Register(dd.MetricName, dd.Description, CollectorDiagnosticCategory, func(ctx context.Context) (map[string]any, error) {
  121. details, err := c.diagnosticsModule.DiagnosticsDetails(dd.ID)
  122. if err != nil {
  123. return nil, err
  124. }
  125. return details, nil
  126. })
  127. if err != nil {
  128. log.Warnf("Failed to register collector diagnostic %s: %s", dd.ID, err.Error())
  129. }
  130. }
  131. }
  132. func (c *collectorDataSource) Metrics() source.MetricsQuerier {
  133. return c.metricsQuerier
  134. }
  135. func (c *collectorDataSource) ClusterMap() clusters.ClusterMap {
  136. return c.clusterMap
  137. }
  138. func (c *collectorDataSource) ClusterInfo() clusters.ClusterInfoProvider {
  139. return c.clusterInfo
  140. }
  141. // BatchDuration collector data source queries do not need to be broken up
  142. func (c *collectorDataSource) BatchDuration() time.Duration {
  143. var maxDuration time.Duration = 1<<63 - 1
  144. return maxDuration
  145. }
  146. func (c *collectorDataSource) Resolution() time.Duration {
  147. interval, _ := util.NewInterval(c.config.ScrapeInterval)
  148. current := interval.Truncate(time.Now().UTC())
  149. next := interval.Add(current, 1)
  150. return next.Sub(current)
  151. }