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
00ee8640
Commit
00ee8640
authored
Jun 10, 2020
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement Prometheus metric exposition
parent
cfc0baa5
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
297 additions
and
0 deletions
+297
-0
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+2
-0
libcaf_core/caf/string_view.hpp
libcaf_core/caf/string_view.hpp
+8
-0
libcaf_core/caf/telemetry/collector/prometheus.hpp
libcaf_core/caf/telemetry/collector/prometheus.hpp
+69
-0
libcaf_core/src/telemetry/collector/prometheus.cpp
libcaf_core/src/telemetry/collector/prometheus.cpp
+144
-0
libcaf_core/test/telemetry/collector/prometheus.cpp
libcaf_core/test/telemetry/collector/prometheus.cpp
+74
-0
No files found.
libcaf_core/CMakeLists.txt
View file @
00ee8640
...
@@ -162,6 +162,7 @@ add_library(libcaf_core_obj OBJECT ${CAF_CORE_HEADERS}
...
@@ -162,6 +162,7 @@ add_library(libcaf_core_obj OBJECT ${CAF_CORE_HEADERS}
src/stream_priority_strings.cpp
src/stream_priority_strings.cpp
src/string_algorithms.cpp
src/string_algorithms.cpp
src/string_view.cpp
src/string_view.cpp
src/telemetry/collector/prometheus.cpp
src/telemetry/label.cpp
src/telemetry/label.cpp
src/telemetry/label_view.cpp
src/telemetry/label_view.cpp
src/telemetry/metric.cpp
src/telemetry/metric.cpp
...
@@ -307,6 +308,7 @@ caf_add_test_suites(caf-core-test
...
@@ -307,6 +308,7 @@ caf_add_test_suites(caf-core-test
string_algorithms
string_algorithms
string_view
string_view
sum_type
sum_type
telemetry.collector.prometheus
telemetry.int_gauge
telemetry.int_gauge
telemetry.label
telemetry.label
telemetry.metric_registry
telemetry.metric_registry
...
...
libcaf_core/caf/string_view.hpp
View file @
00ee8640
...
@@ -289,6 +289,14 @@ inline std::string to_string(string_view x) {
...
@@ -289,6 +289,14 @@ inline std::string to_string(string_view x) {
}
// namespace caf
}
// namespace caf
namespace
caf
::
literals
{
constexpr
string_view
operator
""
_sv
(
const
char
*
cstr
,
size_t
len
)
{
return
{
cstr
,
len
};
}
}
// namespace caf::literals
namespace
std
{
namespace
std
{
CAF_CORE_EXPORT
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
caf
::
string_view
);
CAF_CORE_EXPORT
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
caf
::
string_view
);
...
...
libcaf_core/caf/telemetry/collector/prometheus.hpp
0 → 100644
View file @
00ee8640
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <unordered_map>
#include <vector>
#include "caf/fwd.hpp"
#include "caf/string_view.hpp"
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
{
public:
/// A buffer for storing UTF-8 characters. Using a vector instead of a
/// `std::string` has slight performance benefits, since the vector does not
/// have to maintain a null-terminator.
using
char_buffer
=
std
::
vector
<
char
>
;
/// Initializes state before passing this collector to a metric registry.
void
begin_collecting
();
/// Finalizes state after collecting metrics from a registry completed.
void
end_collecting
();
/// Applies this collector to the registry, filling the character buffer while
/// collecting metrics.
string_view
collect_from
(
const
metric_registry
&
registry
);
// -- call operators for the metric registry ---------------------------------
void
operator
()(
const
metric_family
*
family
,
const
metric
*
instance
,
const
int_gauge
*
gauge
);
private:
/// Sets `current_family_` if not pointing to `family` already. When setting
/// the member variable, also writes meta information to `buf_`.
void
set_current_family
(
const
metric_family
*
family
,
string_view
prometheus_type
);
/// Stores the generated text output.
char_buffer
buf_
;
/// Caches type information and help text for a metric.
std
::
unordered_map
<
const
metric_family
*
,
char_buffer
>
meta_info_
;
/// Caches which metric family is currently collected.
const
metric_family
*
current_family_
=
nullptr
;
};
}
// namespace caf::telemetry::collector
libcaf_core/src/telemetry/collector/prometheus.cpp
0 → 100644
View file @
00ee8640
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/telemetry/collector/prometheus.hpp"
#include <cmath>
#include "caf/telemetry/int_gauge.hpp"
#include "caf/telemetry/metric.hpp"
#include "caf/telemetry/metric_family.hpp"
#include "caf/telemetry/metric_registry.hpp"
using
namespace
caf
::
literals
;
namespace
caf
::
telemetry
::
collector
{
namespace
{
void
append
(
prometheus
::
char_buffer
&
)
{
// End of recursion.
}
template
<
class
...
Ts
>
void
append
(
prometheus
::
char_buffer
&
,
string_view
,
Ts
&&
...);
template
<
class
...
Ts
>
void
append
(
prometheus
::
char_buffer
&
,
char
,
Ts
&&
...);
template
<
class
...
Ts
>
void
append
(
prometheus
::
char_buffer
&
,
double
,
Ts
&&
...);
template
<
class
...
Ts
>
void
append
(
prometheus
::
char_buffer
&
,
int64_t
,
Ts
&&
...);
template
<
class
...
Ts
>
void
append
(
prometheus
::
char_buffer
&
,
const
metric_family
*
,
Ts
&&
...);
template
<
class
...
Ts
>
void
append
(
prometheus
::
char_buffer
&
,
const
metric
*
,
Ts
&&
...);
template
<
class
...
Ts
>
void
append
(
prometheus
::
char_buffer
&
buf
,
string_view
str
,
Ts
&&
...
xs
)
{
buf
.
insert
(
buf
.
end
(),
str
.
begin
(),
str
.
end
());
append
(
buf
,
std
::
forward
<
Ts
>
(
xs
)...);
}
template
<
class
...
Ts
>
void
append
(
prometheus
::
char_buffer
&
buf
,
char
ch
,
Ts
&&
...
xs
)
{
buf
.
emplace_back
(
ch
);
append
(
buf
,
std
::
forward
<
Ts
>
(
xs
)...);
}
template
<
class
...
Ts
>
void
append
(
prometheus
::
char_buffer
&
buf
,
double
val
,
Ts
&&
...
xs
)
{
if
(
isnan
(
val
))
{
append
(
buf
,
"NaN"
_sv
);
}
else
if
(
isinf
(
val
))
{
if
(
signbit
(
val
))
append
(
buf
,
"+Inf"
_sv
);
else
append
(
buf
,
"-Inf"
_sv
);
}
else
{
append
(
buf
,
std
::
to_string
(
val
));
}
append
(
buf
,
std
::
forward
<
Ts
>
(
xs
)...);
}
template
<
class
...
Ts
>
void
append
(
prometheus
::
char_buffer
&
buf
,
int64_t
val
,
Ts
&&
...
xs
)
{
append
(
buf
,
std
::
to_string
(
val
));
append
(
buf
,
std
::
forward
<
Ts
>
(
xs
)...);
}
template
<
class
...
Ts
>
void
append
(
prometheus
::
char_buffer
&
buf
,
const
metric_family
*
family
,
Ts
&&
...
xs
)
{
append
(
buf
,
family
->
prefix
(),
'_'
,
family
->
name
());
if
(
family
->
unit
()
!=
"1"
_sv
)
append
(
buf
,
'_'
,
family
->
unit
());
if
(
family
->
is_sum
())
append
(
buf
,
"_total"
_sv
);
append
(
buf
,
std
::
forward
<
Ts
>
(
xs
)...);
}
template
<
class
...
Ts
>
void
append
(
prometheus
::
char_buffer
&
buf
,
const
metric
*
instance
,
Ts
&&
...
xs
)
{
const
auto
&
labels
=
instance
->
labels
();
if
(
!
labels
.
empty
())
{
append
(
buf
,
'{'
);
auto
i
=
labels
.
begin
();
append
(
buf
,
i
->
name
(),
"=
\"
"
_sv
,
i
->
value
(),
'"'
);
while
(
++
i
!=
labels
.
end
())
append
(
buf
,
','
,
i
->
name
(),
"=
\"
"
,
i
->
value
(),
'"'
);
append
(
buf
,
'}'
);
}
append
(
buf
,
std
::
forward
<
Ts
>
(
xs
)...);
}
}
// namespace
string_view
prometheus
::
collect_from
(
const
metric_registry
&
registry
)
{
buf_
.
clear
();
registry
.
collect
(
*
this
);
current_family_
=
nullptr
;
return
{
buf_
.
data
(),
buf_
.
size
()};
}
void
prometheus
::
operator
()(
const
metric_family
*
family
,
const
metric
*
instance
,
const
int_gauge
*
gauge
)
{
set_current_family
(
family
,
"gauge"
);
append
(
buf_
,
family
,
instance
,
' '
,
gauge
->
value
(),
'\n'
);
}
void
prometheus
::
set_current_family
(
const
metric_family
*
family
,
string_view
prometheus_type
)
{
if
(
current_family_
==
family
)
return
;
current_family_
=
family
;
auto
i
=
meta_info_
.
find
(
family
);
if
(
i
==
meta_info_
.
end
())
{
i
=
meta_info_
.
emplace
(
family
,
char_buffer
{}).
first
;
if
(
!
family
->
helptext
().
empty
())
append
(
i
->
second
,
"# HELP "
,
family
,
' '
,
family
->
helptext
(),
'\n'
);
append
(
i
->
second
,
"# TYPE "
,
family
,
' '
,
prometheus_type
,
'\n'
);
}
buf_
.
insert
(
buf_
.
end
(),
i
->
second
.
begin
(),
i
->
second
.
end
());
}
}
// namespace caf::telemetry::collector
libcaf_core/test/telemetry/collector/prometheus.cpp
0 → 100644
View file @
00ee8640
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE telemetry.collector.prometheus
#include "caf/telemetry/collector/prometheus.hpp"
#include "caf/test/dsl.hpp"
#include "caf/telemetry/metric_registry.hpp"
#include "caf/telemetry/metric_type.hpp"
using
namespace
caf
;
using
namespace
caf
::
literals
;
using
namespace
caf
::
telemetry
;
namespace
{
struct
fixture
{
collector
::
prometheus
exporter
;
metric_registry
registry
;
};
}
// namespace
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
);
CAF_CHECK_EQUAL
(
exporter
.
collect_from
(
registry
),
R"(# HELP foo_bar_seconds Just some value without labels.
# TYPE foo_bar_seconds gauge
foo_bar_seconds 123
# HELP some_value_total Just some (total) value with two labels.
# TYPE some_value_total gauge
some_value_total{a="1",b="2"} 12
some_value_total{a="2",b="1"} 21
# TYPE other_value_seconds_total gauge
other_value_seconds_total{x="true"} 31337
)"
_sv
);
CAF_MESSAGE
(
"multiple runs generate the same output"
);
std
::
string
res1
;
{
auto
buf
=
exporter
.
collect_from
(
registry
);
res1
.
assign
(
buf
.
begin
(),
buf
.
end
());
}
CAF_CHECK_EQUAL
(
res1
,
exporter
.
collect_from
(
registry
));
}
CAF_TEST_FIXTURE_SCOPE_END
()
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