source.go 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package exporter
  2. import (
  3. "time"
  4. "github.com/google/uuid"
  5. "github.com/opencost/opencost/core/pkg/clusters"
  6. "github.com/opencost/opencost/core/pkg/heartbeat"
  7. )
  8. // HeartbeatMetadataProvider is an interface that provides metadata for heartbeat instances. It can be used to inject
  9. // custom metadata into a generic `Heartbeat` payload.
  10. type HeartbeatMetadataProvider interface {
  11. // GetMetadata returns the metadata for new heartbeat instances.
  12. GetMetadata() map[string]any
  13. }
  14. // ClusterInfoMetadataProvider is a `HeartbeatMetadataProvider` implementation that provides metadata about the cluster
  15. // leveraging a `ClusterInfoProvider` implementation.
  16. type ClusterInfoMetadataProvider struct {
  17. clusterInfoProvider clusters.ClusterInfoProvider
  18. }
  19. // NewClusterInfoMetadataProvider creates a new `ClusterInfoMetadataProvider` instance. The `provider` parameter is used to
  20. // inject custom metadata, but can be set to `nil` if no metadata is needed.
  21. func NewClusterInfoMetadataProvider(provider clusters.ClusterInfoProvider) *ClusterInfoMetadataProvider {
  22. return &ClusterInfoMetadataProvider{
  23. clusterInfoProvider: provider,
  24. }
  25. }
  26. // GetMetadata returns the metadata for new heartbeat instances. It uses the `ClusterInfoProvider` to get the cluster
  27. // information and injects it into the metadata map.
  28. func (c *ClusterInfoMetadataProvider) GetMetadata() map[string]any {
  29. m := c.clusterInfoProvider.GetClusterInfo()
  30. metadata := make(map[string]any, len(m))
  31. for k, v := range m {
  32. metadata[k] = v
  33. }
  34. return metadata
  35. }
  36. // HeartbeatSource is an `export.ExportSource` implementation that provides the basic data for a `Heartbeat` payload, and
  37. // leverages a `HeartbeatMetadataProvider` to inject custom metadata.
  38. type HeartbeatSource struct {
  39. startTime time.Time
  40. applicationName string
  41. version string
  42. metadataProvider HeartbeatMetadataProvider
  43. }
  44. // NewHeartbeatSource creates a new `HeartbeatSource` instance. The `provider` parameter is used to inject custom metadata,
  45. // but can be set to `nil` if no metadata is needed.
  46. func NewHeartbeatSource(applicationName string, version string, provider HeartbeatMetadataProvider) *HeartbeatSource {
  47. return &HeartbeatSource{
  48. startTime: time.Now().UTC(),
  49. applicationName: applicationName,
  50. version: version,
  51. metadataProvider: provider,
  52. }
  53. }
  54. // Make creates a new `Heartbeat` instance with the provided current time.
  55. func (h *HeartbeatSource) Make(t time.Time) *heartbeat.Heartbeat {
  56. id := uuid.Must(uuid.NewV7()).String()
  57. uptime := uint64(t.Sub(h.startTime).Minutes())
  58. var metadata map[string]any
  59. if h.metadataProvider != nil {
  60. metadata = h.metadataProvider.GetMetadata()
  61. }
  62. return heartbeat.NewHeartbeat(id, t, uptime, h.applicationName, h.version, metadata)
  63. }
  64. func (h *HeartbeatSource) Name() string {
  65. return heartbeat.HeartbeatEventName + "-source"
  66. }