d7b4f36a3c
Process.clock_gettime allows getting the real time in nanoseconds as well as allowing one to get a monotonic timestamp. This offers greater accuracy without the overhead of having to allocate a Time instance. In general using Time.now/Time.new is about 2x slower than using Process.clock_gettime(). For example: require 'benchmark/ips' Benchmark.ips do |bench| bench.report 'Time.now' do Time.now.to_f end bench.report 'clock_gettime' do Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) end bench.compare! end Running this benchmark gives: Calculating ------------------------------------- Time.now 108.052k i/100ms clock_gettime 125.984k i/100ms ------------------------------------------------- Time.now 2.343M (± 7.1%) i/s - 11.670M clock_gettime 4.979M (± 0.8%) i/s - 24.945M Comparison: clock_gettime: 4979393.8 i/s Time.now: 2342986.8 i/s - 2.13x slower Another benefit of using Process.clock_gettime() is that we can simplify the code a bit since it can give timestamps in nanoseconds out of the box.
47 lines
1.8 KiB
Ruby
47 lines
1.8 KiB
Ruby
module Gitlab
|
|
module Metrics
|
|
# Class for storing details of a single metric (label, value, etc).
|
|
class Metric
|
|
JITTER_RANGE = 0.000001..0.001
|
|
|
|
attr_reader :series, :values, :tags
|
|
|
|
# series - The name of the series (as a String) to store the metric in.
|
|
# values - A Hash containing the values to store.
|
|
# tags - A Hash containing extra tags to add to the metrics.
|
|
def initialize(series, values, tags = {})
|
|
@values = values
|
|
@series = series
|
|
@tags = tags
|
|
end
|
|
|
|
# Returns a Hash in a format that can be directly written to InfluxDB.
|
|
def to_hash
|
|
# InfluxDB overwrites an existing point if a new point has the same
|
|
# series, tag set, and timestamp. In a highly concurrent environment
|
|
# this means that using the number of seconds since the Unix epoch is
|
|
# inevitably going to collide with another timestamp. For example, two
|
|
# Rails requests processed by different processes may end up generating
|
|
# metrics using the _exact_ same timestamp (in seconds).
|
|
#
|
|
# Due to the way InfluxDB is set up there's no solution to this problem,
|
|
# all we can do is lower the amount of collisions. We do this by using
|
|
# System.real_time which returns the nanoseconds as a Float providing
|
|
# greater accuracy. We then add a small random value that is large
|
|
# enough to distinguish most timestamps but small enough to not alter
|
|
# the timestamp significantly.
|
|
#
|
|
# See https://gitlab.com/gitlab-com/operations/issues/175 for more
|
|
# information.
|
|
time = System.real_time(:nanosecond) + rand(JITTER_RANGE)
|
|
|
|
{
|
|
series: @series,
|
|
tags: @tags,
|
|
values: @values,
|
|
timestamp: time.to_i
|
|
}
|
|
end
|
|
end
|
|
end
|
|
end
|