Current section

11 Versions

Jump to

Compare versions

8 files changed
+293 additions
-159 deletions
  @@ -4,6 +4,7 @@
4 4 locals_without_parens: [
5 5 assert_dispatched: 3,
6 6 assert_dispatched: 4,
7 - assert_dispatch: 4
7 + assert_dispatch: 4,
8 + on_exit: 1
8 9 ]
9 10 ]
  @@ -0,0 +1,39 @@
1 + # Changelog
2 +
3 + All notable changes to this project will be documented in this file.
4 +
5 + The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 + and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 +
8 + ## [0.2.0](https://github.com/beam-telemetry/telemetry_poller/tree/v0.2.0)
9 +
10 + ### Added
11 +
12 + * Added `:total_run_queue_lengths` and `:run_queue_lengths` memory measurements;
13 +
14 + ### Changed
15 +
16 + * `:total_run_queue_lengths` is now included in the set of default VM measurements;
17 + * A default Poller process, with a default set of VM measurements, is started when `:telemetry_poller`
18 + application starts (configurable via `:telemetry.poller, :default` application environment).
19 + * VM measurements are now provided to Poller's `:vm_measurements` option. Passing atom `:default`
20 + to this option makes the Poller use a default set of VM measurements;
21 + * Telemetry has been upgraded to version 0.3, meaning that VM measurements now use this version to
22 + emit the events.
23 +
24 + ### Removed
25 +
26 + * `Telemetry.Poller.vm_measurements/0` function has been removed in favor of `:vm_measurements`
27 + option.
28 +
29 + ### Fixed
30 +
31 + * Fixed the type definition of `Telemetry.Poller.measurement/0` type - no Dialyzer warnings are
32 + emitted when running it on the project.
33 +
34 + ## [0.1.0](https://github.com/beam-telemetry/telemetry_poller/tree/v0.1.0)
35 +
36 + ### Added
37 +
38 + * The Poller process periodically invoking registered functions which emit Telemetry events.
39 + It supports VM memory measurements and custom measurements provided as MFAs.
\ No newline at end of file
  @@ -1,31 +1,38 @@
