func (self *defaultDecoder) getContainerMetrics(container *source_api.Container, labels map[string]string) []sinksV1Api.Timeseries { if container == nil { return nil } labels[sinksV1Api.LabelContainerName.Key] = container.Name // One metric value per data point. var result []sinksV1Api.Timeseries labelsAsString := util.LabelsToString(labels, ",") for _, stat := range container.Stats { if stat == nil { continue } // Add all supported metrics that have values. for index, supported := range self.supportedStatMetrics { // Finest allowed granularity is seconds. stat.Timestamp = stat.Timestamp.Round(time.Second) key := timeseriesKey{ Name: supported.Name, Labels: labelsAsString, } // TODO: remove this once the heapster source is tested to not provide duplicate stats. if data, ok := self.lastExported[key]; ok && data.After(stat.Timestamp) { continue } if supported.HasValue(&container.Spec) { // Cumulative stats have container creation time as their start time. var startTime time.Time if supported.Type == sinksV1Api.MetricCumulative { startTime = container.Spec.CreationTime } else { startTime = stat.Timestamp } points := supported.GetValue(&container.Spec, stat) for _, point := range points { labels := util.CopyLabels(labels) for name, value := range point.Labels { labels[name] = value } timeseries := sinksV1Api.Timeseries{ MetricDescriptor: &self.supportedStatMetrics[index].MetricDescriptor, Point: &sinksV1Api.Point{ Name: supported.Name, Labels: labels, Start: startTime.Round(time.Second), End: stat.Timestamp, Value: point.Value, }, } result = append(result, timeseries) } } self.lastExported[key] = stat.Timestamp } } return result }
func (self *decoder) TimeseriesFromContainers(containers []*cache.ContainerElement) ([]Timeseries, error) { labels := make(map[string]string) var result []Timeseries for index := range containers { labels[LabelHostname.Key] = containers[index].Hostname result = append(result, self.getContainerMetrics(containers[index], util.CopyLabels(labels))...) } return result, nil }
func (self *defaultDecoder) getContainerSliceMetrics(containers []source_api.Container) []sinksV1Api.Timeseries { labels := make(map[string]string) var result []sinksV1Api.Timeseries for index := range containers { labels[sinksV1Api.LabelHostname.Key] = containers[index].Hostname labels[sinksV1Api.LabelHostID.Key] = containers[index].ExternalID result = append(result, self.getContainerMetrics(&containers[index], util.CopyLabels(labels))...) } return result }
func (self *decoder) getContainerMetrics(container *cache.ContainerElement, labels map[string]string) []Timeseries { if container == nil { return nil } labels[LabelContainerName.Key] = container.Name if _, exists := labels[LabelHostID.Key]; !exists { labels[LabelHostID.Key] = container.ExternalID } // One metric value per data point. var result []Timeseries labelsAsString := util.LabelsToString(labels, ",") for _, metric := range container.Metrics { if metric == nil || metric.Spec == nil || metric.Stats == nil { continue } // Add all supported metrics that have values. for index, supported := range self.supportedStatMetrics { // Finest allowed granularity is seconds. metric.Stats.Timestamp = metric.Stats.Timestamp.Round(time.Second) key := timeseriesKey{ Name: supported.Name, Labels: labelsAsString, } // TODO: remove this once the heapster source is tested to not provide duplicate metric.Statss. if data, ok := self.lastExported[key]; ok && data.After(metric.Stats.Timestamp) { continue } if supported.HasValue(metric.Spec) { // Cumulative metric.Statss have container creation time as their start time. var startTime time.Time if supported.Type == MetricCumulative { startTime = metric.Spec.CreationTime } else { startTime = metric.Stats.Timestamp } points := supported.GetValue(metric.Spec, metric.Stats) for _, point := range points { labels := util.CopyLabels(labels) for name, value := range point.Labels { labels[name] = value } timeseries := Timeseries{ MetricDescriptor: &self.supportedStatMetrics[index].MetricDescriptor, Point: &Point{ Name: supported.Name, Labels: labels, Start: startTime.Round(time.Second), End: metric.Stats.Timestamp, Value: point.Value, }, } result = append(result, timeseries) } } self.lastExported[key] = metric.Stats.Timestamp } } return result }