runner.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. package inferencecost
  2. import (
  3. "context"
  4. "time"
  5. "github.com/opencost/opencost/core/pkg/log"
  6. )
  7. // Runner periodically drives the collect → calculate → export pipeline.
  8. type Runner struct {
  9. collector *Collector
  10. calculator *Calculator
  11. exporter *Exporter
  12. interval time.Duration
  13. }
  14. // NewRunner creates a Runner. The exporter must already be registered with
  15. // Prometheus (call exporter.Register() before NewRunner).
  16. func NewRunner(collector *Collector, calculator *Calculator, exporter *Exporter, interval time.Duration) *Runner {
  17. return &Runner{
  18. collector: collector,
  19. calculator: calculator,
  20. exporter: exporter,
  21. interval: interval,
  22. }
  23. }
  24. // Start runs the collection loop until ctx is cancelled.
  25. func (r *Runner) Start(ctx context.Context) {
  26. log.Infof("InferenceCost: starting collection loop (interval=%s)", r.interval)
  27. r.runOnce(ctx)
  28. ticker := time.NewTicker(r.interval)
  29. defer ticker.Stop()
  30. for {
  31. select {
  32. case <-ctx.Done():
  33. log.Infof("InferenceCost: collection loop stopped")
  34. return
  35. case <-ticker.C:
  36. r.runOnce(ctx)
  37. }
  38. }
  39. }
  40. func (r *Runner) runOnce(ctx context.Context) {
  41. end := time.Now()
  42. start := end.Add(-r.interval)
  43. metrics, err := r.collector.CollectMetrics(ctx, start, end)
  44. if err != nil {
  45. log.Errorf("InferenceCost: collection failed: %v", err)
  46. return
  47. }
  48. r.calculator.CalculateCosts(metrics)
  49. r.exporter.Export(metrics)
  50. log.Debugf("InferenceCost: exported metrics for %d models", len(metrics))
  51. }