1 1 # Telemetry.Poller
2 2
3 + [![CircleCI](https://circleci.com/gh/beam-telemetry/telemetry_poller.svg?style=svg)](https://circleci.com/gh/beam-telemetry/telemetry_poller)
4 + [![Codecov](https://codecov.io/gh/beam-telemetry/telemetry_poller/branch/master/graphs/badge.svg)](https://codecov.io/gh/beam-telemetry/telemetry_poller/branch/master/graphs/badge.svg)
5 +
3 6 Allows to periodically collect measurements and dispatch them as Telemetry events.
4 7
5 - Poller provides a convenient API for specifying functions called periodically to dispatch
6 - measurements as Telemetry events. It also includes helpers for measuring Erlang virtual machine
7 - metrics:
8 + `Telemetry.Poller` ships with a default poller for VM measurements:
9 +
10 + ```elixir
11 + config :telemetry_poller, :default,
12 + vm_measurements: :default # or a list such as [:total_memory, :binary_memory, ...]
13 + ```
14 +
15 + Poller also provides a convenient API for specifying functions called periodically to dispatch
16 + measurements as Telemetry events:
8 17
9 18 ```elixir
10 19 # define custom function dispatching event with value you're interested in
11 20 defmodule ExampleApp.Measurements do
12 21 def dispatch_session_count() do
13 - Telemetry.execute([:example_app, :session_count], ExampleApp.session_count())
22 + :telemetry.execute([:example_app, :session_count], ExampleApp.session_count())
14 23 end
15 24 end
16 25
17 26 Telemetry.Poller.start_link(
27 + # include custom measurement
18 28 measurements: [
19 - # include custom measurement
20 29 {ExampleApp.Measurements, :dispatch_session_count, []}
21 - # include default VM measurements
22 - | Telemetry.Poller.vm_measurements()
23 30 ],
24 31 period: 10_000 # configure sampling period
25 32 )
26 33 ```
27 34
28 - See [documentation](https://hexdocs.pm/telemetry_poller) for more concrete examples and usage
35 + See [documentation](https://hexdocs.pm/telemetry_poller/0.2.0) for more concrete examples and usage
29 36 instructions.
30 37
31 38 ## Copyright and License
  @@ -2,19 +2,20 @@
2 2 {<<"build_tools">>,[<<"mix">>]}.
3 3 {<<"description">>,
4 4 <<"Allows to periodically collect measurements and dispatch them as Telemetry events">>}.
5 - {<<"elixir">>,<<"~> 1.4">>}.
5 + {<<"elixir">>,<<"~> 1.5">>}.
6 6 {<<"files">>,
7 7 [<<"lib">>,<<"lib/telemetry_poller">>,<<"lib/telemetry_poller.ex">>,
8 - <<"lib/telemetry_poller/vm.ex">>,<<".formatter.exs">>,<<"mix.exs">>,
9 - <<"README.md">>,<<"LICENSE">>]}.
8 + <<"lib/telemetry_poller/application.ex">>,<<"lib/telemetry_poller/vm.ex">>,
9 + <<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>,<<"LICENSE">>,
10 + <<"CHANGELOG.md">>]}.
10 11 {<<"licenses">>,[<<"Apache 2.0">>]}.
11 12 {<<"links">>,
12 - [{<<"GitHub">>,<<"https://github.com/elixir-telemetry/telemetry_poller">>}]}.
13 + [{<<"GitHub">>,<<"https://github.com/beam-telemetry/telemetry_poller">>}]}.
13 14 {<<"name">>,<<"telemetry_poller">>}.
14 15 {<<"requirements">>,
15 16 [[{<<"app">>,<<"telemetry">>},
16 17 {<<"name">>,<<"telemetry">>},
17 18 {<<"optional">>,false},
18 19 {<<"repository">>,<<"hexpm">>},
19 - {<<"requirement">>,<<"~> 0.2.0">>}]]}.
20 - {<<"version">>,<<"0.1.0">>}.
20 + {<<"requirement">>,<<"~> 0.3">>}]]}.
21 + {<<"version">>,<<"0.2.0">>}.
  @@ -1,43 +1,130 @@
1 1 defmodule Telemetry.Poller do
2 - @moduledoc """
2 + @moduledoc ~S"""
3 3 A time-based poller to periodically dispatch Telemetry events.
4 4
5 - Measurements are MFAs called periodically by the Poller process. These MFAs should collect
6 - a value (if possible) and dispatch an event using `Telemetry.execute/3` function.
5 + By default a single poller is started under `Telemetry.Poller` application.
6 + It is started with name `Telemetry.Poller.Default` and a default set of VM
7 + measurements. It polls all default VM measurements, which is equivalent to:
7 8
8 - If the invokation of the MFA fails, the measurement is removed from the Poller.
9 + config :telemetry_poller, :default,
10 + vm_measurements: :default # this is the default
9 11
10 - See the "Example - (...)" sections for more concrete examples.
12 + But you may specify all VM measurements you want:
11 13
12 - ## Starting and stopping
14 + config :telemetry_poller, :default,
15 + vm_measurements: [:total_memory, :binary_memory, :total_run_queue_lengths]
13 16
14 - You can start the Poller using the `start_link/1` function. Poller can be alaso started as a
15 - part of your supervision tree, using both the old-style and the new-style child specifications:
17 + Measurements are MFAs called periodically by the poller process.
18 + You can disable the default poller by setting it to `false`:
16 19
17 - # pre Elixir 1.5.0
18 - children = [Supervisor.Spec.worker(Telemetry.Poller, [[period: 5000]])]
20 + config :telemetry_poller, :default, false
19 21
20 - # post Elixir 1.5.0
21 - children = [{Telemetry.Poller, [period: 5000]}]
22 + Telemetry poller also allows you perform custom measurements by spawning
23 + your own poller process:
22 24
23 - Supervisor.start_link(children, [strategy: :one_for_one])
25 + children = [
26 + {Telemetry.Poller,
27 + measurements: [{MyApp.Example, :measure, []}]}
28 + ]
24 29
25 - You can start as many Pollers as you wish, but generally you shouldn't need to do it, unless
26 - you know that it's not keeping up with collecting all specified measurements.
30 + For custom pollers, the measurements are given as MFAs. Those MFAs should
31 + collect a value (if possible) and dispatch an event using `:telemetry.execute/3`
32 + function. If the invokation of the MFA fails, the measurement is removed
33 + from the Poller.
27 34
28 - Measurements need to be provided via `:measurements` option.
35 + For all options, see `start_link/1`. The options listed there can be given
36 + to the default poller as well as to custom pollers.
37 +
38 + Over the next sections, we will describe all built-in VM measurements and
39 + explore some concrete examples.
29 40
30 41 ## VM measurements
31 42
32 - The `vm_measurements/1` function returns common measurements related to Erlang virtual machine
33 - metrics. See its documentation for more information.
43 + VM measurements need to be provided via `:vm_measurements` option. Below you
44 + can find a list of available measurements per category.
45 +
46 + ### Memory
47 +
48 + See documentation for `:erlang.memory/0` function for more information about
49 + each type of memory measured.
50 +
51 + * `:total_memory` - dispatches an event with total amount of currently allocated memory, in bytes.
52 + Event name is `[:vm, :memory, :total]` and event metadata is empty;
53 + * `:processes_memory` - dispatches an event with amount of memory cyrrently allocated for
54 + processes, in bytes. Event name is `[:vm, :memory, :processes]` and event metadata is empty;
55 + * `:processes_used_memory` - dispatches an event with amount of memory currently used for
56 + processes, in bytes. Event name is `[:vm, :memory, :processes_used]` and event metadata is empty.
57 + Memory measured is a fraction of value collected by `:processes_memory` measurement;
58 + * `:binary_memory` - dispatches an event with amount of memory currently allocated for binaries.
59 + Event name is `[:vm, :memory, :binary]` and event metadata is empty;
60 + * `:ets_memory` - dispatches an event with amount of memory currently allocated for ETS tables.
61 + Event name is `[:vm, :memory, :ets]` and event metadata is empty;
62 + * `:system_memory` - dispatches an event with amount of currently allocated memory not directly
63 + related to any process running in the VM, in bytes. Event name is `[:vm, :memory, :system]` and
64 + event metadata is empty;
65 + * `:atom_memory` - dispatches an event with amount of memory currently allocated for atoms. Event
66 + name is `[:vm, :memory, :atom]` and event metadata is empty;
67 + * `:atom_used_memory` - dispatches an event with amount of memory currently used for atoms. Event
68 + name is `[:vm, :memory, :atom_used]` and event metadata is empty;
69 + * `:code_memory` - dispatches an event with amount of memory currently allocated for code. Event
70 + name is `[:vm, :memory, :code]` and event metadata is empty;
71 +
72 + ### Run queue lengths
73 +
74 + On startup, the Erlang VM starts many schedulers to do both IO and CPU work. If a process
75 + needs to do some work or wait on IO, it is allocated to the appropriate scheduler. The run
76 + queue is a queue of tasks to be scheduled. A length of a run queue corresponds to the amount
77 + of work accumulated in the system. If a run queue length is constantly growing, it means that
78 + the BEAM is not keeping up with executing all the tasks.
79 +
80 + There are several run queue types in the Erlang VMe. Each CPU scheduler (usually one per core)
81 + has its own run queue, and since Erlang 20.0 there is one dirty CPU run queue, and one dirty
82 + IO run queue.
83 +
84 + The following VM measurements related to run queue lengths are available:
85 +
86 + * `:total_run_queue_lengths` - dispatches an event with a sum of normal schedulers' run queue lengths
87 + and a dirty CPU run queue length (if dirty schedulers are available). Event name is
88 + `[:vm, run_queue_lengths, :total]` and event metadata is empty.
89 +
90 + Note that the method of making this measurement varies between different Erlang versions: for
91 + Erlang 18 and 19, the implementation is less efficient than for version 20 and up.
92 +
93 + The length of all queues is not gathered atomically, so the event value does not represent
94 + a consistent snapshot of the run queues' state. However, the value is accurate enough to help
95 + to indentify issues in a running system.
96 +
97 + * `:run_queue_lengths` - dispatches events with individual normal run queue lengths and a dirty
98 + CPU run queue length (if dirty schedulers are available).
99 +
100 + For normal run queues, event name is `[:vm, run_queue_lengths, :normal]` and event metadata
101 + includes a single key, `:scheduler_id`, with the scheduler ID of the queue. Note that number
102 + of schedulers is fixed at virtual machine boot time, so the number of events emitted on each
103 + measurement is constant.
104 +
105 + For dirty CPU run queue, the event name is `[:vm, :run_queue_lengths, :dirty_cpu]` and the
106 + event metadata is empty.
107 +
108 + The length of all queues is not gathered atomically, so the event values do not represent
109 + a consistent snapshot of the run queues' state. However, the value is accurate enough to help
110 + to indentify issues in a running system.
111 +
112 + If you do not need the individual run queue lengths, it is more efficient to use
113 + `:total_run_queue_lengths` measurement.
114 +
115 + ### Default measurements
116 +
117 + When `:default` is provided as the value of `:vm_measurement` options, Poller uses
118 + `:total_memory`, `:processes_memory`, `:processes_used_memory`, `:binary_memory`,
119 + `:ets_memory` and `:total_run_queue_lengths` VM measurements.
34 120
35 121 ## Example - measuring message queue length of the process
36 122
37 - Measuring process' message queue length is a good way to find out if and when the process becomes
38 - the bottleneck. If the length of the queue is growing, it means that the process is not keeping
39 - up with the work it's been assigned and other processes asking it to do the work will get
40 - timeouts. Let's try to simulate that situation using the following GenServer:
123 + Measuring process' message queue length is a good way to find out if and when the
124 + process becomes the bottleneck. If the length of the queue is growing, it means that
125 + the process is not keeping up with the work it's been assigned and other processes
126 + asking it to do the work will get timeouts. Let's try to simulate that situation
127 + using the following GenServer:
41 128
42 129 defmodule Worker do
43 130 use GenServer
  @@ -60,8 +147,8 @@ defmodule Telemetry.Poller do
