Skip to main content
Pigweed's logo Pigweed
code_xml
  1. Home
  2. Reference
  3. C/C++
  4. Observability
  5. pw_metric
Loading...
Searching...
No Matches
pw_metric

Overview

Classes

class  pw::metric::UntypedMetric
 
class  pw::metric::TypedMetric< T >
 
class  pw::metric::TypedMetric< float >
 
class  pw::metric::TypedMetric< uint32_t >
 
struct  pw::metric::TokenValue
 
class  pw::metric::TypedMetric< bool >
 A metric for bool values. More...
 
class  pw::metric::TypedMetric< int32_t >
 A metric for int32_t values. More...
 
class  pw::metric::TypedMetric< TokenValue >
 A metric for TokenValue values. More...
 
class  pw::metric::Group
 
class  pw::metric::TypedMetric< uint64_t >
 A metric for uint64_t values. More...
 
class  pw::metric::TypedMetric< int64_t >
 A metric for int64_t values. More...
 
class  pw::metric::TypedMetric< double >
 

Macros

#define PW_METRIC_CONFIG_ENABLE_64BIT   1
 
#define PW_METRIC_GLOBAL(variable_name, metric_name, init)
 
#define PW_METRIC_GLOBAL_TYPED(variable_name, metric_name, type, init)
 
#define PW_METRIC_GROUP_GLOBAL(variable_name, group_name)
 
#define _PW_METRIC_TOKEN_MASK   0x0fffffff
 
#define PW_METRIC(...)   PW_DELEGATE_BY_ARG_COUNT(_PW_METRIC_, , __VA_ARGS__)
 
#define PW_METRIC_STATIC(...)    PW_DELEGATE_BY_ARG_COUNT(_PW_METRIC_STATIC_, static, __VA_ARGS__)
 
#define _PW_METRIC_FLOAT_OR_UINT32(literal)
 
#define PW_METRIC_TYPED(...)    PW_DELEGATE_BY_ARG_COUNT(_PW_METRIC_TYPED_, , __VA_ARGS__)
 
#define PW_METRIC_TYPED_STATIC(...)    PW_DELEGATE_BY_ARG_COUNT(_PW_METRIC_TYPED_STATIC_, static, __VA_ARGS__)
 
#define PW_METRIC_TOKEN(metric_name)    PW_TOKENIZE_STRING_MASK("metrics", _PW_METRIC_TOKEN_MASK, metric_name)
 
#define _PW_METRIC_4(static_def, variable_name, metric_name, init)
 
#define _PW_METRIC_5(static_def, group, variable_name, metric_name, init)
 
#define _PW_METRIC_STATIC_4(static_def, variable_name, metric_name, init)
 
#define _PW_METRIC_STATIC_5( static_def, group, variable_name, metric_name, init)
 
#define _PW_METRIC_TYPED_5(static_def, variable_name, metric_name, type, init)
 
#define _PW_METRIC_TYPED_6( static_def, group, variable_name, metric_name, type, init)
 
#define _PW_METRIC_TYPED_STATIC_5( static_def, variable_name, metric_name, type, init)
 
#define _PW_METRIC_TYPED_STATIC_6( static_def, group, variable_name, metric_name, type, init)
 
#define PW_METRIC_GROUP(...)    PW_DELEGATE_BY_ARG_COUNT(_PW_METRIC_GROUP_, , __VA_ARGS__)
 
#define PW_METRIC_GROUP_STATIC(...)    PW_DELEGATE_BY_ARG_COUNT(_PW_METRIC_GROUP_STATIC_, static, __VA_ARGS__)
 
#define _PW_METRIC_GROUP_3(static_def, variable_name, group_name)
 
#define _PW_METRIC_GROUP_4(static_def, parent, variable_name, group_name)
 
#define _PW_METRIC_GROUP_STATIC_3(static_def, variable_name, group_name)
 
#define _PW_METRIC_GROUP_STATIC_4( static_def, parent, variable_name, group_name)
 
#define PW_METRIC_TOKEN_EXPR(metric_name)    PW_TOKENIZE_STRING_MASK_EXPR("metrics", _PW_METRIC_TOKEN_MASK, metric_name)
 

Typedefs

using pw::metric::MetricList = internal::ListWrapper< UntypedMetric >
 A list of metrics.
 
using pw::metric::GroupList = internal::ListWrapper< Group >
 A list of metrics groups.
 
using pw::metric::Metric = UntypedMetric
 Backward compatibility alias.
 

Variables

GroupList pw::metric::global_groups
 Global list of registered metric groups.
 
MetricList pw::metric::global_metrics
 Global list of registered metrics.
 

Macro Definition Documentation

◆ _PW_METRIC_4

#define _PW_METRIC_4 (   static_def,
  variable_name,
  metric_name,
  init 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_METRIC_TOKEN(metric_name); \
static_def::pw::metric::TypedMetric<_PW_METRIC_FLOAT_OR_UINT32(init)> \
variable_name = {variable_name##_token, init}

◆ _PW_METRIC_5

#define _PW_METRIC_5 (   static_def,
  group,
  variable_name,
  metric_name,
  init 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_METRIC_TOKEN(metric_name); \
static_def::pw::metric::TypedMetric<_PW_METRIC_FLOAT_OR_UINT32(init)> \
variable_name = {variable_name##_token, init, group.metrics()}

◆ _PW_METRIC_FLOAT_OR_UINT32

#define _PW_METRIC_FLOAT_OR_UINT32 (   literal)
Value:
std::conditional_t<std::is_floating_point_v<decltype(literal)>, \
float, \
uint32_t>

◆ _PW_METRIC_GROUP_3

#define _PW_METRIC_GROUP_3 (   static_def,
  variable_name,
  group_name 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_TOKENIZE_STRING_DOMAIN("metrics", group_name); \
static_def::pw::metric::Group variable_name = {variable_name##_token}

◆ _PW_METRIC_GROUP_4

#define _PW_METRIC_GROUP_4 (   static_def,
  parent,
  variable_name,
  group_name 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_TOKENIZE_STRING_DOMAIN("metrics", group_name); \
static_def::pw::metric::Group variable_name = {variable_name##_token, \
parent.children()}

◆ _PW_METRIC_GROUP_STATIC_3

#define _PW_METRIC_GROUP_STATIC_3 (   static_def,
  variable_name,
  group_name 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_TOKENIZE_STRING_DOMAIN("metrics", group_name); \
static_def::pw::NoDestructor<::pw::metric::Group> variable_name##_storage( \
variable_name##_token); \
static_def::pw::metric::Group& variable_name [[maybe_unused]] = \
*variable_name##_storage

◆ _PW_METRIC_GROUP_STATIC_4

#define _PW_METRIC_GROUP_STATIC_4 (   static_def,
  parent,
  variable_name,
  group_name 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_TOKENIZE_STRING_DOMAIN("metrics", group_name); \
static_def::pw::NoDestructor<::pw::metric::Group> variable_name##_storage( \
variable_name##_token, parent.children()); \
static_def::pw::metric::Group& variable_name [[maybe_unused]] = \
*variable_name##_storage

◆ _PW_METRIC_STATIC_4

#define _PW_METRIC_STATIC_4 (   static_def,
  variable_name,
  metric_name,
  init 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_METRIC_TOKEN(metric_name); \
static_def::pw::NoDestructor< \
::pw::metric::TypedMetric<_PW_METRIC_FLOAT_OR_UINT32(init)>> \
variable_name##_storage(variable_name##_token, init); \
static_def::pw::metric::TypedMetric<_PW_METRIC_FLOAT_OR_UINT32(init)>& \
variable_name [[maybe_unused]] = *variable_name##_storage
Definition: metric.h:190

◆ _PW_METRIC_STATIC_5

#define _PW_METRIC_STATIC_5 (   static_def,
  group,
  variable_name,
  metric_name,
  init 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_METRIC_TOKEN(metric_name); \
static_def::pw::NoDestructor< \
::pw::metric::TypedMetric<_PW_METRIC_FLOAT_OR_UINT32(init)>> \
variable_name##_storage(variable_name##_token, init, group.metrics()); \
static_def::pw::metric::TypedMetric<_PW_METRIC_FLOAT_OR_UINT32(init)>& \
variable_name [[maybe_unused]] = *variable_name##_storage

◆ _PW_METRIC_TYPED_5

#define _PW_METRIC_TYPED_5 (   static_def,
  variable_name,
  metric_name,
  type,
  init 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_METRIC_TOKEN(metric_name); \
static_def::pw::metric::TypedMetric<type> variable_name = { \
variable_name##_token, init}

◆ _PW_METRIC_TYPED_6

#define _PW_METRIC_TYPED_6 (   static_def,
  group,
  variable_name,
  metric_name,
  type,
  init 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_METRIC_TOKEN(metric_name); \
static_def::pw::metric::TypedMetric<type> variable_name = { \
variable_name##_token, init, group.metrics()}

◆ _PW_METRIC_TYPED_STATIC_5

#define _PW_METRIC_TYPED_STATIC_5 (   static_def,
  variable_name,
  metric_name,
  type,
  init 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_METRIC_TOKEN(metric_name); \
static_def::pw::NoDestructor<::pw::metric::TypedMetric<type>> \
variable_name##_storage(variable_name##_token, init); \
static_def::pw::metric::TypedMetric<type>& variable_name [[maybe_unused]] = \
*variable_name##_storage

◆ _PW_METRIC_TYPED_STATIC_6

#define _PW_METRIC_TYPED_STATIC_6 (   static_def,
  group,
  variable_name,
  metric_name,
  type,
  init 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_METRIC_TOKEN(metric_name); \
static_def::pw::NoDestructor<::pw::metric::TypedMetric<type>> \
variable_name##_storage(variable_name##_token, init, group.metrics()); \
static_def::pw::metric::TypedMetric<type>& variable_name [[maybe_unused]] = \
*variable_name##_storage

◆ PW_METRIC

#define PW_METRIC (   ...)    PW_DELEGATE_BY_ARG_COUNT(_PW_METRIC_, , __VA_ARGS__)

Declare a metric, optionally adding it to a group.

Overloads:

  • PW_METRIC(variable_name, metric_name, value)
  • PW_METRIC(group, variable_name, metric_name, value)
  • variable_name - An identifier name for the created variable or member. For example: i2c_transactions might be used as a local or global metric; inside a class, could be named according to members (i2c_transactions_ for Google's C++ style).
  • metric_name - The string name for the metric. This will be tokenized. There are no restrictions on the contents of the name; however, consider restricting these to be valid C++ identifiers to ease integration with other systems.
  • value - The initial value for the metric. Must be either a floating point value (e.g. 3.2f) or unsigned int (e.g. 21u).
  • group - A pw::metric::Group instance. If provided, the metric is added to the given group.

The macro declares a variable or member named variable_name with type pw::metric::TypedMetric<T>, and works in three contexts: global, local, and member.

  1. At global scope:
    PW_METRIC(foo, "foo", 15.5f);
    void MyFunc() { foo.Increment(); }
    #define PW_METRIC(...)
    Definition: metric.h:464
  2. At local function or member function scope:
    void MyFunc() {
    PW_METRIC(foo, "foo", 15.5f);
    foo.Increment();
    // foo goes out of scope here; be careful!
    }
  3. At member level inside a class or struct:
    struct MyStructy {
    void DoSomething() { somethings_.Increment(); }
    // Every instance of MyStructy will have a separate somethings counter.
    PW_METRIC(somethings_, "somethings", 0u);
    };

You can also put a metric into a group with the macro. Metrics can belong to strictly one group, otherwise an assertion will fail. Example:

PW_METRIC_GROUP(my_group, "my_group_name_here");
PW_METRIC(my_group, foo_, "foo", 0.2f);
PW_METRIC(my_group, bar_, "bar", 44000u);
PW_METRIC(my_group, zap_, "zap", 3.14f);
#define PW_METRIC_GROUP(...)
Definition: metric.h:618
Note
If you want a globally registered metric, see pw_metric/global.h; in that context, metrics are globally registered without the need to centrally register in a single place.

◆ PW_METRIC_CONFIG_ENABLE_64BIT

#define PW_METRIC_CONFIG_ENABLE_64BIT   1

Control whether 64-bit metrics are enabled.

By default, 64-bit metrics are enabled automatically on 64-bit host platforms (e.g. x86_64, AArch64). On 32-bit target platforms (e.g. ARM Cortex-M), 64-bit metrics are disabled by default to prevent linker errors for atomic libcalls (__atomic_load_8).

Downstream projects targeting 32-bit platforms can opt-in to 64-bit metrics by defining PW_METRIC_CONFIG_ENABLE_64BIT=1 and linking the appropriate atomic helper library (e.g. @pigweed//pw_atomic:cortex_m_64bit_atomics).

◆ PW_METRIC_GLOBAL

#define PW_METRIC_GLOBAL (   variable_name,
  metric_name,
  init 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_METRIC_TOKEN(metric_name); \
::pw::metric::TypedMetric<_PW_METRIC_FLOAT_OR_UINT32(init)>> \
variable_name##_storage{ \
variable_name##_token, init, ::pw::metric::global_metrics}; \
::pw::metric::TypedMetric<_PW_METRIC_FLOAT_OR_UINT32(init)>& variable_name \
[[maybe_unused]] = *variable_name##_storage
Definition: no_destructor.h:77
MetricList global_metrics
Global list of registered metrics.

Declare a pw::metric::TypedMetric<T> with name metric_name, and register it in the global metrics list pw::metric::global_metrics.

This is useful for cases where uncoordinated instrumentation with metrics is needed; for example, when instrumenting legacy code where plumbing a metric group around by dependency injection is infeasible.

Example:

#include "pw_metric/global.h"
#include "pw_metric/metric.h"
// No need to coordinate collection of foo and bar; they're autoregistered.
PW_METRIC_GLOBAL(foo, "foo", 0.2f);
PW_METRIC_GLOBAL(bar, "bar", 44000u);
#define PW_METRIC_GLOBAL(variable_name, metric_name, init)
Definition: global.h:58

Note that metrics defined with PW_METRIC_GLOBAL should never be added to groups defined with PW_METRIC_GROUP_GLOBAL. Each metric can only belong to one group, and metrics defined with PW_METRIC_GLOBAL are pre-registered with the global metrics list.

Warning
Do not create PW_METRIC_GLOBAL instances anywhere other than global scope. Putting these on an instance (member context) would lead to dangling pointers and misery. Metrics are never deleted or unregistered!

◆ PW_METRIC_GLOBAL_TYPED

#define PW_METRIC_GLOBAL_TYPED (   variable_name,
  metric_name,
  type,
  init 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_METRIC_TOKEN(metric_name); \
variable_name##_token, init, ::pw::metric::global_metrics}; \
::pw::metric::TypedMetric<type>& variable_name [[maybe_unused]] = \
*variable_name##_storage

Declare a pw::metric::TypedMetric<T> with name metric_name and explicit type type, and register it in the global metrics list pw::metric::global_metrics.

This macro works identically to PW_METRIC_GLOBAL, but requires explicitly specifying the metric type (e.g. float, uint32_t, or uint64_t).

Example:

#include "pw_metric/global.h"
#include "pw_metric/metric.h"
PW_METRIC_GLOBAL_TYPED(my_global_64bit, "my_global_64bit", uint64_t, 0ULL);
#define PW_METRIC_GLOBAL_TYPED(variable_name, metric_name, type, init)
Definition: global.h:82

◆ PW_METRIC_GROUP

#define PW_METRIC_GROUP (   ...)     PW_DELEGATE_BY_ARG_COUNT(_PW_METRIC_GROUP_, , __VA_ARGS__)

Declares a pw::metric::Group with name group_name; the name is tokenized. Works similar to PW_METRIC and can be used in the same contexts (global, local, and member). Optionally, the group can be added to a parent group.

Overloads:

Example:

class MySubsystem {
public:
void DoSomething() {
attempts_.Increment();
if (ActionSucceeds()) {
successes_.Increment();
}
}
const Group& metrics() const { return metrics_; }
Group& metrics() { return metrics_; }
private:
PW_METRIC_GROUP(metrics_, "my_subsystem");
PW_METRIC(metrics_, attempts_, "attempts", 0u);
PW_METRIC(metrics_, successes_, "successes", 0u);
};

◆ PW_METRIC_GROUP_GLOBAL

#define PW_METRIC_GROUP_GLOBAL (   variable_name,
  group_name 
)
Value:
static constexpr uint32_t variable_name##_token = \
PW_TOKENIZE_STRING_DOMAIN("metrics", group_name); \
::pw::NoDestructor<::pw::metric::Group> variable_name##_storage{ \
variable_name##_token, ::pw::metric::global_groups}; \
::pw::metric::Group& variable_name [[maybe_unused]] = *variable_name##_storage
Definition: metric.h:334
GroupList global_groups
Global list of registered metric groups.

Declare a pw::metric::Group with name group_name, and register it in the global metric groups list pw::metric::global_groups.

Note that metrics created with PW_METRIC_GLOBAL should never be added to groups! Instead, just create a freestanding metric and register it into the global group (like in the example below).

Example:

#include "pw_metric/global.h"
#include "pw_metric/metric.h"
// No need to coordinate collection of this group; it's globally registered.
PW_METRIC_GROUP_GLOBAL(legacy_system, "legacy_system");
PW_METRIC(legacy_system, foo, "foo", 0.2f);
PW_METRIC(legacy_system, bar, "bar", 44000u);
#define PW_METRIC_GROUP_GLOBAL(variable_name, group_name)
Definition: global.h:111
Warning
Do not create PW_METRIC_GROUP_GLOBAL instances anywhere other than global scope. Putting these on an instance (member context) would lead to dangling pointers and misery. Metrics are never deleted or unregistered!

◆ PW_METRIC_GROUP_STATIC

#define PW_METRIC_GROUP_STATIC (   ...)     PW_DELEGATE_BY_ARG_COUNT(_PW_METRIC_GROUP_STATIC_, static, __VA_ARGS__)

Declares a PW_METRIC_GROUP variable with static storage. These can be used in function scopes, but not in classes.

Overloads:

◆ PW_METRIC_STATIC

#define PW_METRIC_STATIC (   ...)     PW_DELEGATE_BY_ARG_COUNT(_PW_METRIC_STATIC_, static, __VA_ARGS__)

Declares a PW_METRIC variable with static storage. These can be used in function scopes, but not in classes.

Overloads:

◆ PW_METRIC_TOKEN

#define PW_METRIC_TOKEN (   metric_name)     PW_TOKENIZE_STRING_MASK("metrics", _PW_METRIC_TOKEN_MASK, metric_name)

Declare a pw::metric::Token (pw::tokenizer::Token) for a metric with name metric_name. This token matches the .name() of a metric with the same name.

This is a wrapper around PW_TOKENIZE_STRING_MASK and carries the same semantics.

This is unlikely to be used by most pw_metric consumers.

◆ PW_METRIC_TOKEN_EXPR

#define PW_METRIC_TOKEN_EXPR (   metric_name)     PW_TOKENIZE_STRING_MASK_EXPR("metrics", _PW_METRIC_TOKEN_MASK, metric_name)

Similar to PW_TOKENIZE_STRING_EXPR, converts a string literal to a uint32_t token within an expression. Requires C++.

// Tokenizes a string literal in the metric domain within an expression.
DoSomethingWithToken(PW_METRIC_TOKEN_EXPR("Succeed"));
#define PW_METRIC_TOKEN_EXPR(metric_name)
Definition: metric.h:665

◆ PW_METRIC_TYPED

#define PW_METRIC_TYPED (   ...)     PW_DELEGATE_BY_ARG_COUNT(_PW_METRIC_TYPED_, , __VA_ARGS__)

Declare a metric with an explicit type, optionally adding it to a group.

Overloads:

This macro works identically to PW_METRIC, but requires explicitly specifying the metric type (e.g. float, uint32_t, or uint64_t). This is useful for declaring 64-bit metrics or when you want to make the metric's type explicit.

Example:

PW_METRIC_GROUP(my_group, "my_group");
PW_METRIC_TYPED(my_group, my_64bit_metric, "my_64bit_metric", uint64_t,
0ULL);
#define PW_METRIC_TYPED(...)
Definition: metric.h:497

◆ PW_METRIC_TYPED_STATIC

#define PW_METRIC_TYPED_STATIC (   ...)     PW_DELEGATE_BY_ARG_COUNT(_PW_METRIC_TYPED_STATIC_, static, __VA_ARGS__)

Declares a PW_METRIC_TYPED variable with static storage. These can be used in function scopes, but not in classes.

Overloads: