Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
f20b13b0
Commit
f20b13b0
authored
Jun 12, 2020
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revise the metric family API
parent
6b1bd132
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
166 additions
and
182 deletions
+166
-182
libcaf_core/caf/telemetry/collector/prometheus.hpp
libcaf_core/caf/telemetry/collector/prometheus.hpp
+2
-1
libcaf_core/caf/telemetry/int_gauge.hpp
libcaf_core/caf/telemetry/int_gauge.hpp
+8
-4
libcaf_core/caf/telemetry/metric_family.hpp
libcaf_core/caf/telemetry/metric_family.hpp
+2
-0
libcaf_core/caf/telemetry/metric_family_impl.hpp
libcaf_core/caf/telemetry/metric_family_impl.hpp
+19
-9
libcaf_core/caf/telemetry/metric_registry.hpp
libcaf_core/caf/telemetry/metric_registry.hpp
+49
-41
libcaf_core/src/actor_registry.cpp
libcaf_core/src/actor_registry.cpp
+1
-1
libcaf_core/src/telemetry/metric_registry.cpp
libcaf_core/src/telemetry/metric_registry.cpp
+25
-64
libcaf_core/test/telemetry/collector/prometheus.cpp
libcaf_core/test/telemetry/collector/prometheus.cpp
+13
-12
libcaf_core/test/telemetry/int_gauge.cpp
libcaf_core/test/telemetry/int_gauge.cpp
+4
-4
libcaf_core/test/telemetry/metric_registry.cpp
libcaf_core/test/telemetry/metric_registry.cpp
+43
-46
No files found.
libcaf_core/caf/telemetry/collector/prometheus.hpp
View file @
f20b13b0
...
...
@@ -22,6 +22,7 @@
#include <unordered_map>
#include <vector>
#include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp"
#include "caf/string_view.hpp"
...
...
@@ -29,7 +30,7 @@ namespace caf::telemetry::collector {
/// Collects system metrics and exports them to the text-based Prometheus
/// format. For a documentation of the format, see: https://git.io/fjgDD.
class
prometheus
{
class
CAF_CORE_EXPORT
prometheus
{
public:
// -- member types -----------------------------------------------------------
...
...
libcaf_core/caf/telemetry/int_gauge.hpp
View file @
f20b13b0
...
...
@@ -23,12 +23,16 @@
#include <atomic>
#include <cstdint>
#include "caf/telemetry/metric_type.hpp"
namespace
caf
::
telemetry
{
/// A metric that represents a single integer value that can arbitrarily go up
/// and down.
class
CAF_CORE_EXPORT
int_gauge
{
public:
static
constexpr
metric_type
runtime_type
=
metric_type
::
int_gauge
;
int_gauge
()
noexcept
:
value_
(
0
)
{
// nop
}
...
...
@@ -38,22 +42,22 @@ public:
}
/// Increments the gauge by 1.
void
inc
rement
()
noexcept
{
void
inc
()
noexcept
{
++
value_
;
}
/// Increments the gauge by `amount`.
void
inc
rement
(
int64_t
amount
)
noexcept
{
void
inc
(
int64_t
amount
)
noexcept
{
value_
.
fetch_add
(
amount
);
}
/// Decrements the gauge by 1.
void
dec
rement
()
noexcept
{
void
dec
()
noexcept
{
--
value_
;
}
/// Decrements the gauge by `amount`.
void
dec
rement
(
int64_t
amount
)
noexcept
{
void
dec
(
int64_t
amount
)
noexcept
{
value_
.
fetch_sub
(
amount
);
}
...
...
libcaf_core/caf/telemetry/metric_family.hpp
View file @
f20b13b0
...
...
@@ -77,6 +77,8 @@ public:
return
is_sum_
;
}
virtual
metric_type
type
()
const
noexcept
=
0
;
private:
std
::
string
prefix_
;
std
::
string
name_
;
...
...
libcaf_core/caf/telemetry/metric_family_impl.hpp
View file @
f20b13b0
...
...
@@ -19,9 +19,12 @@
#pragma once
#include <algorithm>
#include <initializer_list>
#include <memory>
#include <mutex>
#include "caf/span.hpp"
#include "caf/string_view.hpp"
#include "caf/telemetry/label.hpp"
#include "caf/telemetry/label_view.hpp"
#include "caf/telemetry/metric.hpp"
...
...
@@ -33,27 +36,34 @@ namespace caf::telemetry {
template
<
class
Type
>
class
metric_family_impl
:
public
metric_family
{
public:
using
metric
_type
=
metric_impl
<
Type
>
;
using
impl
_type
=
metric_impl
<
Type
>
;
using
metric_family
::
metric_family
;
Type
*
get_or_add
(
const
std
::
vector
<
label_view
>&
labels
)
{
auto
has_label_values
=
[
&
labels
](
const
auto
&
metric_ptr
)
{
metric_type
type
()
const
noexcept
override
{
return
Type
::
runtime_type
;
}
Type
*
get_or_add
(
span
<
const
label_view
>
labels
)
{
auto
has_label_values
=
[
labels
](
const
auto
&
metric_ptr
)
{
const
auto
&
metric_labels
=
metric_ptr
->
labels
();
for
(
size_t
index
=
0
;
index
<
labels
.
size
();
++
index
)
if
(
labels
[
index
].
value
()
!=
metric_labels
[
index
].
value
())
return
false
;
return
true
;
return
std
::
is_permutation
(
metric_labels
.
begin
(),
metric_labels
.
end
(),
labels
.
begin
(),
labels
.
end
());
};
std
::
unique_lock
<
std
::
mutex
>
guard
{
mx_
};
auto
m
=
std
::
find_if
(
metrics_
.
begin
(),
metrics_
.
end
(),
has_label_values
);
if
(
m
==
metrics_
.
end
())
{
std
::
vector
<
label
>
cpy
{
labels
.
begin
(),
labels
.
end
()};
m
=
metrics_
.
emplace
(
m
,
std
::
make_unique
<
metric_type
>
(
std
::
move
(
cpy
)));
std
::
sort
(
cpy
.
begin
(),
cpy
.
end
());
m
=
metrics_
.
emplace
(
m
,
std
::
make_unique
<
impl_type
>
(
std
::
move
(
cpy
)));
}
return
std
::
addressof
(
m
->
get
()
->
impl
());
}
Type
*
get_or_add
(
std
::
initializer_list
<
label_view
>
labels
)
{
return
get_or_add
(
span
<
const
label_view
>
{
labels
.
begin
(),
labels
.
size
()});
}
template
<
class
Collector
>
void
collect
(
Collector
&
collector
)
const
{
std
::
unique_lock
<
std
::
mutex
>
guard
{
mx_
};
...
...
@@ -63,7 +73,7 @@ public:
private:
mutable
std
::
mutex
mx_
;
std
::
vector
<
std
::
unique_ptr
<
metric
_type
>>
metrics_
;
std
::
vector
<
std
::
unique_ptr
<
impl
_type
>>
metrics_
;
};
}
// namespace caf::telemetry
libcaf_core/caf/telemetry/metric_registry.hpp
View file @
f20b13b0
...
...
@@ -18,6 +18,7 @@
#pragma once
#include <initializer_list>
#include <map>
#include <memory>
#include <mutex>
...
...
@@ -42,26 +43,8 @@ public:
~
metric_registry
();
/// Adds a new metric family to the registry.
/// @param type The kind of the metric, e.g. gauge or count.
/// @param prefix The prefix (namespace) this family belongs to. Usually the
/// application or protocol name, e.g., `http`. The prefix `caf`
/// as well as prefixes starting with an underscore are
/// reserved.
/// @param name The human-readable name of the metric, e.g., `requests`.
/// @param label_names Names for all label dimensions of the metric.
/// @param helptext Short explanation of the metric.
/// @param unit Unit of measurement. Please use base units such as `bytes` or
/// `seconds` (prefer lowercase). The pseudo-unit `1` identifies
/// dimensionless counts.
/// @param is_sum Setting this to `true` indicates that this metric adds
/// something up to a total, where only the total value is of
/// interest. For example, the total number of HTTP requests.
void
add_family
(
metric_type
type
,
std
::
string
prefix
,
std
::
string
name
,
std
::
vector
<
std
::
string
>
label_names
,
std
::
string
helptext
,
std
::
string
unit
=
"1"
,
bool
is_sum
=
false
);
/// Adds a new metric family to the registry.
/// Returns a metric family. Creates the family lazily if necessary, but fails
/// if the full name already belongs to a different family.
/// @param prefix The prefix (namespace) this family belongs to. Usually the
/// application or protocol name, e.g., `http`. The prefix `caf`
/// as well as prefixes starting with an underscore are
...
...
@@ -76,25 +59,40 @@ public:
/// something up to a total, where only the total value is of
/// interest. For example, the total number of HTTP requests.
template
<
class
Type
>
metric_family_impl
<
Type
>*
add_family
(
std
::
string
prefix
,
std
::
string
name
,
std
::
vector
<
std
::
string
>
label_names
,
std
::
string
helptext
,
std
::
string
unit
=
"1"
,
bool
is_sum
=
false
)
{
metric_family_impl
<
Type
>*
family
(
string_view
prefix
,
string_view
name
,
span
<
const
string_view
>
label_names
,
string_view
helptext
,
string_view
unit
=
"1"
,
bool
is_sum
=
false
)
{
using
family_type
=
metric_family_impl
<
Type
>
;
std
::
sort
(
label_names
.
begin
(),
label_names
.
end
());
auto
ptr
=
std
::
make_unique
<
family_type
>
(
std
::
move
(
prefix
),
std
::
move
(
name
),
std
::
move
(
label_names
),
std
::
move
(
helptext
),
std
::
move
(
unit
),
is_sum
);
std
::
unique_lock
<
std
::
mutex
>
guard
{
families_mx_
};
assert_unregistered
(
ptr
->
prefix
(),
ptr
->
name
());
if
(
auto
ptr
=
fetch
(
prefix
,
name
))
{
assert_properties
(
ptr
,
Type
::
runtime_type
,
label_names
,
unit
,
is_sum
);
return
static_cast
<
family_type
*>
(
ptr
);
}
auto
ptr
=
std
::
make_unique
<
family_type
>
(
to_string
(
prefix
),
to_string
(
name
),
to_sorted_vec
(
label_names
),
to_string
(
helptext
),
to_string
(
unit
),
is_sum
);
auto
&
families
=
container_by_type
<
Type
>
();
families
.
emplace_back
(
std
::
move
(
ptr
));
return
families
.
back
().
get
();
}
/// Adds a new metric singleton, i.e., a family without label dimensions and
/// thus exactly one metric instance.
/// @copydoc family
template
<
class
Type
>
metric_family_impl
<
Type
>*
family
(
string_view
prefix
,
string_view
name
,
std
::
initializer_list
<
string_view
>
label_names
,
string_view
helptext
,
string_view
unit
=
"1"
,
bool
is_sum
=
false
)
{
return
family
<
Type
>
(
prefix
,
name
,
span
<
const
string_view
>
{
label_names
.
begin
(),
label_names
.
size
()},
helptext
,
unit
,
is_sum
);
}
/// Returns a metric singleton, i.e., the single instance of a family without
/// label dimensions. Creates all objects lazily if necessary, but fails if
/// the full name already belongs to a different family.
/// @param prefix The prefix (namespace) this family belongs to. Usually the
/// application or protocol name, e.g., `http`. The prefix `caf`
/// as well as prefixes starting with an underscore are
...
...
@@ -108,17 +106,12 @@ public:
/// something up to a total, where only the total value is of
/// interest. For example, the total number of HTTP requests.
template
<
class
Type
>
Type
*
add_singleton
(
std
::
string
prefix
,
std
::
string
name
,
std
::
string
helptext
,
std
::
string
unit
=
"1"
,
bool
is_sum
=
false
)
{
auto
fptr
=
add_family
<
Type
>
(
std
::
move
(
prefix
),
std
::
move
(
name
),
{},
std
::
move
(
helptext
),
std
::
move
(
unit
),
is_sum
);
Type
*
singleton
(
string_view
prefix
,
string_view
name
,
string_view
helptext
,
string_view
unit
=
"1"
,
bool
is_sum
=
false
)
{
auto
fptr
=
family
<
Type
>
(
prefix
,
name
,
{},
helptext
,
unit
,
is_sum
);
return
fptr
->
get_or_add
({});
}
telemetry
::
int_gauge
*
int_gauge
(
string_view
prefix
,
string_view
name
,
std
::
vector
<
label_view
>
labels
);
template
<
class
Collector
>
void
collect
(
Collector
&
collector
)
const
{
std
::
unique_lock
<
std
::
mutex
>
guard
{
families_mx_
};
...
...
@@ -128,7 +121,22 @@ public:
private:
/// @pre `families_mx_` is locked.
void
assert_unregistered
(
const
std
::
string
&
prefix
,
const
std
::
string
&
name
);
metric_family
*
fetch
(
const
string_view
&
prefix
,
const
string_view
&
name
);
static
std
::
vector
<
std
::
string
>
to_sorted_vec
(
span
<
const
string_view
>
xs
)
{
std
::
vector
<
std
::
string
>
result
;
if
(
!
xs
.
empty
())
{
result
.
reserve
(
xs
.
size
());
for
(
auto
x
:
xs
)
result
.
emplace_back
(
to_string
(
x
));
std
::
sort
(
result
.
begin
(),
result
.
end
());
}
return
result
;
}
void
assert_properties
(
metric_family
*
ptr
,
metric_type
type
,
span
<
const
string_view
>
label_names
,
string_view
unit
,
bool
is_sum
);
template
<
class
Type
>
metric_family_container
<
Type
>&
container_by_type
();
...
...
libcaf_core/src/actor_registry.cpp
View file @
f20b13b0
...
...
@@ -49,7 +49,7 @@ actor_registry::~actor_registry() {
}
actor_registry
::
actor_registry
(
actor_system
&
sys
)
:
system_
(
sys
)
{
running_
=
sys
.
telemetry
().
add_
singleton
<
telemetry
::
int_gauge
>
(
running_
=
sys
.
telemetry
().
singleton
<
telemetry
::
int_gauge
>
(
"caf"
,
"running_actors"
,
"Number of currently running actors."
);
}
...
...
libcaf_core/src/telemetry/metric_registry.cpp
View file @
f20b13b0
...
...
@@ -35,74 +35,35 @@ metric_registry::~metric_registry() {
// nop
}
telemetry
::
int_gauge
*
metric_registry
::
int_gauge
(
string_view
prefix
,
string_view
name
,
std
::
vector
<
label_view
>
labels
)
{
// Make sure labels are sorted by name.
auto
cmp
=
[](
const
label_view
&
x
,
const
label_view
&
y
)
{
return
x
.
name
()
<
y
.
name
();
};
std
::
sort
(
labels
.
begin
(),
labels
.
end
(),
cmp
);
// Fetch the family.
auto
matches
=
[
&
](
const
auto
&
family
)
{
auto
lbl_cmp
=
[](
const
label_view
&
lbl
,
string_view
name
)
{
return
lbl
.
name
()
==
name
;
};
return
family
->
prefix
()
==
prefix
&&
family
->
name
()
==
name
&&
std
::
equal
(
labels
.
begin
(),
labels
.
end
(),
family
->
label_names
().
begin
(),
family
->
label_names
().
end
(),
lbl_cmp
);
metric_family
*
metric_registry
::
fetch
(
const
string_view
&
prefix
,
const
string_view
&
name
)
{
auto
matches
=
[
&
](
const
auto
&
ptr
)
{
return
ptr
->
prefix
()
==
prefix
&&
ptr
->
name
()
==
name
;
};
using
family_type
=
metric_family_impl
<
telemetry
::
int_gauge
>
;
family_type
*
fptr
;
{
std
::
unique_lock
<
std
::
mutex
>
guard
{
families_mx_
};
auto
i
=
std
::
find_if
(
int_gauges_
.
begin
(),
int_gauges_
.
end
(),
matches
);
if
(
i
==
int_gauges_
.
end
())
{
std
::
string
prefix_str
{
prefix
.
begin
(),
prefix
.
end
()};
std
::
string
name_str
{
name
.
begin
(),
name
.
end
()};
assert_unregistered
(
prefix_str
,
name_str
);
std
::
vector
<
std
::
string
>
label_names
;
label_names
.
reserve
(
labels
.
size
());
for
(
auto
&
lbl
:
labels
)
{
auto
lbl_name
=
lbl
.
name
();
label_names
.
emplace_back
(
std
::
string
{
lbl_name
.
begin
(),
lbl_name
.
end
()});
}
auto
ptr
=
std
::
make_unique
<
family_type
>
(
std
::
move
(
prefix_str
),
std
::
move
(
name_str
),
std
::
move
(
label_names
),
""
,
"1"
,
false
);
i
=
int_gauges_
.
emplace
(
i
,
std
::
move
(
ptr
));
}
fptr
=
i
->
get
();
}
return
fptr
->
get_or_add
(
labels
);
if
(
auto
i
=
std
::
find_if
(
int_gauges_
.
begin
(),
int_gauges_
.
end
(),
matches
);
i
!=
int_gauges_
.
end
())
return
i
->
get
();
return
nullptr
;
}
void
metric_registry
::
add_family
(
metric_type
type
,
std
::
string
prefix
,
std
::
string
name
,
std
::
vector
<
std
::
string
>
label_names
,
std
::
string
helptext
,
std
::
string
unit
,
bool
is_sum
)
{
namespace
t
=
caf
::
telemetry
;
switch
(
type
)
{
case
metric_type
:
:
int_gauge
:
add_family
<
t
::
int_gauge
>
(
std
::
move
(
prefix
),
std
::
move
(
name
),
std
::
move
(
label_names
),
std
::
move
(
helptext
),
std
::
move
(
unit
),
is_sum
);
break
;
default:
CAF_RAISE_ERROR
(
"invalid metric type"
);
}
}
void
metric_registry
::
assert_unregistered
(
const
std
::
string
&
prefix
,
const
std
::
string
&
name
)
{
auto
matches
=
[
&
](
const
auto
&
ptr
)
{
return
ptr
->
prefix
()
==
prefix
&&
ptr
->
name
()
==
name
;
void
metric_registry
::
assert_properties
(
metric_family
*
ptr
,
metric_type
type
,
span
<
const
string_view
>
label_names
,
string_view
unit
,
bool
is_sum
)
{
auto
labels_match
=
[
&
]
{
const
auto
&
xs
=
ptr
->
label_names
();
const
auto
&
ys
=
label_names
;
return
std
::
is_sorted
(
ys
.
begin
(),
ys
.
end
())
?
std
::
equal
(
xs
.
begin
(),
xs
.
end
(),
ys
.
begin
(),
ys
.
end
())
:
std
::
is_permutation
(
xs
.
begin
(),
xs
.
end
(),
ys
.
begin
(),
ys
.
end
());
};
if
(
std
::
any_of
(
int_gauges_
.
begin
(),
int_gauges_
.
end
(),
matches
))
CAF_RAISE_ERROR
(
"prefix and name already belong to an int gauge family"
);
if
(
ptr
->
type
()
!=
type
)
CAF_RAISE_ERROR
(
"full name with different metric type found"
);
if
(
!
labels_match
())
CAF_RAISE_ERROR
(
"full name with different label dimensions found"
);
if
(
ptr
->
unit
()
!=
unit
)
CAF_RAISE_ERROR
(
"full name with different unit found"
);
if
(
ptr
->
is_sum
()
!=
is_sum
)
CAF_RAISE_ERROR
(
"full name with different is-sum flag found"
);
}
}
// namespace caf::telemetry
libcaf_core/test/telemetry/collector/prometheus.cpp
View file @
f20b13b0
...
...
@@ -32,6 +32,7 @@ using namespace caf::telemetry;
namespace
{
struct
fixture
{
using
ig
=
int_gauge
;
collector
::
prometheus
exporter
;
metric_registry
registry
;
};
...
...
@@ -41,21 +42,21 @@ struct fixture {
CAF_TEST_FIXTURE_SCOPE
(
prometheus_tests
,
fixture
)
CAF_TEST
(
the
Prometheus
collector
generates
text
output
)
{
registry
.
add_family
(
metric_type
::
int_gauge
,
"foo"
,
"bar"
,
{}
,
"Just some value without labels."
,
"seconds"
);
registry
.
add_family
(
metric_type
::
int_gauge
,
"some"
,
"value"
,
{
"a"
,
"b"
},
"Just some (total) value with two labels."
,
"1"
,
true
);
registry
.
add_family
(
metric_type
::
int_gauge
,
"other"
,
"value"
,
{
"x"
},
""
,
"seconds"
,
true
);
registry
.
int_gauge
(
"foo"
,
"bar"
,
{})
->
value
(
123
);
registry
.
int_gauge
(
"some"
,
"value"
,
{{
"a"
,
"1"
},
{
"b"
,
"2"
}})
->
value
(
12
);
registry
.
int_gauge
(
"some"
,
"value"
,
{{
"b"
,
"1"
},
{
"a"
,
"2"
}})
->
value
(
21
);
registry
.
int_gauge
(
"other"
,
"value"
,
{{
"x"
,
"true"
}})
->
value
(
31337
);
auto
fb
=
registry
.
family
<
ig
>
(
"foo"
,
"bar"
,
{},
"Some value without labels."
,
"seconds"
);
auto
sv
=
registry
.
family
<
ig
>
(
"some"
,
"value"
,
{
"a"
,
"b"
},
"Some (total) value with two labels."
,
"1"
,
true
);
auto
ov
=
registry
.
family
<
ig
>
(
"other"
,
"value"
,
{
"x"
},
""
,
"seconds"
,
true
);
fb
->
get_or_add
(
{})
->
value
(
123
);
sv
->
get_or_add
(
{{
"a"
,
"1"
},
{
"b"
,
"2"
}})
->
value
(
12
);
sv
->
get_or_add
(
{{
"b"
,
"1"
},
{
"a"
,
"2"
}})
->
value
(
21
);
ov
->
get_or_add
(
{{
"x"
,
"true"
}})
->
value
(
31337
);
CAF_CHECK_EQUAL
(
exporter
.
collect_from
(
registry
,
42
),
R"(# HELP foo_bar_seconds
Just s
ome value without labels.
R"(# HELP foo_bar_seconds
S
ome value without labels.
# TYPE foo_bar_seconds gauge
foo_bar_seconds 123 42
# HELP some_value_total
Just s
ome (total) value with two labels.
# HELP some_value_total
S
ome (total) value with two labels.
# TYPE some_value_total gauge
some_value_total{a="1",b="2"} 12 42
some_value_total{a="2",b="1"} 21 42
...
...
libcaf_core/test/telemetry/int_gauge.cpp
View file @
f20b13b0
...
...
@@ -29,12 +29,12 @@ CAF_TEST(integer gauges can increment and decrement) {
CAF_MESSAGE
(
"gauges start at 0"
);
CAF_CHECK_EQUAL
(
g
.
value
(),
0
);
CAF_MESSAGE
(
"gauges are incrementable"
);
g
.
inc
rement
();
g
.
inc
rement
(
2
);
g
.
inc
();
g
.
inc
(
2
);
CAF_CHECK_EQUAL
(
g
.
value
(),
3
);
CAF_MESSAGE
(
"gauges are decrementable"
);
g
.
dec
rement
();
g
.
dec
rement
(
5
);
g
.
dec
();
g
.
dec
(
5
);
CAF_CHECK_EQUAL
(
g
.
value
(),
-
3
);
CAF_MESSAGE
(
"gauges allow setting values"
);
g
.
value
(
42
);
...
...
libcaf_core/test/telemetry/metric_registry.cpp
View file @
f20b13b0
...
...
@@ -32,7 +32,7 @@ using namespace caf::telemetry;
namespace
{
struct
collector
{
struct
test_
collector
{
std
::
string
result
;
void
operator
()(
const
metric_family
*
family
,
const
metric
*
instance
,
...
...
@@ -70,19 +70,9 @@ struct collector {
};
struct
fixture
{
using
ig
=
int_gauge
;
metric_registry
registry
;
auto
bind
(
string_view
prefix
,
string_view
name
)
{
struct
bound
{
fixture
*
self_
;
string_view
prefix_
;
string_view
name_
;
auto
int_gauge
(
std
::
vector
<
label_view
>
labels
)
{
return
self_
->
registry
.
int_gauge
(
prefix_
,
name_
,
std
::
move
(
labels
));
}
};
return
bound
{
this
,
prefix
,
name
};
}
test_collector
collector
;
};
}
// namespace
...
...
@@ -90,46 +80,53 @@ struct fixture {
CAF_TEST_FIXTURE_SCOPE
(
metric_registry_tests
,
fixture
)
CAF_TEST
(
registries
lazily
create
metrics
)
{
registry
.
add_family
(
metric_type
::
int_gauge
,
"caf"
,
"running_actors"
,
{
"var1"
,
"var2"
},
"How many actors are currently running?"
);
auto
var
=
bind
(
"caf"
,
"running_actors"
);
auto
f
=
registry
.
family
<
ig
>
(
"caf"
,
"running_actors"
,
{
"var1"
,
"var2"
},
"How many actors are currently running?"
);
std
::
vector
<
label_view
>
v1
{{
"var1"
,
"foo"
},
{
"var2"
,
"bar"
}};
std
::
vector
<
label_view
>
v1_reversed
{{
"var2"
,
"bar"
},
{
"var1"
,
"foo"
}};
std
::
vector
<
label_view
>
v2
{{
"var1"
,
"bar"
},
{
"var2"
,
"foo"
}};
std
::
vector
<
label_view
>
v2_reversed
{{
"var2"
,
"foo"
},
{
"var1"
,
"bar"
}};
var
.
int_gauge
(
v1
)
->
value
(
42
);
var
.
int_gauge
(
v2
)
->
value
(
23
);
CAF_CHECK_EQUAL
(
var
.
int_gauge
(
v1
)
->
value
(),
42
);
CAF_CHECK_EQUAL
(
var
.
int_gauge
(
v1_reversed
)
->
value
(),
42
);
CAF_CHECK_EQUAL
(
var
.
int_gauge
(
v2
)
->
value
(),
23
);
CAF_CHECK_EQUAL
(
var
.
int_gauge
(
v2_reversed
)
->
value
(),
23
);
f
->
get_or_add
(
v1
)
->
value
(
42
);
f
->
get_or_add
(
v2
)
->
value
(
23
);
CAF_CHECK_EQUAL
(
f
->
get_or_add
(
v1
)
->
value
(),
42
);
CAF_CHECK_EQUAL
(
f
->
get_or_add
(
v1_reversed
)
->
value
(),
42
);
CAF_CHECK_EQUAL
(
f
->
get_or_add
(
v2
)
->
value
(),
23
);
CAF_CHECK_EQUAL
(
f
->
get_or_add
(
v2_reversed
)
->
value
(),
23
);
}
CAF_TEST
(
registries
allow
users
to
collect
all
registered
metrics
)
{
registry
.
add_family
(
metric_type
::
int_gauge
,
"foo"
,
"bar"
,
{},
"Just some value without labels."
,
"seconds"
);
registry
.
add_family
(
metric_type
::
int_gauge
,
"some"
,
"value"
,
{
"a"
,
"b"
},
"Just some (total) value with two labels."
,
"1"
,
true
);
registry
.
add_family
(
metric_type
::
int_gauge
,
"other"
,
"value"
,
{
"x"
},
"Just some (total) seconds value with a labels."
,
"seconds"
,
true
);
registry
.
add_family
(
metric_type
::
int_gauge
,
"caf"
,
"running_actors"
,
{
"node"
},
"How many actors are currently running?"
);
registry
.
int_gauge
(
"foo"
,
"bar"
,
{})
->
value
(
123
);
registry
.
int_gauge
(
"some"
,
"value"
,
{{
"a"
,
"1"
},
{
"b"
,
"2"
}})
->
value
(
12
);
registry
.
int_gauge
(
"some"
,
"value"
,
{{
"b"
,
"1"
},
{
"a"
,
"2"
}})
->
value
(
21
);
registry
.
int_gauge
(
"other"
,
"value"
,
{{
"x"
,
"true"
}})
->
value
(
31337
);
auto
running_actors
=
bind
(
"caf"
,
"running_actors"
);
running_actors
.
int_gauge
({{
"node"
,
"localhost"
}})
->
value
(
42
);
// Note: not registering caf_mailbox_size previously forces CAF to create it
// lazily when adding the first gauge.
auto
mailbox_size
=
bind
(
"caf"
,
"mailbox_size"
);
mailbox_size
.
int_gauge
({{
"name"
,
"printer"
}})
->
value
(
3
);
mailbox_size
.
int_gauge
({{
"name"
,
"parser"
}})
->
value
(
12
);
collector
c
;
registry
.
collect
(
c
);
CAF_CHECK_EQUAL
(
c
.
result
,
R"(
auto
fb
=
registry
.
family
<
ig
>
(
"foo"
,
"bar"
,
{},
"Some value without labels."
,
"seconds"
);
auto
sv
=
registry
.
family
<
ig
>
(
"some"
,
"value"
,
{
"a"
,
"b"
},
"Some (total) value with two labels."
,
"1"
,
true
);
auto
ov
=
registry
.
family
<
ig
>
(
"other"
,
"value"
,
{
"x"
},
"Some (total) seconds with one label."
,
"seconds"
,
true
);
auto
ra
=
registry
.
family
<
ig
>
(
"caf"
,
"running_actors"
,
{
"node"
},
"How many actors are running?"
);
auto
ms
=
registry
.
family
<
ig
>
(
"caf"
,
"mailbox_size"
,
{
"name"
},
"How full is the mailbox?"
);
CAF_MESSAGE
(
"the registry always returns the same family object"
);
CAF_CHECK_EQUAL
(
fb
,
registry
.
family
<
ig
>
(
"foo"
,
"bar"
,
{},
""
,
"seconds"
));
CAF_CHECK_EQUAL
(
sv
,
registry
.
family
<
ig
>
(
"some"
,
"value"
,
{
"a"
,
"b"
},
""
,
"1"
,
true
));
CAF_CHECK_EQUAL
(
sv
,
registry
.
family
<
ig
>
(
"some"
,
"value"
,
{
"b"
,
"a"
},
""
,
"1"
,
true
));
CAF_MESSAGE
(
"families always return the same metric object for given labels"
);
CAF_CHECK_EQUAL
(
fb
->
get_or_add
({}),
fb
->
get_or_add
({}));
CAF_CHECK_EQUAL
(
sv
->
get_or_add
({{
"a"
,
"1"
},
{
"b"
,
"2"
}}),
sv
->
get_or_add
({{
"b"
,
"2"
},
{
"a"
,
"1"
}}));
CAF_MESSAGE
(
"collectors can observe all metrics in the registry"
);
fb
->
get_or_add
({})
->
inc
(
123
);
sv
->
get_or_add
({{
"a"
,
"1"
},
{
"b"
,
"2"
}})
->
value
(
12
);
sv
->
get_or_add
({{
"b"
,
"1"
},
{
"a"
,
"2"
}})
->
value
(
21
);
ov
->
get_or_add
({{
"x"
,
"true"
}})
->
value
(
31337
);
ra
->
get_or_add
({{
"node"
,
"localhost"
}})
->
value
(
42
);
ms
->
get_or_add
({{
"name"
,
"printer"
}})
->
value
(
3
);
ms
->
get_or_add
({{
"name"
,
"parser"
}})
->
value
(
12
);
registry
.
collect
(
collector
);
CAF_CHECK_EQUAL
(
collector
.
result
,
R"(
foo_bar_seconds 123
some_value_total{a="1",b="2"} 12
some_value_total{a="2",b="1"} 21
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment