update
This commit is contained in:
BIN
phoenix/deps/telemetry_poller/.hex
Normal file
BIN
phoenix/deps/telemetry_poller/.hex
Normal file
Binary file not shown.
133
phoenix/deps/telemetry_poller/CHANGELOG.md
Normal file
133
phoenix/deps/telemetry_poller/CHANGELOG.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.3.0](https://github.com/beam-telemetry/telemetry_poller/tree/v1.3.0)
|
||||
|
||||
### Added
|
||||
|
||||
- Add `atom_limit`, `process_limit`, and `port_limit` measurements to the `[vm, system_counts]` event. (#79)
|
||||
|
||||
## [1.2.0](https://github.com/beam-telemetry/telemetry_poller/tree/v1.2.0)
|
||||
|
||||
### Added
|
||||
|
||||
- Support `persistent_term` measurements.
|
||||
- Require Erlang/OTP 24+.
|
||||
|
||||
## [1.1.0](https://github.com/beam-telemetry/telemetry_poller/tree/v1.1.0)
|
||||
|
||||
### Added
|
||||
|
||||
- Add the `init_delay` configuration option. (#70)
|
||||
|
||||
## [1.0.0](https://github.com/beam-telemetry/telemetry_poller/tree/v1.0.0)
|
||||
|
||||
This release marks stability of the API. The library now requires Telemetry ~> 1.0.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix disabling the default poller via application environment.
|
||||
|
||||
### Changed
|
||||
|
||||
- Drop support for OTP 20.
|
||||
|
||||
## [0.5.1](https://github.com/beam-telemetry/telemetry_poller/tree/v0.5.1)
|
||||
|
||||
### Added
|
||||
|
||||
- Support `{:global, atom()}` and `{:via, module(), term()}` names for the poller process.
|
||||
|
||||
## [0.5.0](https://github.com/beam-telemetry/telemetry_poller/tree/v0.5.0)
|
||||
|
||||
### Added
|
||||
|
||||
- `system_counts` measurement
|
||||
|
||||
## [0.4.1](https://github.com/beam-telemetry/telemetry_poller/tree/v0.4.1)
|
||||
|
||||
### Changed
|
||||
|
||||
- Improve docs
|
||||
- No longer add a default name to telemetry processes
|
||||
|
||||
## [0.4.0](https://github.com/beam-telemetry/telemetry_poller/tree/v0.4.0)
|
||||
|
||||
Telemetry Poller has been rewritten in Erlang so it can be used by the overall Erlang community.
|
||||
Therefore, the `Telemetry.Poller` module must now be accessed as `telemetry_poller`.
|
||||
A new `process_info` measurement has also been added and the `vm_measurements` and `measurements`
|
||||
keys have been merged into a single `measurements` key for simplicity.
|
||||
|
||||
### Added
|
||||
|
||||
- `:process_info` measurement
|
||||
|
||||
### Changed
|
||||
|
||||
- `vm_measurements` and `measurements` have been merged into `measurements`
|
||||
- `Telemetry.Poller` has been rewritten to `telemetry_poller`
|
||||
|
||||
## [0.3.0](https://github.com/beam-telemetry/telemetry_poller/tree/v0.3.0)
|
||||
|
||||
This release marks the upgrade to Telemetry 0.4.0. This means that Poller measurements can emit a map
|
||||
of values now instead of a single one, making it less "noisy" when it comes to number of emitted events.
|
||||
|
||||
All specific memory measurements have been replaced with a single `:memory` measurement sending all
|
||||
the values that were emitted by old measurements at once.
|
||||
|
||||
`:run_queue_lengths` VM measurement has been removed for now, as we believe that as detailed data
|
||||
as it provided is not necessary to effectively debug the system. `:total_run_queue_lengths` VM
|
||||
measurement has been changed so that it reports a `:total` length of run queues, length of `:cpu`
|
||||
run queues (including dirty CPU run queue), and length of (dirty) `:io` run queue.
|
||||
|
||||
### Added
|
||||
|
||||
- `:memory` VM measurement reporting all the data returned by `:erlang.memory/0` call.
|
||||
|
||||
### Changed
|
||||
|
||||
- `:total_run_queue_lengths` VM measurement is reporting a `:total`, `:cpu` and `:io` run queue lengths
|
||||
now. See documentation for more details.
|
||||
|
||||
### Removed
|
||||
|
||||
- `:total_memory`, `:atom_memory`, `:atom_used_memory`, `:processes_memory`, `:processes_used_memory`,
|
||||
`:binary_memory`, `:ets_memory`, `:code_memory` and `:system_memory` VM measurements have been removed.
|
||||
Please use the `:memory` measurement now instead.
|
||||
|
||||
## [0.2.0](https://github.com/beam-telemetry/telemetry_poller/tree/v0.2.0)
|
||||
|
||||
### Added
|
||||
|
||||
- Added `:total_run_queue_lengths` and `:run_queue_lengths` memory measurements;
|
||||
|
||||
### Changed
|
||||
|
||||
- `:total_run_queue_lengths` is now included in the set of default VM measurements;
|
||||
- A default Poller process, with a default set of VM measurements, is started when `:telemetry_poller`
|
||||
application starts (configurable via `:telemetry.poller, :default` application environment).
|
||||
- VM measurements are now provided to Poller's `:vm_measurements` option. Passing atom `:default`
|
||||
to this option makes the Poller use a default set of VM measurements;
|
||||
- Telemetry has been upgraded to version 0.3, meaning that VM measurements now use this version to
|
||||
emit the events.
|
||||
|
||||
### Removed
|
||||
|
||||
- `Telemetry.Poller.vm_measurements/0` function has been removed in favor of `:vm_measurements`
|
||||
option.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed the type definition of `Telemetry.Poller.measurement/0` type - no Dialyzer warnings are
|
||||
emitted when running it on the project.
|
||||
|
||||
## [0.1.0](https://github.com/beam-telemetry/telemetry_poller/tree/v0.1.0)
|
||||
|
||||
### Added
|
||||
|
||||
- The Poller process periodically invoking registered functions which emit Telemetry events.
|
||||
It supports VM memory measurements and custom measurements provided as MFAs.
|
||||
177
phoenix/deps/telemetry_poller/LICENSE
Normal file
177
phoenix/deps/telemetry_poller/LICENSE
Normal file
@@ -0,0 +1,177 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
13
phoenix/deps/telemetry_poller/NOTICE
Normal file
13
phoenix/deps/telemetry_poller/NOTICE
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright (c) 2018, Chris McCord and Erlang Solutions
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
122
phoenix/deps/telemetry_poller/README.md
Normal file
122
phoenix/deps/telemetry_poller/README.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# telemetry_poller
|
||||
|
||||
[](https://github.com/beam-telemetry/telemetry_poller/actions/workflows/test.yml)
|
||||
[](https://codecov.io/gh/beam-telemetry/telemetry_poller/branch/master/graphs/badge.svg)
|
||||
|
||||
Allows to periodically collect measurements and dispatch them as Telemetry events.
|
||||
|
||||
`telemetry_poller` by default runs a poller to perform VM measurements:
|
||||
|
||||
* `[vm, memory]` - contains the total memory, process memory, and all other keys in `erlang:memory/0`
|
||||
* `[vm, total_run_queue_lengths]` - returns the run queue lengths for CPU and IO schedulers. It contains the `total`, `cpu` and `io` measurements
|
||||
* `[vm, system_counts]` - returns the current process, atom and port count as well as their respective limits as per `erlang:system_info/1`
|
||||
* `[vm, persistent_term]` - number of terms and memory byte size for `persistent_term`
|
||||
|
||||
You can directly consume those events after adding `telemetry_poller` as a dependency.
|
||||
|
||||
Poller also provides a convenient API for running custom pollers.
|
||||
|
||||
## Defining custom measurements
|
||||
|
||||
Poller also includes conveniences for performing process-based measurements as well as custom ones.
|
||||
|
||||
### Erlang
|
||||
|
||||
First define the poller with the custom measurements. The first measurement is the built-in `process_info` measurement and the second one is given by a custom module-function-args defined by you:
|
||||
|
||||
```erlang
|
||||
telemetry_poller:start_link(
|
||||
[{measurements, [
|
||||
{process_info, [{name, my_app_worker}, {event, [my_app, worker]}, {keys, [memory, message_queue_len]}]},
|
||||
{example_app_measurements, dispatch_session_count, []}
|
||||
]},
|
||||
{period, timer:seconds(10)}, % configure sampling period - default is timer:seconds(5)
|
||||
{init_delay, timer:seconds(600)}, % configure sampling initial delay - default is 0
|
||||
{name, my_app_poller}
|
||||
]).
|
||||
```
|
||||
|
||||
Now define the custom measurement and you are good to go:
|
||||
|
||||
```erlang
|
||||
-module(example_app_measurements).
|
||||
|
||||
dispatch_session_count() ->
|
||||
% emit a telemetry event when called
|
||||
telemetry:execute([example_app, session_count], #{count => example_app:session_count()}, #{}).
|
||||
```
|
||||
|
||||
### Elixir
|
||||
|
||||
You typically start the poller as a child in your supervision tree:
|
||||
|
||||
```elixir
|
||||
children = [
|
||||
{:telemetry_poller,
|
||||
# include custom measurement as an MFA tuple
|
||||
measurements: [
|
||||
{:process_info, name: :my_app_worker, event: [:my_app, :worker], keys: [:memory, :message_queue_len]},
|
||||
{ExampleApp.Measurements, :dispatch_session_count, []},
|
||||
],
|
||||
period: :timer.seconds(10), # configure sampling period - default is :timer.seconds(5)
|
||||
init_delay: :timer.seconds(600), # configure sampling initial delay - default is 0
|
||||
name: :my_app_poller}
|
||||
]
|
||||
|
||||
Supervisor.start_link(children, strategy: :one_for_one)
|
||||
```
|
||||
|
||||
The poller above has two periodic measurements. The first is the built-in `process_info` measurement that will gather the memory and message queue length of a process. The second is given by a custom module-function-args defined by you, such as below:
|
||||
|
||||
```elixir
|
||||
defmodule ExampleApp.Measurements do
|
||||
def dispatch_session_count() do
|
||||
# emit a telemetry event when called
|
||||
:telemetry.execute([:example_app, :session_count], %{count: ExampleApp.session_count()}, %{})
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
See [documentation](https://hexdocs.pm/telemetry_poller/) for more concrete examples and usage
|
||||
instructions.
|
||||
|
||||
## VM metrics example
|
||||
|
||||
### Erlang
|
||||
|
||||
Find, in `examples/telemetry_poller_vm.erl`, an example on how to retrieve to VM measurements,
|
||||
mentioned above.
|
||||
|
||||
To see it in action, fire up `rebar3 shell`, then
|
||||
|
||||
```erlang
|
||||
{ok, telemetry_poller_vm} = c("examples/telemetry_poller_vm").
|
||||
ok = file:delete("telemetry_poller_vm.beam"). % Deletes generated BEAM
|
||||
ok = telemetry_poller_vm:attach().
|
||||
```
|
||||
|
||||
### Elixir
|
||||
|
||||
Find, in `examples/TelemetryPollerVM.ex`, an example on how to retrieve to VM measurements,
|
||||
mentioned above.
|
||||
|
||||
To see it in action, first compile the Erlang sources with `rebar3 compile`.
|
||||
|
||||
Then fire up `iex -pa "_build/default/lib/*/ebin"`, then
|
||||
|
||||
```elixir
|
||||
{:ok, _} = Application.ensure_all_started(:telemetry_poller)
|
||||
|
||||
[TelemetryPollerVM] = c("examples/TelemetryPollerVM.ex")
|
||||
:ok = TelemetryPollerVM.attach()
|
||||
```
|
||||
|
||||
## Copyright and License
|
||||
|
||||
Copyright (c) 2025 Erlang Ecosystem Foundation.
|
||||
|
||||
telemetry_poller source code is released under Apache License, Version 2.0.
|
||||
|
||||
See [LICENSE](LICENSE) and [NOTICE](NOTICE) files for more information.
|
||||
Binary file not shown.
20
phoenix/deps/telemetry_poller/hex_metadata.config
Normal file
20
phoenix/deps/telemetry_poller/hex_metadata.config
Normal file
@@ -0,0 +1,20 @@
|
||||
{<<"app">>,<<"telemetry_poller">>}.
|
||||
{<<"build_tools">>,[<<"rebar3">>]}.
|
||||
{<<"description">>,
|
||||
<<"Periodically collect measurements and dispatch them as Telemetry events.">>}.
|
||||
{<<"files">>,
|
||||
[<<"CHANGELOG.md">>,<<"LICENSE">>,<<"NOTICE">>,<<"README.md">>,
|
||||
<<"rebar.config">>,<<"rebar.lock">>,<<"src">>,
|
||||
<<"src/telemetry_poller.app.src">>,<<"src/telemetry_poller.erl">>,
|
||||
<<"src/telemetry_poller_app.erl">>,<<"src/telemetry_poller_builtin.erl">>,
|
||||
<<"src/telemetry_poller_sup.erl">>]}.
|
||||
{<<"licenses">>,[<<"Apache-2.0">>]}.
|
||||
{<<"links">>,
|
||||
[{<<"GitHub">>,<<"https://github.com/beam-telemetry/telemetry_poller">>}]}.
|
||||
{<<"name">>,<<"telemetry_poller">>}.
|
||||
{<<"requirements">>,
|
||||
[{<<"telemetry">>,
|
||||
[{<<"app">>,<<"telemetry">>},
|
||||
{<<"optional">>,false},
|
||||
{<<"requirement">>,<<"~> 1.0">>}]}]}.
|
||||
{<<"version">>,<<"1.3.0">>}.
|
||||
33
phoenix/deps/telemetry_poller/rebar.config
Normal file
33
phoenix/deps/telemetry_poller/rebar.config
Normal file
@@ -0,0 +1,33 @@
|
||||
{minimum_otp_vsn, "24.0"}.
|
||||
|
||||
{erl_opts, [debug_info]}.
|
||||
|
||||
{deps, [
|
||||
{telemetry, "~> 1.0"}
|
||||
]}.
|
||||
|
||||
{profiles, [
|
||||
{test, [
|
||||
{erl_opts, [nowarn_export_all]},
|
||||
%% create junit xml for circleci
|
||||
{ct_opts, [{ct_hooks, [cth_surefire]}]},
|
||||
{src_dirs, ["src", "test/support"]}
|
||||
]}
|
||||
]}.
|
||||
|
||||
{shell, [{apps, [telemetry_poller]}]}.
|
||||
|
||||
{project_plugins, [rebar3_ex_doc]}.
|
||||
{ex_doc, [
|
||||
{main, "README"},
|
||||
{extras, [<<"README.md">>, <<"CHANGELOG.md">>, <<"LICENSE">>, <<"NOTICE">>]},
|
||||
{source_url, <<"https://github.com/beam-telemetry/telemetry_poller">>},
|
||||
{source_ref, <<"v1.3.0">>}
|
||||
]}.
|
||||
{hex, [
|
||||
{doc, #{provider => ex_doc}}
|
||||
]}.
|
||||
|
||||
%% take out warnings for unused exported functions
|
||||
{xref_checks,[undefined_function_calls, undefined_functions, locals_not_used,
|
||||
deprecated_function_calls, deprecated_functions]}.
|
||||
8
phoenix/deps/telemetry_poller/rebar.lock
Normal file
8
phoenix/deps/telemetry_poller/rebar.lock
Normal file
@@ -0,0 +1,8 @@
|
||||
{"1.2.0",
|
||||
[{<<"telemetry">>,{pkg,<<"telemetry">>,<<"1.0.0">>},0}]}.
|
||||
[
|
||||
{pkg_hash,[
|
||||
{<<"telemetry">>, <<"0F453A102CDF13D506B7C0AB158324C337C41F1CC7548F0BC0E130BBF0AE9452">>}]},
|
||||
{pkg_hash_ext,[
|
||||
{<<"telemetry">>, <<"73BC09FA59B4A0284EFB4624335583C528E07EC9AE76ACA96EA0673850AEC57A">>}]}
|
||||
].
|
||||
12
phoenix/deps/telemetry_poller/src/telemetry_poller.app.src
Normal file
12
phoenix/deps/telemetry_poller/src/telemetry_poller.app.src
Normal file
@@ -0,0 +1,12 @@
|
||||
{application,telemetry_poller,
|
||||
[{description,"Periodically collect measurements and dispatch them as Telemetry events."},
|
||||
{vsn,"1.3.0"},
|
||||
{registered,[]},
|
||||
{mod,{telemetry_poller_app,[]}},
|
||||
{applications,[kernel,stdlib,telemetry]},
|
||||
{env,[]},
|
||||
{modules,[]},
|
||||
{licenses,["Apache-2.0"]},
|
||||
{doc,"doc"},
|
||||
{links,[{"GitHub",
|
||||
"https://github.com/beam-telemetry/telemetry_poller"}]}]}.
|
||||
505
phoenix/deps/telemetry_poller/src/telemetry_poller.erl
Normal file
505
phoenix/deps/telemetry_poller/src/telemetry_poller.erl
Normal file
@@ -0,0 +1,505 @@
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
-module(telemetry_poller).
|
||||
|
||||
?MODULEDOC("""
|
||||
A time-based poller to periodically dispatch Telemetry events.
|
||||
|
||||
A poller is a process start in your supervision tree with a list
|
||||
of measurements to perform periodically. On start it expects the
|
||||
period in milliseconds and a list of measurements to perform. Initial delay
|
||||
is an optional parameter that sets time delay in milliseconds before starting
|
||||
measurements:
|
||||
|
||||
<!-- tabs-open -->
|
||||
|
||||
### Erlang
|
||||
|
||||
```
|
||||
telemetry_poller:start_link([
|
||||
{measurements, Measurements},
|
||||
{period, Period},
|
||||
{init_delay, InitDelay}
|
||||
])
|
||||
```
|
||||
|
||||
### Elixir
|
||||
|
||||
```
|
||||
:telemetry_poller.start_link(
|
||||
measurements: measurements,
|
||||
period: period,
|
||||
init_delay: init_delay
|
||||
)
|
||||
```
|
||||
|
||||
<!-- tabs-close -->
|
||||
|
||||
## Measurements
|
||||
|
||||
The following measurements are supported:
|
||||
|
||||
* `memory` (default)
|
||||
* `total_run_queue_lengths` (default)
|
||||
* `system_counts` (default)
|
||||
* `persistent_term` (default)
|
||||
* `{process_info, Proplist}`
|
||||
* `{Module, Function, Args}`
|
||||
|
||||
We will discuss each measurement in detail. Also note that the
|
||||
`telemetry_poller` application ships with a built-in poller that
|
||||
measures `memory`, `total_run_queue_lengths`, `system_counts`, and `persistent_term`. This takes
|
||||
the VM measurement out of the way so your application can focus
|
||||
on what is specific to its behaviour.
|
||||
|
||||
### Memory
|
||||
|
||||
An event emitted as `[vm, memory]`. The measurement includes all
|
||||
the key-value pairs returned by the `erlang:memory/0` function,
|
||||
e.g. `total` for total memory, `processes_used` for memory used by
|
||||
all processes, and so on.
|
||||
|
||||
### Total run queue lengths
|
||||
|
||||
On startup, the Erlang VM starts many schedulers to do both IO and
|
||||
CPU work. If a process needs to do some work or wait on IO, it is
|
||||
allocated to the appropriate scheduler. The measurement includes the
|
||||
following keys:
|
||||
|
||||
* `total` - all schedulers (CPU + IO)
|
||||
* `cpu` - CPU schedulers
|
||||
* `io` - IO schedulers
|
||||
|
||||
### System counts
|
||||
|
||||
The measurement includes:
|
||||
|
||||
* `process_count` - the number of processes currently existing at the local node
|
||||
* `atom_count` - the number of atoms currently existing at the local node
|
||||
* `port_count` - the number of ports currently existing at the local node
|
||||
* `process_limit` - the maximum number of processes allowed at the local node
|
||||
* `atom_limit` - the maximum number of atoms allowed at the local node
|
||||
* `port_limit` - the maximum number of ports allowed at the local node
|
||||
|
||||
### Persistent term (since 1.2.0)
|
||||
|
||||
An event emitted as `[vm, persistent_term]`. The measurement includes information
|
||||
about persistent terms in the system, as returned by `persistent_term:info/0`:
|
||||
|
||||
* `count` - The number of persistent terms
|
||||
* `memory` - The total amount of memory (measured in bytes) used by all persistent terms
|
||||
|
||||
### Process info
|
||||
|
||||
A measurement with information about a given process. It must be specified
|
||||
alongside a proplist with the process name, the event name, and a list of
|
||||
keys to be included:
|
||||
|
||||
<!-- tabs-open -->
|
||||
|
||||
### Erlang
|
||||
|
||||
```erlang
|
||||
{process_info, [
|
||||
{name, my_app_worker},
|
||||
{event, [my_app, worker]},
|
||||
{keys, [message_queue_len, memory]}
|
||||
]}
|
||||
```
|
||||
|
||||
### Elixir
|
||||
|
||||
```elixir
|
||||
{:process_info, [
|
||||
name: my_app_worker,
|
||||
event: [my_app, worker],
|
||||
keys: [message_queue_len, memory]
|
||||
]}
|
||||
```
|
||||
|
||||
<!-- tabs-close -->
|
||||
|
||||
### Custom measurements
|
||||
|
||||
Telemetry poller also allows you to perform custom measurements by passing
|
||||
a module-function-args tuple:
|
||||
|
||||
<!-- tabs-open -->
|
||||
|
||||
### Erlang
|
||||
|
||||
```erlang
|
||||
{my_app_example, measure, []}
|
||||
```
|
||||
|
||||
### Elixir
|
||||
|
||||
```elixir
|
||||
{MyApp.Example, :measure, []}
|
||||
```
|
||||
|
||||
<!-- tabs-close -->
|
||||
|
||||
The given function will be invoked periodically and they must explicitly invoke the
|
||||
`telemetry:execute/3` function. If the invocation of the MFA fails,
|
||||
the measurement is removed from the Poller.
|
||||
|
||||
For all options, see `start_link/1`. The options listed there can be given
|
||||
to the default poller as well as to custom pollers.
|
||||
|
||||
### Default poller
|
||||
|
||||
A default poller is started with `telemetry_poller` responsible for emitting
|
||||
measurements for `memory` and `total_run_queue_lengths`. You can customize
|
||||
the behaviour of the default poller by setting the `default` key under the
|
||||
`telemetry_poller` application environment. Setting it to `false` disables
|
||||
the poller.
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: tracking number of active sessions in web application
|
||||
|
||||
Let's imagine that you have a web application and you would like to periodically
|
||||
measure number of active user sessions.
|
||||
|
||||
<!-- tabs-open -->
|
||||
|
||||
### Erlang
|
||||
|
||||
```erlang
|
||||
-module(example_app).
|
||||
|
||||
session_count() ->
|
||||
% logic for calculating session count.
|
||||
```
|
||||
|
||||
### Elixir
|
||||
|
||||
```elixir
|
||||
defmodule ExampleApp do
|
||||
def session_count do
|
||||
# logic for calculating session count
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
<!-- tabs-close -->
|
||||
|
||||
To achieve that, we need a measurement dispatching the value we're interested in:
|
||||
|
||||
<!-- tabs-open -->
|
||||
|
||||
### Erlang
|
||||
|
||||
```erlang
|
||||
-module(example_app_measurements).
|
||||
|
||||
dispatch_session_count() ->
|
||||
telemetry:execute([example_app, session_count], example_app:session_count()).
|
||||
```
|
||||
|
||||
### Elixir
|
||||
|
||||
```elixir
|
||||
defmodule ExampleApp.Measurements do
|
||||
def dispatch_session_count do
|
||||
:telemetry.execute([:example_app, :session_count], ExampleApp.session_count())
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
<!-- tabs-close -->
|
||||
|
||||
and tell the Poller to invoke it periodically:
|
||||
|
||||
<!-- tabs-open -->
|
||||
|
||||
### Erlang
|
||||
|
||||
```erlang
|
||||
telemetry_poller:start_link([{measurements, [{example_app_measurements, dispatch_session_count, []}]).
|
||||
```
|
||||
|
||||
### Elixir
|
||||
|
||||
```elixir
|
||||
:telemetry_poller.start_link(measurements: [{ExampleApp.Measurements, :dispatch_session_count, []}])
|
||||
```
|
||||
|
||||
<!-- tabs-close -->
|
||||
|
||||
If you find that you need to somehow label the event values, e.g. differentiate between number of
|
||||
sessions of regular and admin users, you could use event metadata:
|
||||
|
||||
<!-- tabs-open -->
|
||||
|
||||
### Erlang
|
||||
|
||||
```erlang
|
||||
-module(example_app_measurements).
|
||||
|
||||
dispatch_session_count() ->
|
||||
Regulars = example_app:regular_users_session_count(),
|
||||
Admins = example_app:admin_users_session_count(),
|
||||
telemetry:execute([example_app, session_count], #{count => Admins}, #{role => admin}),
|
||||
telemetry:execute([example_app, session_count], #{count => Regulars}, #{role => regular}).
|
||||
```
|
||||
|
||||
### Elixir
|
||||
|
||||
```elixir
|
||||
defmodule ExampleApp.Measurements do
|
||||
def dispatch_session_count do
|
||||
regulars = ExampleApp.regular_users_session_count()
|
||||
admins = ExampleApp.admin_users_session_count()
|
||||
:telemetry.execute([:example_app, :session_count], %{count: admins}, %{role: :admin})
|
||||
:telemetry.execute([:example_app, :session_count], %{count: regulars}, %{role: :regular})
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
<!-- tabs-close -->
|
||||
|
||||
> #### Note {: .info}
|
||||
>
|
||||
> The other solution would be to dispatch two different events by hooking up
|
||||
> `example_app:regular_users_session_count/0` and `example_app:admin_users_session_count/0`
|
||||
> functions directly. However, if you add more and more user roles to your app, you'll find
|
||||
> yourself creating a new event for each one of them, which will force you to modify existing
|
||||
event handlers. If you can break down event value by some feature, like user role in this
|
||||
example, it's usually better to use event metadata than add new events.
|
||||
|
||||
This is a perfect use case for poller, because you don't need to write a dedicated process
|
||||
which would call these functions periodically. Additionally, if you find that you need to collect
|
||||
more statistics like this in the future, you can easily hook them up to the same poller process
|
||||
and avoid creating lots of processes which would stay idle most of the time.
|
||||
""").
|
||||
|
||||
-behaviour(gen_server).
|
||||
|
||||
%% API
|
||||
-export([
|
||||
child_spec/1,
|
||||
list_measurements/1,
|
||||
start_link/1
|
||||
]).
|
||||
|
||||
-export([code_change/3, handle_call/3, handle_cast/2,
|
||||
handle_info/2, init/1, terminate/2]).
|
||||
|
||||
-export_type([
|
||||
option/0,
|
||||
options/0,
|
||||
measurement/0,
|
||||
period/0]).
|
||||
|
||||
-include_lib("kernel/include/logger.hrl").
|
||||
|
||||
?DOC("""
|
||||
The reference to a poller process.
|
||||
""").
|
||||
-type t() :: gen_server:server_ref().
|
||||
|
||||
?DOC("""
|
||||
A list of options for the poller.
|
||||
""").
|
||||
-type options() :: [option()].
|
||||
|
||||
?DOC("""
|
||||
An option for the poller.
|
||||
""").
|
||||
-type option() ::
|
||||
{name, atom() | gen_server:server_name()}
|
||||
| {period, period()}
|
||||
| {init_delay, init_delay()}
|
||||
| {measurements, [measurement()]}.
|
||||
|
||||
?DOC("""
|
||||
A measurement for the poller.
|
||||
""").
|
||||
-type measurement() ::
|
||||
memory
|
||||
| total_run_queue_lengths
|
||||
| system_counts
|
||||
| persistent_term
|
||||
| {process_info, [{name, atom()} | {event, [atom()]} | {keys, [atom()]}]}
|
||||
| {module(), atom(), list()}.
|
||||
|
||||
?DOC("""
|
||||
A period for the poller.
|
||||
""").
|
||||
-type period() :: pos_integer().
|
||||
|
||||
?DOC("""
|
||||
An init delay for the poller.
|
||||
""").
|
||||
-type init_delay() :: non_neg_integer().
|
||||
|
||||
-type state() :: #{measurements => [measurement()], period => period()}.
|
||||
|
||||
?DOC("""
|
||||
Starts a poller linked to the calling process.
|
||||
|
||||
Useful for starting Pollers as a part of a supervision tree.
|
||||
|
||||
## Options
|
||||
|
||||
The default options are:
|
||||
|
||||
* `{name, telemetry_poller}`
|
||||
* `{period, timer:seconds(5)}`
|
||||
* `{init_delay, 0}`
|
||||
|
||||
""").
|
||||
-spec start_link(options()) -> gen_server:start_ret().
|
||||
start_link(Opts) when is_list(Opts) ->
|
||||
Args = parse_args(Opts),
|
||||
|
||||
case lists:keyfind(name, 1, Opts) of
|
||||
{name, Name} when is_atom(Name) -> gen_server:start_link({local, Name}, ?MODULE, Args, []);
|
||||
{name, Name} -> gen_server:start_link(Name, ?MODULE, Args, []);
|
||||
false -> gen_server:start_link(?MODULE, Args, [])
|
||||
end.
|
||||
|
||||
?DOC("""
|
||||
Returns a list of measurements used by the poller.
|
||||
""").
|
||||
-spec list_measurements(t()) -> [measurement()].
|
||||
list_measurements(Poller) ->
|
||||
gen_server:call(Poller, get_measurements).
|
||||
|
||||
?DOC(false).
|
||||
-spec init(map()) -> {ok, state()}.
|
||||
init(Args) ->
|
||||
schedule_measurement(maps:get(init_delay, Args)),
|
||||
{ok, #{
|
||||
measurements => maps:get(measurements, Args),
|
||||
period => maps:get(period, Args)}}.
|
||||
?DOC("""
|
||||
Returns a child spec for the poller for running under a supervisor.
|
||||
""").
|
||||
-spec child_spec(options()) -> supervisor:child_spec().
|
||||
child_spec(Opts) ->
|
||||
Id =
|
||||
case proplists:get_value(name, Opts) of
|
||||
undefined -> ?MODULE;
|
||||
Name when is_atom(Name) -> Name;
|
||||
{global, Name} -> Name;
|
||||
{via, _, Name} -> Name
|
||||
end,
|
||||
|
||||
#{
|
||||
id => Id,
|
||||
start => {telemetry_poller, start_link, [Opts]}
|
||||
}.
|
||||
|
||||
parse_args(Args) ->
|
||||
Measurements = proplists:get_value(measurements, Args, []),
|
||||
Period = proplists:get_value(period, Args, timer:seconds(5)),
|
||||
InitDelay = proplists:get_value(init_delay, Args, 0),
|
||||
#{
|
||||
measurements => parse_measurements(Measurements),
|
||||
period => validate_period(Period),
|
||||
init_delay => validate_init_delay(InitDelay)
|
||||
}.
|
||||
|
||||
-spec schedule_measurement(non_neg_integer()) -> ok.
|
||||
schedule_measurement(CollectInMillis) ->
|
||||
erlang:send_after(CollectInMillis, self(), collect), ok.
|
||||
|
||||
-spec validate_period(term()) -> period() | no_return().
|
||||
validate_period(Period) when is_integer(Period), Period > 0 ->
|
||||
Period;
|
||||
validate_period(Term) ->
|
||||
erlang:error({badarg, "Expected period to be a positive integer"}, [Term]).
|
||||
|
||||
-spec validate_init_delay(term()) -> init_delay() | no_return().
|
||||
validate_init_delay(InitDelay) when is_integer(InitDelay), InitDelay >= 0 ->
|
||||
InitDelay;
|
||||
validate_init_delay(Term) ->
|
||||
erlang:error({badarg, "Expected init_delay to be 0 or a positive integer"}, [Term]).
|
||||
|
||||
-spec parse_measurements([measurement()]) -> [{module(), atom(), list()}].
|
||||
parse_measurements(Measurements) when is_list(Measurements) ->
|
||||
lists:map(fun parse_measurement/1, Measurements);
|
||||
parse_measurements(Term) ->
|
||||
erlang:error({badarg, "Expected measurements to be a list"}, [Term]).
|
||||
|
||||
-spec parse_measurement(measurement()) -> {module(), atom(), list()}.
|
||||
parse_measurement(memory) ->
|
||||
{telemetry_poller_builtin, memory, []};
|
||||
parse_measurement(total_run_queue_lengths) ->
|
||||
{telemetry_poller_builtin, total_run_queue_lengths, []};
|
||||
parse_measurement(system_counts) ->
|
||||
{telemetry_poller_builtin, system_counts, []};
|
||||
parse_measurement(persistent_term) ->
|
||||
{telemetry_poller_builtin, persistent_term, []};
|
||||
parse_measurement({process_info, List}) when is_list(List) ->
|
||||
Name = case proplists:get_value(name, List) of
|
||||
undefined -> erlang:error({badarg, "Expected `name' key to be given under process_info measurement"});
|
||||
PropName when is_atom(PropName) -> PropName;
|
||||
PropName -> erlang:error({badarg, "Expected `name' key to be an atom under process_info measurement"}, [PropName])
|
||||
end,
|
||||
|
||||
Event = case proplists:get_value(event, List) of
|
||||
undefined -> erlang:error({badarg, "Expected `event' key to be given under process_info measurement"});
|
||||
PropEvent when is_list(PropEvent) -> PropEvent;
|
||||
PropEvent -> erlang:error({badarg, "Expected `event' key to be a list of atoms under process_info measurement"}, [PropEvent])
|
||||
end,
|
||||
|
||||
Keys = case proplists:get_value(keys, List) of
|
||||
undefined -> erlang:error({badarg, "Expected `keys' key to be given under process_info measurement"});
|
||||
PropKeys when is_list(PropKeys) -> PropKeys;
|
||||
PropKeys -> erlang:error({badarg, "Expected `keys' key to be a list of atoms under process_info measurement"}, [PropKeys])
|
||||
end,
|
||||
|
||||
{telemetry_poller_builtin, process_info, [Event, Name, Keys]};
|
||||
parse_measurement({M, F, A}) when is_atom(M), is_atom(F), is_list(A) ->
|
||||
{M, F, A};
|
||||
parse_measurement(Term) ->
|
||||
erlang:error({badarg, "Expected measurement to be memory, total_run_queue_lengths, {process_info, list()}, or a {module(), function(), list()} tuple"}, [Term]).
|
||||
|
||||
-spec make_measurements_and_filter_misbehaving([measurement()]) -> [measurement()].
|
||||
make_measurements_and_filter_misbehaving(Measurements) ->
|
||||
[Measurement || Measurement <- Measurements, make_measurement(Measurement) =/= error].
|
||||
|
||||
-spec make_measurement(measurement()) -> measurement() | no_return().
|
||||
make_measurement(Measurement = {M, F, A}) ->
|
||||
try erlang:apply(M, F, A) of
|
||||
_ -> Measurement
|
||||
catch
|
||||
Class:Reason:Stacktrace ->
|
||||
?LOG_ERROR("Error when calling MFA defined by measurement: ~p ~p ~p~n"
|
||||
"Class=~p~nReason=~p~nStacktrace=~p~n",
|
||||
[M, F, A, Class, Reason, Stacktrace]),
|
||||
error
|
||||
end.
|
||||
|
||||
?DOC(false).
|
||||
handle_call(get_measurements, _From, State = #{measurements := Measurements}) ->
|
||||
{reply, Measurements, State};
|
||||
handle_call(_Request, _From, State) ->
|
||||
{reply, ok, State}.
|
||||
|
||||
?DOC(false).
|
||||
handle_cast(_Msg, State) -> {noreply, State}.
|
||||
|
||||
?DOC(false).
|
||||
handle_info(collect, State) ->
|
||||
GoodMeasurements = make_measurements_and_filter_misbehaving(maps:get(measurements, State)),
|
||||
schedule_measurement(maps:get(period, State)),
|
||||
{noreply, State#{measurements := GoodMeasurements}};
|
||||
handle_info(_, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
?DOC(false).
|
||||
terminate(_Reason, _State) -> ok.
|
||||
|
||||
?DOC(false).
|
||||
code_change(_OldVsn, State, _Extra) -> {ok, State}.
|
||||
29
phoenix/deps/telemetry_poller/src/telemetry_poller_app.erl
Normal file
29
phoenix/deps/telemetry_poller/src/telemetry_poller_app.erl
Normal file
@@ -0,0 +1,29 @@
|
||||
%% @private
|
||||
-module(telemetry_poller_app).
|
||||
|
||||
-behaviour(application).
|
||||
|
||||
-export([start/2, stop/1]).
|
||||
|
||||
start(_StartType, _StartArgs) ->
|
||||
PollerChildSpec =
|
||||
case application:get_env(telemetry_poller, default, []) of
|
||||
false ->
|
||||
[];
|
||||
PollerOpts ->
|
||||
Default = #{
|
||||
name => telemetry_poller_default,
|
||||
measurements => [
|
||||
memory,
|
||||
total_run_queue_lengths,
|
||||
system_counts,
|
||||
persistent_term
|
||||
]
|
||||
},
|
||||
FinalOpts = maps:to_list(maps:merge(Default, maps:from_list(PollerOpts))),
|
||||
[telemetry_poller:child_spec(FinalOpts)]
|
||||
end,
|
||||
telemetry_poller_sup:start_link(PollerChildSpec).
|
||||
|
||||
stop(_State) ->
|
||||
ok.
|
||||
@@ -0,0 +1,64 @@
|
||||
%% @private
|
||||
-module(telemetry_poller_builtin).
|
||||
|
||||
-export([
|
||||
memory/0,
|
||||
total_run_queue_lengths/0,
|
||||
system_counts/0,
|
||||
persistent_term/0,
|
||||
process_info/3
|
||||
]).
|
||||
|
||||
-spec process_info([atom()], atom(), [atom()]) -> ok.
|
||||
process_info(Event, Name, Measurements) ->
|
||||
case erlang:whereis(Name) of
|
||||
undefined -> ok;
|
||||
Pid ->
|
||||
case erlang:process_info(Pid, Measurements) of
|
||||
undefined -> ok;
|
||||
Info -> telemetry:execute(Event, maps:from_list(Info), #{name => Name})
|
||||
end
|
||||
end.
|
||||
|
||||
-spec memory() -> ok.
|
||||
memory() ->
|
||||
Measurements = erlang:memory(),
|
||||
telemetry:execute([vm, memory], maps:from_list(Measurements), #{}).
|
||||
|
||||
-spec total_run_queue_lengths() -> ok.
|
||||
total_run_queue_lengths() ->
|
||||
Total = cpu_stats(total),
|
||||
CPU = cpu_stats(cpu),
|
||||
telemetry:execute([vm, total_run_queue_lengths], #{
|
||||
total => Total,
|
||||
cpu => CPU,
|
||||
io => Total - CPU},
|
||||
#{}).
|
||||
|
||||
-spec cpu_stats(total | cpu) -> non_neg_integer().
|
||||
cpu_stats(total) ->
|
||||
erlang:statistics(total_run_queue_lengths_all);
|
||||
cpu_stats(cpu) ->
|
||||
erlang:statistics(total_run_queue_lengths).
|
||||
|
||||
-spec system_counts() -> ok.
|
||||
system_counts() ->
|
||||
ProcessCount = erlang:system_info(process_count),
|
||||
AtomCount = erlang:system_info(atom_count),
|
||||
PortCount = erlang:system_info(port_count),
|
||||
ProcessLimit = erlang:system_info(process_limit),
|
||||
AtomLimit = erlang:system_info(atom_limit),
|
||||
PortLimit = erlang:system_info(port_limit),
|
||||
telemetry:execute([vm, system_counts], #{
|
||||
process_count => ProcessCount,
|
||||
atom_count => AtomCount,
|
||||
port_count => PortCount,
|
||||
process_limit => ProcessLimit,
|
||||
atom_limit => AtomLimit,
|
||||
port_limit => PortLimit
|
||||
}).
|
||||
|
||||
-spec persistent_term() -> ok.
|
||||
persistent_term() ->
|
||||
Info = persistent_term:info(),
|
||||
telemetry:execute([vm, persistent_term], Info, #{}).
|
||||
18
phoenix/deps/telemetry_poller/src/telemetry_poller_sup.erl
Normal file
18
phoenix/deps/telemetry_poller/src/telemetry_poller_sup.erl
Normal file
@@ -0,0 +1,18 @@
|
||||
%% @private
|
||||
-module(telemetry_poller_sup).
|
||||
|
||||
-behaviour(supervisor).
|
||||
|
||||
-export([start_link/1]).
|
||||
-export([init/1]).
|
||||
|
||||
-define(SERVER, ?MODULE).
|
||||
|
||||
start_link(PollerChildSpec) ->
|
||||
supervisor:start_link({local, ?SERVER}, ?MODULE, PollerChildSpec).
|
||||
|
||||
init(PollerChildSpec) ->
|
||||
SupFlags = #{strategy => one_for_one,
|
||||
intensity => 1,
|
||||
period => 5},
|
||||
{ok, {SupFlags, PollerChildSpec}}.
|
||||
Reference in New Issue
Block a user