txt: ## telemetry.md
  class Telemetry
  
  Collect performance state for analysis
  
  ```raku
  class Telemetry { }
  ```
  
  **Note:**  This class is a Rakudo-specific feature and not standard Raku.
  
  On creation, a `Telemetry` object contains a snapshot of various aspects of the current state of the virtual machine. This is in itself useful, but generally one needs two snapshots for the difference (which is a [`Telemetry::Period`](/type/Telemetry/Period) object).
  
  The Telemetry object is really a collection of snapshots taken by different "instruments". By default, the [`Telemetry::Instrument::Usage`](/type/Telemetry/Instrument/Usage) and [`Telemetry::Instrument::ThreadPool`](/type/Telemetry/Instrument/ThreadPool) instruments are activated.
  
  The `Telemetry` (and [`Telemetry::Period`](/type/Telemetry/Period)) object also [`Associative`](/type/Associative). This means that you can treat a Telemetry object as a read-only [`Hash`](/type/Hash), with all of the data values of the instruments as keys.
  
  You can determine which instruments `Telemetry` should use by setting the `$*SAMPLER` dynamic variable, which is a [`Telemetry::Sampler`](/type/Telemetry/Sampler) object.
  
  Currently, the following instruments are supported by the Rakudo core:
  
  * Telemetry::Instrument::Usage
  
  Provides (in alphabetical order): `cpu`, `cpu-sys`, `cpu-user`, `cpus`, `id-rss`, `inb`, `invcsw`, `is-rss`, `ix-rss`, `majf`, `max-rss`, `minf`, `mrcv`, `msnd`, `nsig`, `nswp`, `volcsw`, `outb`, `util%` and `wallclock`. For complete documentation of the meaning of these data values, see [`Telemetry::Instrument::Usage`](/type/Telemetry/Instrument/Usage).
  
  * Telemetry::Instrument::Thread
  
  Provides (in alphabetical order): `tad`, `tcd`, `thid`, `tjd`, `tsd` and `tys`. For complete documentation of the meaning of these data values, see [`Telemetry::Instrument::Thread`](/type/Telemetry/Instrument/Thread).
  
  * Telemetry::Instrument::ThreadPool
  
  Provides (in alphabetical order): `atc`, `atq`, `aw`, `gtc`, `gtq`, `gw`, `s`, `ttc`, `ttq` and `tw`. For complete documentation of the meaning of these data values, see [`Telemetry::Instrument::ThreadPool`](/type/Telemetry/Instrument/ThreadPool).
  
  * Telemetry::Instrument::AdHoc
  
  Does not provide any data by itself: one must indicate which variables are to be monitored, which will then become available as methods with the same name on the instrument.
  
  ## [routine T](#class_Telemetry "go to top of document")[§](#routine_T "direct link")
  
  ```raku
  sub T()
  ```
  
  Shortcut for `Telemetry.new`. It is exported by default. Since the `Telemetry` class also provides an [`Associative`](/type/Associative) interface, one can easily interpolate multiple values in a single statement:
  
  ```raku
  use Telemetry;
  say "Used {T<max-rss cpu>} (KiB CPU) so far";
  
  ```
  
  ## [routine snap](#class_Telemetry "go to top of document")[§](#routine_snap "direct link")
  
  ```raku
  multi snap(--> Nil)
  multi snap(Str:D $message --> Nil)
  multi snap(Str $message = "taking heap snapshot...", :$heap!)
  multi snap(@s --> Nil)
  ```
  
  The `snap` subroutine is shorthand for creating a new `Telemetry` object and pushing it to an array for later processing. It is exported by default. From release 2021.12, it returns the filename it's storing the snapshots in the case it's provided with a `:$heap` associative parameter.
  
  ```raku
  use Telemetry;
  my @t;
  for ^5 {
      snap(@t);
      # do some stuff
      LAST snap(@t);
  }
  
  ```
  
  If no array is specified, it will use an internal array for convenience.
  
  ## [routine snapper](#class_Telemetry "go to top of document")[§](#routine_snapper "direct link")
  
  ```raku
  sub snapper($sleep = 0.1, :$stop, :$reset --> Nil)
  ```
  
  The `snapper` routine starts a separate thread that will call `snap` repeatedly until the end of program. It is exported by default.
  
  By default, it will call `snap` every **0.1** second. The only positional parameter is taken to be the delay between `snap`s.
  
  Please see the [snapper module](#module_snapper) for externally starting a snapper without having to change the code. Simply adding `-Msnapper` as a command line parameter, will then start a snapper for you.
  
  ## [routine periods](#class_Telemetry "go to top of document")[§](#routine_periods "direct link")
  
  ```raku
  multi periods( --> Seq)
  multi periods(@s --> Seq)
  ```
  
  The `periods` subroutine processes an array of `Telemetry` objects and generates a [`Seq`](/type/Seq) of [`Telemetry::Period`](/type/Telemetry/Period) objects out of that. It is exported by default.
  
  ```raku
  .<cpu wallclock>.say for periods(@t);
  
  # OUTPUT:
  # ====================
  # (164 / 160)
  # (23 / 21)
  # (17 / 17)
  # (15 / 16)
  # (29 / 28)
  
  ```
  
  If no array is specified, it will use the internal array of `snap` without parameters **and** will reset that array upon completion (so that new `snap`s can be added again).
  
  ```raku
  use Telemetry;
  for ^5 {
      snap;
      LAST snap;
  }
  say .<cpu wallclock>.join(" / ") for periods;
  
  # OUTPUT:
  # ====================
  # 172 / 168
  # 24 / 21
  # 17 / 18
  # 17 / 16
  # 27 / 27
  
  ```
  
  If only one `snap` was done, another `snap` will be done to create at least one [`Telemetry::Period`](/type/Telemetry/Period) object.
  
  ## [routine report](#class_Telemetry "go to top of document")[§](#routine_report "direct link")
  
  ```raku
  multi report(:@columns, :$legend, :$header-repeat, :$csv, :@format)
  ```
  
  The `report` subroutine generates a report about an array of `Telemetry` objects. It is exported by default. These can have been created by regularly calling `snap`, or by having a [snapper](/routine/snapper) running. If no positional parameter is used, it will assume the internal array to which the parameterless `snap` pushes.
  
  Below are the additional named parameters of `report`.
  
  * `:columns`
  
  Specify the names of the columns to be included in the report. Names can be specified with the column name (e.g. `gw`). If not specified, defaults to what is specified in the `RAKUDO_REPORT_COLUMNS` environment variable. If that is not set either, defaults to:
  
  ｢text｣ without highlighting
  
  ```
  
  
  ```
  
  wallclock util% max-rss gw gtc tw ttc aw atc
  
  
  ```
  
  
  ```
  
  * `:header-repeat`
  
  Specifies after how many lines the header should be repeated in the report. If not specified, defaults to what is specified in the `RAKUDO_REPORT_HEADER_REPEAT` environment variable. If that is not set either, defaults to 32.
  
  * `:legend`
  
  Specifies whether a legend should be added to the report. If not specified, defaults to what is specified in the `RAKUDO_REPORT_LEGEND` environment variable. If that is not set either, defaults to True.
  
  If there are `snap`s available in the internal array at the end of the program, then `report` will be automatically generated and printed on `STDERR`.
  
  ## [module snapper](#class_Telemetry "go to top of document")[§](#module_snapper "direct link")
  
  Start a thread taking repeated system state snapshots.
  
  This module contains no subroutines or methods or anything. It is intended as a shortcut for starting the [snapper](/routine/snapper) subroutine of the `Telemetry` module, allowing taking snapshots of the execution of a program without needing to change the program. Simple loading the module with `-Msnapper` will do all that is needed to start the snapper, and have a report printed on STDERR upon completion of the program.
  
  The `RAKUDO_SNAPPER` environment variable can be set to indicate the time between snapshots. If not specified, it will default to **0.1** seconds.
  
  The `snapper` module assumes an orderly shutdown of the process. Killing the process (for instance by pressing Control-c) will **not** produce a report.
  
  ## [module safe-snapper](#class_Telemetry "go to top of document")[§](#module_safe-snapper "direct link")
  
  Available as of the 2021.09 release of the Rakudo compiler.
  
  This module provides a safe alternative to the `snapper` module: killing a process by pressing Control-c **will** produce a report. It is able to do so by installing a [signal handler](/type/Supply#sub_signal), which **may** interfere with normal functioning of interactive programs.
  
  Killing a process in any other way, will **not** produce a report.
  
  # [Typegraph](# "go to top of document")[§](#typegraphrelations "direct link")
  
  Type relations for `Telemetry`
  
  
  
  raku-type-graph
  
  
  
  Telemetry
  Telemetry
  
  
  Any
  Any
  
  
  Telemetry->Any
  
  
  
  Mu
  Mu
  
  
  Any->Mu
  
  
  
  Associative
  Associative
  
  
  Telemetry::Period
  Telemetry::Period
  
  
  Telemetry::Period->Telemetry
  
  
  
  Telemetry::Period->Associative
  
  [Expand chart above](/assets/typegraphs/Telemetry.svg)
  