github.com/jonaz/heapster@v1.3.0-beta.0.0.20170208112634-cd3c15ca3d29/metrics/processors/rate_calculator.go (about)

     1  // Copyright 2015 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package processors
    16  
    17  import (
    18  	"k8s.io/heapster/metrics/core"
    19  
    20  	"github.com/golang/glog"
    21  )
    22  
    23  type RateCalculator struct {
    24  	rateMetricsMapping map[string]core.Metric
    25  	previousBatch      *core.DataBatch
    26  }
    27  
    28  func (this *RateCalculator) Name() string {
    29  	return "rate calculator"
    30  }
    31  
    32  func (this *RateCalculator) Process(batch *core.DataBatch) (*core.DataBatch, error) {
    33  	if this.previousBatch == nil {
    34  		this.previousBatch = batch
    35  		return batch, nil
    36  	}
    37  	if !batch.Timestamp.After(this.previousBatch.Timestamp) {
    38  		// something got out of sync, do nothing.
    39  		glog.Errorf("New data batch has timestamp before the previous one: new:%v old:%v", batch.Timestamp, this.previousBatch.Timestamp)
    40  		return batch, nil
    41  	}
    42  
    43  	for key, newMs := range batch.MetricSets {
    44  
    45  		if oldMs, found := this.previousBatch.MetricSets[key]; found {
    46  			if !newMs.ScrapeTime.After(oldMs.ScrapeTime) {
    47  				// New must be strictly after old.
    48  				continue
    49  			}
    50  			if !newMs.CreateTime.Equal(oldMs.CreateTime) {
    51  				glog.V(4).Infof("Skipping rates for %s - different create time new:%v  old:%v", key, newMs.CreateTime, oldMs.CreateTime)
    52  				// Create time for container must be the same.
    53  				continue
    54  			}
    55  
    56  			for metricName, targetMetric := range this.rateMetricsMapping {
    57  				metricValNew, foundNew := newMs.MetricValues[metricName]
    58  				metricValOld, foundOld := oldMs.MetricValues[metricName]
    59  				if foundNew && foundOld {
    60  					if metricName == core.MetricCpuUsage.MetricDescriptor.Name {
    61  						// cpu/usage values are in nanoseconds; we want to have it in millicores (that's why constant 1000 is here).
    62  						newVal := 1000 * (metricValNew.IntValue - metricValOld.IntValue) /
    63  							(newMs.ScrapeTime.UnixNano() - oldMs.ScrapeTime.UnixNano())
    64  
    65  						newMs.MetricValues[targetMetric.MetricDescriptor.Name] = core.MetricValue{
    66  							ValueType:  core.ValueInt64,
    67  							MetricType: core.MetricGauge,
    68  							IntValue:   newVal,
    69  						}
    70  
    71  					} else if targetMetric.MetricDescriptor.ValueType == core.ValueFloat {
    72  						newVal := 1e9 * float32(metricValNew.IntValue-metricValOld.IntValue) /
    73  							float32(newMs.ScrapeTime.UnixNano()-oldMs.ScrapeTime.UnixNano())
    74  
    75  						newMs.MetricValues[targetMetric.MetricDescriptor.Name] = core.MetricValue{
    76  							ValueType:  core.ValueFloat,
    77  							MetricType: core.MetricGauge,
    78  							FloatValue: newVal,
    79  						}
    80  					}
    81  				}
    82  			}
    83  		}
    84  	}
    85  	this.previousBatch = batch
    86  	return batch, nil
    87  }
    88  
    89  func NewRateCalculator(metrics map[string]core.Metric) *RateCalculator {
    90  	return &RateCalculator{
    91  		rateMetricsMapping: metrics,
    92  	}
    93  }