func (t *Translator) translateNode(node stats.NodeStats) ([]*v3.TimeSeries, error) { var timeSeries []*v3.TimeSeries monitoredLabels := map[string]string{ "project_id": t.project, "cluster_name": t.cluster, "zone": t.zone, "instance_id": t.instanceID, "namespace_id": "", "pod_id": "machine", "container_name": "", } tsFactory := newTimeSeriesFactory(monitoredLabels, t.resolution) // Uptime. This is embedded: there's no nil check. now := time.Now() uptimePoint := &v3.Point{ Interval: &v3.TimeInterval{ EndTime: now.Format(time.RFC3339), StartTime: now.Add(-1 * t.resolution).Format(time.RFC3339), }, Value: &v3.TypedValue{ DoubleValue: monitor.Float64Ptr(float64(time.Since(node.StartTime.Time).Seconds())), }, } timeSeries = append(timeSeries, tsFactory.newTimeSeries(noLabels, uptimeMD, uptimePoint)) // Memory stats. memTS, err := translateMemory(node.Memory, tsFactory) if err != nil { return nil, err } timeSeries = append(timeSeries, memTS...) // File-system stats. fsTS, err := translateFS("/", node.Fs, tsFactory) if err != nil { return nil, err } timeSeries = append(timeSeries, fsTS...) // CPU stats. cpuTS, err := translateCPU(node.CPU, tsFactory) if err != nil { return nil, err } timeSeries = append(timeSeries, cpuTS...) return timeSeries, nil }
// translateCPU creates all the TimeSeries for a give CPUStat. func translateCPU(cpu *stats.CPUStats, tsFactory *timeSeriesFactory) ([]*v3.TimeSeries, error) { var timeSeries []*v3.TimeSeries // First check that all required information is present. if cpu == nil { return nil, fmt.Errorf("CPU information missing.") } if cpu.UsageNanoCores == nil { return nil, fmt.Errorf("UsageNanoCores missing from CPUStats %v", cpu) } if cpu.UsageCoreNanoSeconds == nil { return nil, fmt.Errorf("UsageCoreNanoSeconds missing from CPUStats %v", cpu) } // Total CPU utilization for all time. Convert from nanosec to sec. cpuTotalPoint := tsFactory.newPoint(&v3.TypedValue{ DoubleValue: monitor.Float64Ptr(float64(*cpu.UsageCoreNanoSeconds) / float64(1000*1000*1000)), ForceSendFields: []string{"DoubleValue"}, }, cpu.Time.Time, usageTimeMD.MetricKind) timeSeries = append(timeSeries, tsFactory.newTimeSeries(noLabels, usageTimeMD, cpuTotalPoint)) return timeSeries, nil }
func (t *Translator) translateContainers(pods []stats.PodStats) ([]*v3.TimeSeries, error) { var timeSeries []*v3.TimeSeries metricsSeen := make(map[string]time.Time) metrics := make(map[string][]*v3.TimeSeries) for _, pod := range pods { namespace := pod.PodRef.Namespace podID := pod.PodRef.Name // There can be duplicate data points for containers, so only // take the latest one. for _, container := range pod.Containers { containerName := container.Name // Check for duplicates if container.StartTime.Time.Before(metricsSeen[containerName]) || container.StartTime.Time.Equal(metricsSeen[containerName]) { continue } metricsSeen[containerName] = container.StartTime.Time var containerSeries []*v3.TimeSeries monitoredLabels := map[string]string{ "project_id": t.project, "cluster_name": t.cluster, "zone": t.zone, "instance_id": t.instanceID, "namespace_id": namespace, "pod_id": podID, "container_name": containerName, } tsFactory := newTimeSeriesFactory(monitoredLabels, t.resolution) // Uptime. This is embedded: there's no nil check. now := time.Now() uptimePoint := &v3.Point{ Interval: &v3.TimeInterval{ EndTime: now.Format(time.RFC3339), StartTime: container.StartTime.Time.Format(time.RFC3339), }, Value: &v3.TypedValue{ DoubleValue: monitor.Float64Ptr(float64(time.Since(container.StartTime.Time).Seconds())), ForceSendFields: []string{"DoubleValue"}, }, } containerSeries = append(containerSeries, tsFactory.newTimeSeries(noLabels, uptimeMD, uptimePoint)) // Memory stats. memTS, err := translateMemory(container.Memory, tsFactory) if err != nil { return nil, err } containerSeries = append(containerSeries, memTS...) // File-system stats. rootfsTS, err := translateFS("/", container.Rootfs, tsFactory) if err != nil { return nil, err } containerSeries = append(containerSeries, rootfsTS...) logfsTS, err := translateFS("logs", container.Logs, tsFactory) if err != nil { return nil, err } containerSeries = append(containerSeries, logfsTS...) // CPU stats. cpuTS, err := translateCPU(container.CPU, tsFactory) if err != nil { return nil, err } containerSeries = append(containerSeries, cpuTS...) metrics[containerName] = containerSeries } } // Flatten the deduplicated metrics. for _, containerSeries := range metrics { timeSeries = append(timeSeries, containerSeries...) } return timeSeries, nil }