1 // Copyright 2020 The Pigweed Authors
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
7 // https://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
15 #include "pw_metric/metric.h"
20 #include "pw_log/log.h"
21 #include "pw_tokenizer/base64.h"
23 namespace pw::metric {
27 std::span<const std::byte> AsSpan(const T& t) {
28 return std::span<const std::byte>(reinterpret_cast<const std::byte*>(&t),
32 // A convenience class to encode a token as base64 while managing the storage.
33 // TODO(keir): Consider putting this into upstream pw_tokenizer.
34 struct Base64EncodedToken {
35 Base64EncodedToken(Token token) {
36 int encoded_size = tokenizer::PrefixedBase64Encode(AsSpan(token), data);
37 data[encoded_size] = 0;
40 const char* value() { return data.data(); }
41 std::array<char, 16> data;
44 const char* Indent(int level) {
45 static const char* kWhitespace8 = " ";
46 level = std::min(level, 4);
47 return kWhitespace8 + 8 - 2 * level;
52 // Enable easier registration when used as a member.
53 Metric::Metric(Token name, float value, IntrusiveList<Metric>& metrics)
54 : Metric(name, value) {
55 metrics.push_front(*this);
57 Metric::Metric(Token name, uint32_t value, IntrusiveList<Metric>& metrics)
58 : Metric(name, value) {
59 metrics.push_front(*this);
62 float Metric::as_float() const {
63 PW_DCHECK(is_float());
67 uint32_t Metric::as_int() const {
72 void Metric::Increment(uint32_t amount) {
77 void Metric::SetInt(uint32_t value) {
82 void Metric::SetFloat(float value) {
83 PW_DCHECK(is_float());
87 void Metric::Dump(int level) {
88 Base64EncodedToken encoded_name(name());
89 const char* indent = Indent(level);
91 PW_LOG_INFO("%s \"%s\": %f,", indent, encoded_name.value(), as_float());
93 PW_LOG_INFO("%s \"%s\": %u,",
96 static_cast<unsigned int>(as_int()));
100 void Metric::Dump(IntrusiveList<Metric>& metrics, int level) {
101 for (auto& m : metrics) {
106 Group::Group(Token name) : name_(name) {}
108 Group::Group(Token name, IntrusiveList<Group>& groups) : name_(name) {
109 groups.push_front(*this);
112 void Group::Dump(int level) {
113 Base64EncodedToken encoded_name(name());
114 const char* indent = Indent(level);
115 PW_LOG_INFO("%s \"%s\": {", indent, encoded_name.value());
116 Group::Dump(children(), level + 1);
117 Metric::Dump(metrics(), level + 1);
118 PW_LOG_INFO("%s }", indent);
121 void Group::Dump(IntrusiveList<Group>& groups, int level) {
122 for (auto& group : groups) {
127 } // namespace pw::metric