60 147 end
61 148 end
62 149
63 - When assigned with work (`handle_call/3`), the worker will sleep for 1 second to imitate long
64 - running task.
150 + When assigned with work (`handle_call/3`), the worker will sleep for 1 second to
151 + imitate long running task.
65 152
66 153 Now we need a measurement dispatching the message queue length of the worker:
67 154
  @@ -69,7 +156,7 @@ defmodule Telemetry.Poller do
69 156 def message_queue_length(name) do
70 157 with pid when is_pid(pid) <- Process.whereis(name),
71 158 {:message_queue_len, length} <- Process.info(pid, :message_queue_len) do
72 - Telemetry.execute([:example_app, :message_queue_length], length, %{name: name})
159 + :telemetry.execute([:example_app, :message_queue_length], length, %{name: name})
73 160 end
74 161 end
75 162 end
  @@ -89,10 +176,10 @@ defmodule Telemetry.Poller do
89 176
90 177 iex> defmodule Handler do
91 178 ...> def handle([:example_app, :message_queue_length], length, %{name: name}, _) do
92 - ...> IO.puts("Process #\{inspect(name)} message queue length: #\{length}")
179 + ...> IO.puts("Process #{inspect(name)} message queue length: #{length}")
93 180 ...> end
94 181 ...> end
95 - iex> Telemetry.attach(:handler, [:example_app, :message_queue_length], Handler, :handle)
182 + iex> :telemetry.attach(:handler, [:example_app, :message_queue_length], &Handler.handle/4, nil)
96 183 :ok
97 184
98 185 Now let's start assigning work to the worker:
  @@ -144,7 +231,7 @@ defmodule Telemetry.Poller do
