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 *decoder) getContainerMetrics(container *cache.ContainerElement, labels map[string]string) []Timeseries { if container == nil { return nil } labels[LabelContainerName.Key] = container.Name labels[LabelContainerBaseImage.Key] = container.Image // Add container specific labels along with existing labels. containerLabels := util.LabelsToString(container.Labels, ",") if labels[LabelLabels.Key] != "" { containerLabels = fmt.Sprintf("%s,%s", labels[LabelLabels.Key], containerLabels) } labels[LabelLabels.Key] = containerLabels 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 }