containers.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package container // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/container"
  4. import (
  5. "go.opentelemetry.io/collector/pdata/pcommon"
  6. conventions "go.opentelemetry.io/collector/semconv/v1.6.1"
  7. "go.uber.org/zap"
  8. corev1 "k8s.io/api/core/v1"
  9. "github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/docker"
  10. metadataPkg "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/experimentalmetricmetadata"
  11. "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/metadata"
  12. imetadata "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/metadata"
  13. "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/utils"
  14. )
  15. const (
  16. // Keys for container metadata.
  17. containerKeyStatus = "container.status"
  18. containerKeyStatusReason = "container.status.reason"
  19. // Values for container metadata
  20. containerStatusRunning = "running"
  21. containerStatusWaiting = "waiting"
  22. containerStatusTerminated = "terminated"
  23. )
  24. // RecordSpecMetrics metricizes values from the container spec.
  25. // This includes values like resource requests and limits.
  26. func RecordSpecMetrics(logger *zap.Logger, mb *imetadata.MetricsBuilder, c corev1.Container, pod *corev1.Pod, ts pcommon.Timestamp) {
  27. for k, r := range c.Resources.Requests {
  28. //exhaustive:ignore
  29. switch k {
  30. case corev1.ResourceCPU:
  31. mb.RecordK8sContainerCPURequestDataPoint(ts, float64(r.MilliValue())/1000.0)
  32. case corev1.ResourceMemory:
  33. mb.RecordK8sContainerMemoryRequestDataPoint(ts, r.Value())
  34. case corev1.ResourceStorage:
  35. mb.RecordK8sContainerStorageRequestDataPoint(ts, r.Value())
  36. case corev1.ResourceEphemeralStorage:
  37. mb.RecordK8sContainerEphemeralstorageRequestDataPoint(ts, r.Value())
  38. default:
  39. logger.Debug("unsupported request type", zap.Any("type", k))
  40. }
  41. }
  42. for k, l := range c.Resources.Limits {
  43. //exhaustive:ignore
  44. switch k {
  45. case corev1.ResourceCPU:
  46. mb.RecordK8sContainerCPULimitDataPoint(ts, float64(l.MilliValue())/1000.0)
  47. case corev1.ResourceMemory:
  48. mb.RecordK8sContainerMemoryLimitDataPoint(ts, l.Value())
  49. case corev1.ResourceStorage:
  50. mb.RecordK8sContainerStorageLimitDataPoint(ts, l.Value())
  51. case corev1.ResourceEphemeralStorage:
  52. mb.RecordK8sContainerEphemeralstorageLimitDataPoint(ts, l.Value())
  53. default:
  54. logger.Debug("unsupported request type", zap.Any("type", k))
  55. }
  56. }
  57. var containerID string
  58. var imageStr string
  59. for _, cs := range pod.Status.ContainerStatuses {
  60. if cs.Name == c.Name {
  61. containerID = cs.ContainerID
  62. imageStr = cs.Image
  63. mb.RecordK8sContainerRestartsDataPoint(ts, int64(cs.RestartCount))
  64. mb.RecordK8sContainerReadyDataPoint(ts, boolToInt64(cs.Ready))
  65. break
  66. }
  67. }
  68. rb := mb.NewResourceBuilder()
  69. rb.SetK8sPodUID(string(pod.UID))
  70. rb.SetK8sPodName(pod.Name)
  71. rb.SetK8sNodeName(pod.Spec.NodeName)
  72. rb.SetK8sNamespaceName(pod.Namespace)
  73. rb.SetContainerID(utils.StripContainerID(containerID))
  74. rb.SetK8sContainerName(c.Name)
  75. image, err := docker.ParseImageName(imageStr)
  76. if err != nil {
  77. docker.LogParseError(err, imageStr, logger)
  78. } else {
  79. rb.SetContainerImageName(image.Repository)
  80. rb.SetContainerImageTag(image.Tag)
  81. }
  82. mb.EmitForResource(imetadata.WithResource(rb.Emit()))
  83. }
  84. func GetMetadata(cs corev1.ContainerStatus) *metadata.KubernetesMetadata {
  85. mdata := map[string]string{}
  86. if cs.State.Running != nil {
  87. mdata[containerKeyStatus] = containerStatusRunning
  88. }
  89. if cs.State.Terminated != nil {
  90. mdata[containerKeyStatus] = containerStatusTerminated
  91. mdata[containerKeyStatusReason] = cs.State.Terminated.Reason
  92. }
  93. if cs.State.Waiting != nil {
  94. mdata[containerKeyStatus] = containerStatusWaiting
  95. mdata[containerKeyStatusReason] = cs.State.Waiting.Reason
  96. }
  97. return &metadata.KubernetesMetadata{
  98. EntityType: "container",
  99. ResourceIDKey: conventions.AttributeContainerID,
  100. ResourceID: metadataPkg.ResourceID(utils.StripContainerID(cs.ContainerID)),
  101. Metadata: mdata,
  102. }
  103. }
  104. func boolToInt64(b bool) int64 {
  105. if b {
  106. return 1
  107. }
  108. return 0
  109. }