Skip to content

Commit

Permalink
Implement event filtering on measurements (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaminthorns committed Aug 20, 2024
1 parent ab86164 commit 2b4d743
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 34 deletions.
21 changes: 13 additions & 8 deletions lib/telemetry_metrics.ex
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,12 @@ defmodule Telemetry.Metrics do
* `:tag_values` - a function that receives the metadata and returns a map with
the tags as keys and their respective values. Defaults to returning the
metadata itself.
* `:keep` - a predicate function that evaluates the metadata to conditionally
record a given event. `:keep` and `:drop` cannot be combined. Defaults to `nil`.
* `:drop` - a predicate function that evaluates the metadata to conditionally
skip recording a given event. `:keep` and `:drop` cannot be combined. Defaults to `nil`.
* `:keep` - a predicate function that evaluates the metadata and measurement
to conditionally record a given event. `:keep` and `:drop` cannot be
combined. Defaults to `nil`.
* `:drop` - a predicate function that evaluates the metadata and measurement
to conditionally skip recording a given event. `:keep` and `:drop` cannot
be combined. Defaults to `nil`.
* `:description` - human-readable description of the metric. Might be used by
reporters for documentation purposes. Defaults to `nil`.
* `:unit` - an atom describing the unit of selected measurement, typically in
Expand Down Expand Up @@ -408,7 +410,9 @@ defmodule Telemetry.Metrics do
@type tag :: term()
@type tags :: [tag()]
@type tag_values :: (:telemetry.event_metadata() -> :telemetry.event_metadata())
@type keep :: (:telemetry.event_metadata() -> boolean())
@type keep ::
(:telemetry.event_metadata() -> boolean())
| (:telemetry.event_metadata(), :telemetry.event_measurements() -> boolean())
@type drop :: (:telemetry.event_metadata() -> boolean())
@type description :: nil | String.t()
@type unit :: atom()
Expand Down Expand Up @@ -614,11 +618,11 @@ defmodule Telemetry.Metrics do
end

defp validate_recording_rule_fun!(nil), do: nil
defp validate_recording_rule_fun!(fun) when is_function(fun, 1), do: fun
defp validate_recording_rule_fun!(fun) when is_function(fun, 1) or is_function(fun, 2), do: fun

defp validate_recording_rule_fun!(term) do
raise ArgumentError,
"expected recording rule to be a function accepting metadata, got #{inspect(term)}"
"expected recording rule to be a function accepting either metadata or metadata and measurements, got #{inspect(term)}"
end

defp validate_recording_rule_fun_options!(keep, drop) when is_nil(keep) or is_nil(drop), do: :ok
Expand All @@ -629,8 +633,9 @@ defmodule Telemetry.Metrics do
end

defp keep_fun(nil, nil), do: nil
defp keep_fun(nil, drop), do: fn meta -> not drop.(meta) end
defp keep_fun(keep, nil), do: keep
defp keep_fun(nil, drop) when is_function(drop, 1), do: &(not drop.(&1))
defp keep_fun(nil, drop) when is_function(drop, 2), do: &(not drop.(&1, &2))

@spec fill_in_default_metric_options([metric_option()]) :: [metric_option()]
defp fill_in_default_metric_options(options) do
Expand Down
11 changes: 8 additions & 3 deletions lib/telemetry_metrics/console_reporter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ defmodule Telemetry.Metrics.ConsoleReporter do
Measurement value missing (metric skipped)
"""

not keep?(metric, metadata) ->
not keep?(metric, metadata, measurements) ->
"""
Event dropped
"""
Expand Down Expand Up @@ -142,8 +142,13 @@ defmodule Telemetry.Metrics.ConsoleReporter do
"#{inspect(measurement)} [via #{inspect(fun)}]"
end

defp keep?(%{keep: nil}, _metadata), do: true
defp keep?(metric, metadata), do: metric.keep.(metadata)
defp keep?(metric, metadata, measurements) do
case metric do
%{keep: nil} -> true
%{keep: keep} when is_function(keep, 1) -> keep.(metadata)
%{keep: keep} when is_function(keep, 2) -> keep.(metadata, measurements)
end
end

defp extract_measurement(metric, measurements, metadata) do
case metric.measurement do
Expand Down
4 changes: 2 additions & 2 deletions lib/telemetry_metrics/counter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ defmodule Telemetry.Metrics.Counter do
event_name: :telemetry.event_name(),
measurement: Metrics.measurement(),
tags: Metrics.tags(),
tag_values: (:telemetry.event_metadata() -> :telemetry.event_metadata()),
keep: (:telemetry.event_metadata() -> boolean()),
tag_values: Metrics.tag_values(),
keep: Metrics.keep(),
description: Metrics.description(),
unit: Metrics.unit(),
reporter_options: Metrics.reporter_options()
Expand Down
4 changes: 2 additions & 2 deletions lib/telemetry_metrics/distribution.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ defmodule Telemetry.Metrics.Distribution do
event_name: :telemetry.event_name(),
measurement: Metrics.measurement(),
tags: Metrics.tags(),
tag_values: (:telemetry.event_metadata() -> :telemetry.event_metadata()),
keep: (:telemetry.event_metadata() -> boolean()),
tag_values: Metrics.tag_values(),
keep: Metrics.keep(),
description: Metrics.description(),
unit: Metrics.unit(),
reporter_options: Metrics.reporter_options()
Expand Down
4 changes: 2 additions & 2 deletions lib/telemetry_metrics/last_value.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ defmodule Telemetry.Metrics.LastValue do
event_name: :telemetry.event_name(),
measurement: Metrics.measurement(),
tags: Metrics.tags(),
tag_values: (:telemetry.event_metadata() -> :telemetry.event_metadata()),
keep: (:telemetry.event_metadata() -> boolean()),
tag_values: Metrics.tag_values(),
keep: Metrics.keep(),
description: Metrics.description(),
unit: Metrics.unit(),
reporter_options: Metrics.reporter_options()
Expand Down
4 changes: 2 additions & 2 deletions lib/telemetry_metrics/sum.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ defmodule Telemetry.Metrics.Sum do
event_name: :telemetry.event_name(),
measurement: Metrics.measurement(),
tags: Metrics.tags(),
tag_values: (:telemetry.event_metadata() -> :telemetry.event_metadata()),
keep: (:telemetry.event_metadata() -> boolean()),
tag_values: Metrics.tag_values(),
keep: Metrics.keep(),
description: Metrics.description(),
unit: Metrics.unit(),
reporter_options: Metrics.reporter_options()
Expand Down
4 changes: 2 additions & 2 deletions lib/telemetry_metrics/summary.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ defmodule Telemetry.Metrics.Summary do
event_name: :telemetry.event_name(),
measurement: Metrics.measurement(),
tags: Metrics.tags(),
tag_values: (:telemetry.event_metadata() -> :telemetry.event_metadata()),
keep: (:telemetry.event_metadata() -> boolean()),
tag_values: Metrics.tag_values(),
keep: Metrics.keep(),
description: Metrics.description(),
unit: Metrics.unit(),
reporter_options: Metrics.reporter_options()
Expand Down
29 changes: 16 additions & 13 deletions test/telemetry_metrics_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -146,28 +146,31 @@ defmodule Telemetry.MetricsTest do
keep_metric =
apply(Metrics, unquote(metric_type), [
"my.repo.query",
[
keep: &match?(%{repo: :my_app_read_only_repo}, &1)
]
[keep: &match?(%{repo: :my_app_read_only_repo}, &1)]
])

drop_metric =
apply(Metrics, unquote(metric_type), [
"my.repo.query",
[
drop: &match?(%{repo: :my_app_read_only_repo}, &1)
]
[drop: &match?(%{repo: :my_app_read_only_repo}, &1)]
])

keep_filter_fun = keep_metric.keep
assert keep_metric.keep.(%{repo: :my_app_read_only_repo})
refute keep_metric.keep.(%{repo: :my_app_repo})

assert keep_filter_fun.(%{repo: :my_app_read_only_repo})
refute keep_filter_fun.(%{repo: :my_app_repo})
refute drop_metric.keep.(%{repo: :my_app_read_only_repo})
assert drop_metric.keep.(%{repo: :my_app_repo})
end

drop_filter_fun = drop_metric.keep
test "using event filter that evaluates both metadata and measurement" do
metric =
apply(Metrics, unquote(metric_type), [
"my.repo.query",
[keep: &(match?(%{repo: :my_app_read_only_repo}, &1) and &2 > 100)]
])

refute drop_filter_fun.(%{repo: :my_app_read_only_repo})
assert drop_filter_fun.(%{repo: :my_app_repo})
assert metric.keep.(%{repo: :my_app_read_only_repo}, 200)
refute metric.keep.(%{repo: :my_app_read_only_repo}, 50)
end

test "setting both keep and drop options raises" do
Expand Down Expand Up @@ -314,7 +317,7 @@ defmodule Telemetry.MetricsTest do
end
end

test "raises when event filter is not a function with an arity of 2" do
test "raises when event filter is not a function with an arity of 1 or 2" do
Enum.each([keep: fn -> true end, drop: fn -> true end], fn filter ->
assert_raise ArgumentError, fn ->
apply(Metrics, unquote(metric_type), [
Expand Down

0 comments on commit 2b4d743

Please sign in to comment.