Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Sum of Squares calculation #428

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions lib/new_relic/harvest/collector/metric/harvester.ex
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,21 @@ defmodule NewRelic.Harvest.Collector.Metric.Harvester do
add(counter, @total_exclusive_time, encode(metric.total_exclusive_time))
add(counter, @min_call_time, encode(metric.min_call_time))
add(counter, @max_call_time, encode(metric.max_call_time))
add(counter, @sum_of_squares, encode(metric.sum_of_squares))

Map.put(metrics_acc, {metric.name, metric.scope}, counter)

counter ->
total_call_time = metric.total_call_time
acc_mean = decode(get(counter, @total_call_time)) / get(counter, @call_count)

add(counter, @call_count, round(metric.call_count))
add(counter, @total_call_time, encode(metric.total_call_time))
add(counter, @total_call_time, encode(total_call_time))

mean = decode(get(counter, @total_call_time)) / get(counter, @call_count)

delta = total_call_time - acc_mean
delta2 = total_call_time - mean

add(counter, @total_exclusive_time, encode(metric.total_exclusive_time))

if metric.min_call_time < decode(get(counter, @min_call_time)),
Expand All @@ -125,7 +133,7 @@ defmodule NewRelic.Harvest.Collector.Metric.Harvester do
if metric.max_call_time > decode(get(counter, @max_call_time)),
do: put(counter, @max_call_time, encode(metric.max_call_time))

add(counter, @sum_of_squares, encode(metric.sum_of_squares))
add(counter, @sum_of_squares, encode(delta * delta2))

metrics_acc
end
Expand Down
3 changes: 1 addition & 2 deletions lib/new_relic/metric/metric.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@ defmodule NewRelic.Metric do
total_call_time: 0,
total_exclusive_time: 0,
min_call_time: 0,
max_call_time: 0,
sum_of_squares: 0
max_call_time: 0
end
36 changes: 35 additions & 1 deletion test/metric_harvester_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,41 @@ defmodule MetricHarvesterTest do
[metric] = metrics
[metric_ident, metric_values] = metric
assert metric_ident == %{name: "TestMetric", scope: ""}
assert metric_values == [2, 150, 0, 0, 0, 0]
assert metric_values == [2, 150, 0, 0, 0, 1_250]

# Verify that the Harvester shuts down w/o error
Process.monitor(harvester)
Harvest.HarvestCycle.send_harvest(Collector.Metric.HarvesterSupervisor, harvester)
assert_receive {:DOWN, _ref, _, ^harvester, :shutdown}, 1000
end

test "Harvester - ensure correct sum of squares calculation" do
{:ok, harvester} =
DynamicSupervisor.start_child(
Collector.Metric.HarvesterSupervisor,
Collector.Metric.Harvester
)

values = Enum.map(1..100, &:rand.uniform/1)

Enum.each(values, fn value ->
metric = %NewRelic.Metric{name: "TestMetric", call_count: 1, total_call_time: value}
GenServer.cast(harvester, {:report, metric})
end)

# Calculate the actual SST value
count = Enum.count(values)
sum = Enum.sum(values)
mean = sum / count
sst = Enum.reduce(values, 0, fn val, acc -> :math.pow(val - mean, 2) + acc end)

# Gather the metric values
metrics = GenServer.call(harvester, :gather_harvest)
[metric] = metrics
[_, [100, _, _, _, _, harvested_sst]] = metric

# Verify online calculation is within reasonable limits
assert abs(sst - harvested_sst) < 0.1

# Verify that the Harvester shuts down w/o error
Process.monitor(harvester)
Expand Down
Loading