Skip to content

Commit 532126b

Browse files
authored
Custom log consumer (#21)
* Implement Custom LogConsumer for filter by kind and category in our way Signed-off-by: jparisu <javierparis@eprosima.com> * Add documentation Signed-off-by: jparisu <javierparis@eprosima.com> * apply suggestions Signed-off-by: jparisu <javierparis@eprosima.com> * uncrustify Signed-off-by: jparisu <javierparis@eprosima.com> Signed-off-by: jparisu <javierparis@eprosima.com>
1 parent 5c7ce96 commit 532126b

3 files changed

Lines changed: 179 additions & 2 deletions

File tree

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* @file CustomStdLogConsumer.hpp
17+
*/
18+
19+
#pragma once
20+
21+
#include <regex>
22+
23+
#include <cpp_utils/Log.hpp>
24+
#include <cpp_utils/library/library_dll.h>
25+
26+
namespace eprosima {
27+
namespace utils {
28+
29+
/**
30+
* Custom Log Consumer with Standard (logical) behaviour.
31+
*
32+
* Registering this consumer in Fast DDS Log prints every log entry that has a higher kind than the threshold
33+
* given. In case messages are not of Error kind, they are filtered by category to match a regex.
34+
* Info messages are printed in std::cout while others are sent to std::cerr .
35+
*
36+
* @attention This consumer filters the entries that receives, but some other entries could be filtered beforehand
37+
* by Fast DDS Log. To avoid these, set Log verbosity to Info and do not use Category Filter.
38+
*/
39+
class CustomStdLogConsumer : public utils::LogConsumer
40+
{
41+
public:
42+
43+
//! Create new CustomStdLogConsumer with regex filter generated from a string and with maximum verbosity kind.
44+
CPP_UTILS_DllAPI CustomStdLogConsumer(
45+
const std::string& log_filter,
46+
const eprosima::fastdds::dds::Log::Kind& log_verbosity);
47+
48+
//! Default destructor
49+
CPP_UTILS_DllAPI ~CustomStdLogConsumer() noexcept = default;
50+
51+
/**
52+
* @brief Implements \c LogConsumer \c Consume method.
53+
*
54+
* Each entry must be equal or higher the verbosity level \c verbosity_ .
55+
* Each entry category must match with regex stored in \c filter_ , except
56+
* those entries that are Error will be always printed if \c verbosity_ is not Error.
57+
*
58+
* This method will print the \c entry in \c std::cout with info verbosity and in \c std:cerr otherwise.
59+
*
60+
* @param entry entry to consume
61+
*/
62+
CPP_UTILS_DllAPI void Consume(
63+
const Log::Entry& entry) override;
64+
65+
protected:
66+
67+
//! Whether the entry must be accepted depending on kind and category
68+
CPP_UTILS_DllAPI virtual bool accept_entry_(
69+
const Log::Entry& entry);
70+
71+
/**
72+
* @brief Get which stream must be used depending on the entry
73+
*
74+
* @param entry to decide the output stream
75+
*
76+
* @return \c std::out if entry is Info, \c std::cerr otherwise.
77+
*/
78+
CPP_UTILS_DllAPI virtual std::ostream& get_stream_(
79+
const Log::Entry& entry);
80+
81+
//! Regex filter for entry category
82+
std::regex filter_;
83+
84+
//! Maximum Log Kind that will be printed.
85+
eprosima::fastdds::dds::Log::Kind verbosity_;
86+
};
87+
88+
} /* namespace utils */
89+
} /* namespace eprosima */

cpp_utils/include/cpp_utils/macros/custom_enumeration.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ namespace utils {
6969
/* To string method */ \
7070
inline const std::string& to_string(const enumeration_name& e) \
7171
{ return names_ ## enumeration_name[static_cast<int>(e)]; } \
72+
\
73+
inline std::vector<std::string> string_vector_ ## enumeration_name() \
74+
{ return std::vector<std::string> (names_ ## enumeration_name.begin(), names_ ## enumeration_name.end()); } \
7275
\
7376
/* From string */ \
7477
inline enumeration_name from_string_ ## enumeration_name(const std::string& s) \
@@ -89,5 +92,3 @@ namespace utils {
8992

9093
} /* namespace utils */
9194
} /* namespace eprosima */
92-
93-
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* @file CustomStdLogConsumer.cpp
17+
*
18+
*/
19+
20+
#include <cpp_utils/logging/CustomStdLogConsumer.hpp>
21+
22+
namespace eprosima {
23+
namespace utils {
24+
25+
CustomStdLogConsumer::CustomStdLogConsumer(
26+
const std::string& log_filter,
27+
const eprosima::fastdds::dds::Log::Kind& log_verbosity)
28+
: filter_(log_filter)
29+
, verbosity_(log_verbosity)
30+
{
31+
// Do nothing
32+
}
33+
34+
void CustomStdLogConsumer::Consume(
35+
const utils::Log::Entry& entry)
36+
{
37+
if (accept_entry_(entry))
38+
{
39+
std::ostream& stream = get_stream_(entry);
40+
print_timestamp(stream, entry, true);
41+
print_header(stream, entry, true);
42+
print_message(stream, entry, true);
43+
print_context(stream, entry, true);
44+
print_new_line(stream, true);
45+
stream.flush();
46+
}
47+
}
48+
49+
bool CustomStdLogConsumer::accept_entry_(
50+
const Log::Entry& entry)
51+
{
52+
// Filter by kind
53+
if (entry.kind > verbosity_)
54+
{
55+
return false;
56+
}
57+
else if (entry.kind == eprosima::fastdds::dds::Log::Kind::Error &&
58+
entry.kind < verbosity_)
59+
{
60+
// In case it is an error message and verbosity is not error, filter does not care
61+
return true;
62+
}
63+
64+
// Filter by regex
65+
if (!std::regex_search(entry.context.category, filter_))
66+
{
67+
return false;
68+
}
69+
70+
return true;
71+
}
72+
73+
std::ostream& CustomStdLogConsumer::get_stream_(
74+
const Log::Entry& entry)
75+
{
76+
if (entry.kind < eprosima::fastdds::dds::Log::Kind::Warning)
77+
{
78+
return std::cout;
79+
}
80+
else
81+
{
82+
return std::cerr;
83+
}
84+
}
85+
86+
} /* namespace utils */
87+
} /* namespace eprosima */

0 commit comments

Comments
 (0)