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

Implement event filtering on measurements (#77) #111

Merged
merged 1 commit into from
Aug 20, 2024
Merged
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
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
Loading