144 231
145 232 defmodule ExampleApp.Measurements do
146 233 def dispatch_session_count() do
147 - Telemetry.execute([:example_app, :session_count], ExampleApp.session_count())
234 + :telemetry.execute([:example_app, :session_count], ExampleApp.session_count())
148 235 end
149 236 end
150 237
  @@ -161,8 +248,8 @@ defmodule Telemetry.Poller do
161 248 def dispatch_session_count() do
162 249 regulars = ExampleApp.regular_users_session_count()
163 250 admins = ExampleApp.admin_users_session_count()
164 - Telemetry.execute([:example_app, :session_count], regulars, %{role: :regular})
165 - Telemetry.execute([:example_app, :session_count], admins, %{role: :admin})
251 + :telemetry.execute([:example_app, :session_count], regulars, %{role: :regular})
252 + :telemetry.execute([:example_app, :session_count], admins, %{role: :admin})
166 253 end
167 254 end
168 255
  @@ -189,9 +276,10 @@ defmodule Telemetry.Poller do
189 276 :processes_memory,
190 277 :processes_used_memory,
191 278 :binary_memory,
192 - :ets_memory
279 + :ets_memory,
280 + :total_run_queue_lengths
193 281 ]
194 - @vm_memory_measurements [
282 + @vm_measurements [
195 283 :total_memory,
196 284 :processes_memory,
197 285 :processes_used_memory,
  @@ -200,7 +288,9 @@ defmodule Telemetry.Poller do
200 288 :atom_used_memory,
201 289 :binary_memory,
202 290 :code_memory,
203 - :ets_memory
291 + :ets_memory,
292 + :total_run_queue_lengths,
293 + :run_queue_lengths
204 294 ]
205 295
206 296 @type t :: GenServer.server()
  @@ -209,8 +299,9 @@ defmodule Telemetry.Poller do
209 299 {:name, GenServer.name()}
210 300 | {:period, period()}
211 301 | {:measurements, [measurement()]}
302 + | {:vm_measurements, :default | [vm_measurement()]}
212 303 @type period :: pos_integer()
213 - @type measurement() :: mfa()
304 + @type measurement() :: {module(), function :: atom(), args :: list()}
214 305 @type vm_measurement() ::
215 306 :total_memory
216 307 | :processes_memory
  @@ -221,47 +312,28 @@ defmodule Telemetry.Poller do
221 312 | :binary_memory
222 313 | :code_memory
223 314 | :ets_memory
315 + | :total_run_queue_lengths
316 + | :run_queue_lengths
224 317
225 318 ## API
226 319
227 - @doc """
228 - Returns a child specifiction for Poller.
229 -
230 - It accepts `t:options/0` as an argument, meaning that it's valid to start it under the supervisor
231 - as follows:
232 -
233 - alias Telemetry.Poller
234 - # use default options
235 - Supervisor.start_link([Poller], supervisor_opts) # use default options
236 - # customize options
237 - Supervisor.start_link([{Poller, period: 10_000}], supervisor_opts)
238 - # modify the child spec
239 - Supervisor.start_link(Supervisor.child_spec(Poller, id: MyPoller), supervisor_opts)
240 - """
241 - # Uncomment when dropping support for 1.4.x releases.
242 - # @spec child_spec(term()) :: Supervisor.child_spec()
243 - def child_spec(term)
244 -
245 - def child_spec(options) do
246 - %{
247 - id: __MODULE__,
248 - start: {__MODULE__, :start_link, [options]}
249 - }
250 - end
251 -
252 320 @doc """
253 321 Starts a Poller linked to the calling process.
254 322
255 323 Useful for starting Pollers as a part of a supervision tree.
256 324
257 - ### Options
325 + ## Options
258 326
259 327 * `:measurements` - a list of measurements used by Poller. For description of possible values
260 328 see `Telemetry.Poller` module documentation;
329 + * `:vm_measurements` - a list of atoms describing measurements related to the Erlang VM, or an
330 + atom `:default`, in which case default VM measurements are used. See "VM measurements" section in
331 + the module documentation for more information. Default value is `[]`;
261 332 * `:period` - time period before performing the same measurement again, in milliseconds. Default
262 333 value is #{@default_period} ms;
263 334 * `:name` - the name of the Poller process. See "Name Registragion" section of `GenServer`
264 335 documentation for information about allowed values.
336 +
265 337 """
266 338 @spec start_link(options()) :: GenServer.on_start()
267 339 def start_link(options \\ []) when is_list(options) do
  @@ -287,65 +359,6 @@ defmodule Telemetry.Poller do
287 359 GenServer.call(poller, :get_measurements)
288 360 end
289 361
290 - @doc """
291 - Returns measurements dispatching events with Erlang virtual machine metrics
292 -
293 - It accepts a list `t:vm_measurement/0`s and returns a list of `t:measurement/0`s which can
294 - be provided to `start_link/1`'s `:measurements` option.
295 -
296 - Do not rely on the exact values returned by this function - the only guarantee is that they
297 - are of type `t:measurement/0` and their modification will not be considered a breaking change,
298 - unless the shape of events dispatched by returned measurements changes.
299 -
300 - Returned measurements are unique.
301 -
302 - ## Available measurements
303 -
304 - ### Memory
305 -
306 - See documentation for `:erlang.memory/0` function for more information about each type of memory
307 - measured.
308 -
309 - * `:total_memory` - dispatches an event with total amount of currently allocated memory, in bytes.
310 - Event name is `[:vm, :memory, :total]` and event metadata is empty;
311 - * `:processes_memory` - dispatches an event with amount of memory cyrrently allocated for
312 - processes, in bytes. Event name is `[:vm, :memory, :processes]` and event metadata is empty;
313 - * `:processes_used_memory` - dispatches an event with amount of memory currently used for
314 - processes, in bytes. Event name is `[:vm, :memory, :processes_used]` and event metadata is empty.
315 - Memory measured is a fraction of value collected by `:processes_memory` measurement;
316 - * `:binary_memory` - dispatches an event with amount of memory currently allocated for binaries.
317 - Event name is `[:vm, :memory, :binary]` and event metadata is empty;
318 - * `:ets_memory` - dispatches an event with amount of memory currently allocated for ETS tables.
319 - Event name is `[:vm, :memory, :ets]` and event metadata is empty;
320 - * `:system_memory` - dispatches an event with amount of currently allocated memory not directly
321 - related to any process running in the VM, in bytes. Event name is `[:vm, :memory, :system]` and
322 - event metadata is empty;
323 - * `:atom_memory` - dispatches an event with amount of memory currently allocated for atoms. Event
324 - name is `[:vm, :memory, :atom]` and event metadata is empty;
325 - * `:atom_used_memory` - dispatches an event with amount of memory currently used for atoms. Event
326 - name is `[:vm, :memory, :atom_used]` and event metadata is empty;
327 - * `:code_memory` - dispatches an event with amount of memory currently allocated for code. Event
328 - name is `[:vm, :memory, :code]` and event metadata is empty;
329 -
330 - ## Default measurements
331 -
332 - The 0-arity version of this function includes `:total_memory`, `:processes_memory`,
333 - `:processes_used_memory`, `:binary_memory` and `:ets_memory` measurements by default.
334 -
335 - ## Examples
336 -
337 - alias Telemetry.Poller
338 - Poller.start_link(
339 - measurements: Poller.vm_measurements() ++ Poller.vm_measurements(:atom_memory)
340 - )
341 - """
342 - @spec vm_measurements([vm_measurement()]) :: [measurement()]
343 - def vm_measurements(vm_measurements \\ @default_vm_measurements)
344 - when is_list(vm_measurements) do
345 - measurements = parse_vm_measurements!(vm_measurements)
346 - Enum.uniq(measurements)
347 - end
348 -
349 362 ## GenServer callbacks
350 363
351 364 @impl true
  @@ -379,9 +392,16 @@ defmodule Telemetry.Poller do
379 392 gen_server_opts = Keyword.take(options, [:name])
380 393 measurements = Keyword.get(options, :measurements, [])
381 394 validate_measurements!(measurements)
395 +
396 + vm_measurements =
397 + options
398 + |> Keyword.get(:vm_measurements, [])
399 + |> parse_vm_measurements!()
400 + |> Enum.uniq()
401 +
382 402 period = Keyword.get(options, :period, @default_period)
383 403 validate_period!(period)
384 - {[measurements: measurements, period: period], gen_server_opts}
404 + {[measurements: measurements ++ vm_measurements, period: period], gen_server_opts}
385 405 end
386 406
387 407 @spec validate_measurements!(term()) :: :ok | no_return()
  @@ -391,7 +411,7 @@ defmodule Telemetry.Poller do
391 411 end
392 412
393 413 defp validate_measurements!(other) do
394 - raise ArgumentError, "Expected :measurements to be a list, got #{inspect(other)}"
414 + raise ArgumentError, "expected :measurements to be a list, got #{inspect(other)}"
395 415 end
396 416
397 417 @spec validate_measurement!(term()) :: :ok | no_return()
  @@ -402,14 +422,14 @@ defmodule Telemetry.Poller do
402 422
403 423 defp validate_measurement!(invalid_measurement) do
404 424 raise ArgumentError,
405 - "Expected measurement, got #{inspect(invalid_measurement)}"
425 + "expected measurement, got #{inspect(invalid_measurement)}"
406 426 end
407 427
408 428 @spec validate_period!(term()) :: :ok | no_return()
409 429 defp validate_period!(period) when is_integer(period) and period > 0, do: :ok
410 430
411 431 defp validate_period!(other),
412 - do: raise(ArgumentError, "Expected :period to be a postivie integer, got #{inspect(other)}")
432 + do: raise(ArgumentError, "expected :period to be a postivie integer, got #{inspect(other)}")
413 433
414 434 @spec schedule_measurement(collect_in_millis :: non_neg_integer()) :: :ok
415 435 defp schedule_measurement(collect_in_millis) do
  @@ -440,18 +460,22 @@ defmodule Telemetry.Poller do
440 460 :error
441 461 end
442 462
443 - @spec parse_vm_measurements!([term()]) :: [measurement()] | no_return()
463 + @spec parse_vm_measurements!(term()) :: [measurement()] | no_return()
464 + defp parse_vm_measurements!(:default) do
465 + parse_vm_measurements!(@default_vm_measurements)
466 + end
467 +
444 468 defp parse_vm_measurements!(vm_measurements) do
445 469 Enum.map(vm_measurements, &parse_vm_measurement!/1)
446 470 end
447 471
448 472 @spec parse_vm_measurement!(term()) :: measurement() | no_return()
449 - defp parse_vm_measurement!(memory) when memory in @vm_memory_measurements do
450 - vm_measurement(memory)
473 + defp parse_vm_measurement!(measurement) when measurement in @vm_measurements do
474 + vm_measurement(measurement)
451 475 end
452 476
453 477 defp parse_vm_measurement!(other) do
454 - raise ArgumentError, "Expected VM measurement, got #{inspect(other)}"
478 + raise ArgumentError, "unknown VM measurement #{inspect(other)}"
455 479 end
456 480
457 481 @spec vm_measurement(function :: atom()) :: measurement()
Loading more files…