Boost log issues and workarounds

classic Classic list List threaded Threaded
23 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Boost log issues and workarounds

Boost - Dev mailing list
Hi,

I like the boost log, but there are many small issues, appreciate your
kind help:

I followed the following link to use a good macro LOG:

https://stackoverflow.com/questions/35895199/boost-log-and-severity-local-attributes

But calling LOG(error) caused much trouble for the name space
collision, alternative is to use full namespace
boost::log::trivial::error, but that is too cumbersome,I tried to use
an uppercase ERROR to replace it in an enum ERROR =
boost::log::trivial::error, obviously that could not be complied,
although it is defined as enum severity_level in trivial.hpp, it does
not look like the boost::log::trivial::error is an enum value. Any
workarounds?

Another issue from that link is it has to call LOGGABLE prior to call
LOG(error) in each function, that makes more clumsy, software
developers in my team are not happy about it. Any workaround to have a
fixed argument in BOOST_LOG_STREAM_WITH_PARAMS, without need to claim
boost::log::sources::severity_logger<boost::log::trivial::severity_level>
slg; in each function? You guys are genius that must be a way to do
it, appreciate your advice.

Thank you

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
On Thu, 17 Jan 2019 at 10:33, hh h via Boost <[hidden email]> wrote:

> ... alternative is to use full namespace boost::log::trivial::error, but
> that is too cumbersome ...
>

https://en.cppreference.com/w/cpp/language/namespace_alias

degski
--
*“If something cannot go on forever, it will stop" - Herbert Stein*

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 1/17/19 11:33 AM, hh h via Boost wrote:

> Hi,
>
> I like the boost log, but there are many small issues, appreciate your
> kind help:
>
> I followed the following link to use a good macro LOG:
>
> https://stackoverflow.com/questions/35895199/boost-log-and-severity-local-attributes
>
> But calling LOG(error) caused much trouble for the name space
> collision, alternative is to use full namespace
> boost::log::trivial::error, but that is too cumbersome,I tried to use
> an uppercase ERROR to replace it in an enum ERROR =
> boost::log::trivial::error, obviously that could not be complied,
> although it is defined as enum severity_level in trivial.hpp, it does
> not look like the boost::log::trivial::error is an enum value. Any
> workarounds?

I'm not sure I understand the problem correctly, it would be easier if
you described it in more detail, preferably with code samples.

 From what I gathered, you want a macro `LOG(severity)`, where
`severity` is a value from an enum defined by you. First, Boost.Log
requires a logger (or, generally speaking, a logging source) to emit log
records. You can create either local or global loggers, but since you
don't want a logger to be specified in your macro, I'm assuming you want
a global logger. See here:

https://www.boost.org/doc/libs/1_69_0/libs/log/doc/html/log/detailed/sources.html#log.detailed.sources.global_storage

Given a global logger named `my_logger`, your macro could be defined
like this:

#define LOG(severity) BOOST_LOG_SEV(my_logger::get(), severity)

Note that the library provides `BOOST_LOG_TRIVIAL` macro which doesn't
require a logger. In this case, a global logger defined by Boost.Log is
used. That logger uses `boost::log::trivial::severity_level` enum for
its severity levels.

Regarding your severity level enum, you have to specify it in template
parameters of the logger you use. In the logging macro, you can add any
namespaces before the enum value so that the macro expansion context is
irrelevant. For example:

namespace my_namespace {
enum my_severity
{
     verbose,
     info,
     error
};
}

#define LOG(severity) \
   BOOST_LOG_SEV(my_logger::get(), ::my_namespace::my_severity::severity)

LOG(error) << "Something failed";

> Another issue from that link is it has to call LOGGABLE prior to call
> LOG(error) in each function, that makes more clumsy, software
> developers in my team are not happy about it. Any workaround to have a
> fixed argument in BOOST_LOG_STREAM_WITH_PARAMS, without need to claim
> boost::log::sources::severity_logger<boost::log::trivial::severity_level>
> slg; in each function? You guys are genius that must be a way to do
> it, appreciate your advice.

I would say, `LOGGABLE` from one of the linked answers is a library
misuse. If you don't have a context associated with the logged activity,
you should be using a global logger. Otherwise, you should have a logger
specific to the context, e.g. as a class member.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
Thank you very much Andrey, that is exactly what I am looking for,
does the sample code my_logger.h and my_logger.cpp exist on line or
just hypothetical?

Thank you and appreciate it.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
On 1/17/19 11:37 PM, hh h wrote:
> Thank you very much Andrey, that is exactly what I am looking for,
> does the sample code my_logger.h and my_logger.cpp exist on line or
> just hypothetical?

Those are just examples in the docs. These particular examples don't
exist as standalone files. You can find global loggers used in a number
of other examples in the libs/log/example directory.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
> https://en.cppreference.com/w/cpp/language/namespace_alias

That cannot do namespace INFO = boost::log::trivial::info; so the only
way we might run namespace LEVEL = boost::log::trivial; and to call
LOG(LEVEL::info), not quite tidy, I am looking into Andrey's solution.

Thanks degski

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
On 18/01/2019 11:23, hh h wrote:
> That cannot do namespace INFO = boost::log::trivial::info; so the only
> way we might run namespace LEVEL = boost::log::trivial; and to call
> LOG(LEVEL::info), not quite tidy, I am looking into Andrey's solution.

Have you considered:

#define LOG_INFO() LOG(boost::log::trivial::info)

Or similar.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
Thanks, but let me tell you why I tried so hard to get LOG(INFO)
working, we used google log before, there are thousands and thousands
code lines are using LOG(ERROR), LOG(INFO), it is impossible to change
every line of LOG statement to use different LOG name and format. I am
keen to use boost log, I have been trying it for weeks, haven't got it
work yet, but I don't want to give up until I exhausted all my
avenues. Hope I can get there, but hey, thanks your guys for wonderful
supports.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
On 18/01/2019 12:39, hh h wrote:
> Thanks, but let me tell you why I tried so hard to get LOG(INFO)
> working, we used google log before, there are thousands and thousands
> code lines are using LOG(ERROR), LOG(INFO), it is impossible to change
> every line of LOG statement to use different LOG name and format. I am
> keen to use boost log, I have been trying it for weeks, haven't got it
> work yet, but I don't want to give up until I exhausted all my
> avenues. Hope I can get there, but hey, thanks your guys for wonderful
> supports.

Replace In Files is a thing that exists.

Or #define INFO boost::log::trivial::info

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
Yeah, that was the first thing I tried, but could not compile it, did
that work in your site?

error: expected ‘}’ before ‘::’ token
 #define INFO boost::log::trivial::info


error: ‘::log’ is not a class, namespace, or enumeration
 #define INFO boost::log::trivial::info

On 1/18/19, Gavin Lambert via Boost <[hidden email]> wrote:

> On 18/01/2019 12:39, hh h wrote:
>> Thanks, but let me tell you why I tried so hard to get LOG(INFO)
>> working, we used google log before, there are thousands and thousands
>> code lines are using LOG(ERROR), LOG(INFO), it is impossible to change
>> every line of LOG statement to use different LOG name and format. I am
>> keen to use boost log, I have been trying it for weeks, haven't got it
>> work yet, but I don't want to give up until I exhausted all my
>> avenues. Hope I can get there, but hey, thanks your guys for wonderful
>> supports.
>
> Replace In Files is a thing that exists.
>
> Or #define INFO boost::log::trivial::info
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Hi Andrey,

> Those are just examples in the docs. These particular examples don't
> exist as standalone files. You can find global loggers used in a number
> of other examples in the libs/log/example directory.

The global loggers is working well, but I could not compile the local
log severity, here is the code:

BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS(my_logger,
boost::log::sources::channel_logger_mt< >,
(boost::log::keywords::channel = "general"))

typedef enum {
    INFO,
    DEBUG,
    WARNING,
    ERROR,
    CRITICAL
} ServerityLevel_t;

template<typename CharT, typename TraitsT> std::basic_ostream< CharT,
TraitsT >& operator << (std::basic_ostream< CharT, TraitsT >& strm,
ServerityLevel_t lvl) {
    static const char* const str[] = {
        "INFO",
        "DEBUG",
        "WARNING",
        "ERROR",
        "CRITICAL"
    };
    if (static_cast< std::size_t >(lvl) < (sizeof(str) / sizeof(*str))) {
        strm << str[lvl];
    } else {
        strm << static_cast< int >(lvl);
    }
    return strm;
}

#define LOG(severity) BOOST_LOG_STREAM_WITH_PARAMS((my_logger::get()),
(SetGetAttrib("FileName",
PathToFilename(__FILE__)))(SetGetAttrib("LineNumber", (unsigned
int)__LINE__))(ServerityLevel_t::severity))

/usr/include/boost/log/sources/channel_feature.hpp:171:60: error: no
match for ‘operator[]’ (operand types are ‘const ServerityLevel_t’ and
‘boost::parameter::aux::default_<boost::log::v2_mt_posix::keywords::tag::channel,
const boost::parameter::void_>’)
         return open_record_with_channel_unlocked(args,
args[keywords::channel | parameter::void_()]);

Obviously, you used BOOST_LOG_SEV where I was using
BOOST_LOG_STREAM_WITH_PARAMS, the compiler seems to complain missing
operator[], but I have no clue how to define it.

Thank you.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
Finally fixed it by changing LOG macro
(::boost::log::keywords::severity = (ServerityLevel_t::severity).

The only thing missing is that in logging::add_file_log( ..." " <<
boost::log::trivial::severity << ....), that
boost::log::trivial::severity is empty, the keyword severity has
already been assigned in the macro, what I am missing here?

Thanks Andrey.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 1/18/19 6:45 AM, hh h wrote:

> Hi Andrey,
>
>> Those are just examples in the docs. These particular examples don't
>> exist as standalone files. You can find global loggers used in a number
>> of other examples in the libs/log/example directory.
>
> The global loggers is working well, but I could not compile the local
> log severity, here is the code:
>
> BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS(my_logger,
> boost::log::sources::channel_logger_mt< >,
> (boost::log::keywords::channel = "general"))

If you want a severity level attribute, that should be
severity_channel_logger_mt< ServerityLevel_t >.

> typedef enum {
>      INFO,
>      DEBUG,
>      WARNING,
>      ERROR,
>      CRITICAL
> } ServerityLevel_t;
>
> template<typename CharT, typename TraitsT> std::basic_ostream< CharT,
> TraitsT >& operator << (std::basic_ostream< CharT, TraitsT >& strm,
> ServerityLevel_t lvl) {
>      static const char* const str[] = {
>          "INFO",
>          "DEBUG",
>          "WARNING",
>          "ERROR",
>          "CRITICAL"
>      };
>      if (static_cast< std::size_t >(lvl) < (sizeof(str) / sizeof(*str))) {
>          strm << str[lvl];
>      } else {
>          strm << static_cast< int >(lvl);
>      }
>      return strm;
> }
>
> #define LOG(severity) BOOST_LOG_STREAM_WITH_PARAMS((my_logger::get()),
> (SetGetAttrib("FileName",
> PathToFilename(__FILE__)))(SetGetAttrib("LineNumber", (unsigned
> int)__LINE__))(ServerityLevel_t::severity))
>
> /usr/include/boost/log/sources/channel_feature.hpp:171:60: error: no
> match for ‘operator[]’ (operand types are ‘const ServerityLevel_t’ and
> ‘boost::parameter::aux::default_<boost::log::v2_mt_posix::keywords::tag::channel,
> const boost::parameter::void_>’)
>           return open_record_with_channel_unlocked(args,
> args[keywords::channel | parameter::void_()]);

I'm not sure what SetGetAttrib is, but BOOST_LOG_STREAM_WITH_PARAMS
assumes the parameters are Boost.Parameter named parameters. I.e. to
pass a severity level you need to say:

(::boost::log::keywords::severity = ServerityLevel_t::severity)

and to pass a channel name:

(::boost::log::keywords::channel = (chan))

If you want to use named parameters to add FileName and LineNumber
attributes, you will have to write your own logger feature and add it to
the severity level and channel features, as described here:

https://www.boost.org/doc/libs/1_69_0/libs/log/doc/html/log/extension/sources.html

If you don't need to apply filters to these attributes, you can just use
add_value manipulator in your macro:

https://www.boost.org/doc/libs/1_69_0/libs/log/doc/html/log/detailed/utilities.html#log.detailed.utilities.manipulators.add_value

That will work without having to develop a new logger feature.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 1/18/19 10:27 AM, hh h wrote:
> Finally fixed it by changing LOG macro
> (::boost::log::keywords::severity = (ServerityLevel_t::severity).
>
> The only thing missing is that in logging::add_file_log( ..." " <<
> boost::log::trivial::severity << ....), that
> boost::log::trivial::severity is empty, the keyword severity has
> already been assigned in the macro, what I am missing here?

See my other reply.

Also, please keep some context of the conversation in your replies.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
> If you want a severity level attribute, that should be severity_channel_logger_mt< ServerityLevel_t >

I added ServerityLevel_t to the severity_channel_logger_mt, but still
couldn't printed out the severity, otherwise, seems everything works.I
won't be too worry about the display of severity, finally I can
replace the google log by boost log.

BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger,
src::severity_logger_mt<ServerityLevel_t>)

Thank you very much Andrey.

On 1/18/19, Andrey Semashev via Boost <[hidden email]> wrote:

> On 1/18/19 10:27 AM, hh h wrote:
>> Finally fixed it by changing LOG macro
>> (::boost::log::keywords::severity = (ServerityLevel_t::severity).
>>
>> The only thing missing is that in logging::add_file_log( ..." " <<
>> boost::log::trivial::severity << ....), that
>> boost::log::trivial::severity is empty, the keyword severity has
>> already been assigned in the macro, what I am missing here?
>
> See my other reply.
>
> Also, please keep some context of the conversation in your replies.
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
On 1/18/19 12:41 PM, hh h wrote:
>> If you want a severity level attribute, that should be severity_channel_logger_mt< ServerityLevel_t >
>
> I added ServerityLevel_t to the severity_channel_logger_mt, but still
> couldn't printed out the severity, otherwise, seems everything works.

If you're using boost::log::trivial::severity keyword in the formatter
then that is the problem. This keyword corresponds to the
boost::log::trivial::severity_level enum for severity levels. For custom
enums, custom keywords should be defined and used.

https://www.boost.org/doc/libs/1_69_0/libs/log/doc/html/log/detailed/expressions.html#log.detailed.expressions.attr_keywords

Also, please don't top-post. Our discussion guidelines are described here:

https://www.boost.org/community/policy.html

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
> custom keywords should be defined and used.

Thanks Andrey, that fixed the problem.

The last issue is to set log level, I tried following statements, neither works:

auto filter = boost::log::filter(boost::log::trivial::severity >=
ServerityLevel_t::ERROR);
boost::log::core::get()->set_filter(filter);

OR

boost::log::trivial::severity.or_default(ServerityLevel_t::ERROR);

What I could be missing?

Thank you very much.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
On 1/19/19 12:16 AM, hh h wrote:
>> custom keywords should be defined and used.
>
> Thanks Andrey, that fixed the problem.
>
> The last issue is to set log level, I tried following statements, neither works:
>
> auto filter = boost::log::filter(boost::log::trivial::severity >=
> ServerityLevel_t::ERROR);
> boost::log::core::get()->set_filter(filter);

Same as with formatters, you need to use your custom keyword in the
filter expression.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
Excellent, all done. Thank you so much Andrey, you rock.

On 1/19/19, Andrey Semashev via Boost <[hidden email]> wrote:

> On 1/19/19 12:16 AM, hh h wrote:
>>> custom keywords should be defined and used.
>>
>> Thanks Andrey, that fixed the problem.
>>
>> The last issue is to set log level, I tried following statements, neither
>> works:
>>
>> auto filter = boost::log::filter(boost::log::trivial::severity >=
>> ServerityLevel_t::ERROR);
>> boost::log::core::get()->set_filter(filter);
>
> Same as with formatters, you need to use your custom keyword in the
> filter expression.
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Boost log issues and workarounds

Boost - Dev mailing list
Hi Andrey,

Sorry, I was excited too earlier. In my simple test program, it was
working well, but the massive changes of replacing google log by boost
log did not go well. That could be due to the complicate real
application structure.

I have a Log class to wrap the boost log built into a library, the
BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT, BOOST_LOG_ATTRIBUTE_KEYWORD
and the #define LOG are all defined in Log.hpp, that should be fine,
right? The boost log initial function is implemented in the Log class
in Log.cpp. The log initial function was called just once in an
application base class and remain in the memory until the application
exits. First, it got Segmentation fault (core dumped), after changing
boost::log::core::get()->add_global_attribute() and
boost::log::core::get()->add_thread_attribute() to
boost::log::core::get()->add_thread_attribute in the initial function
of Log.cpp, it fixed the Segmentation fault, but it did not write
anything to the log file in /tmp/log/network.log, the log file is
empty.

Would you please clarify following questions:

(1) Will it be a problem to keep the
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity",
::LibraryGlobalServerityLevel_t) and
BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(mGlobalLogger,
boost::log::sources::severity_logger_mt<::LibraryGlobalServerityLevel_t>)
in a header file Log.hpp where many sources include the header file
Log.hpp?

(2) I think that the boost log initialization should be called once
even in multi threading program to share the same log, is it correct?

(3) What are different between add_global_attribute and
add_thread_attribute? I thought since I use GLOBAL_LOGGER, I should
use the add_global_attribute, why it got Segmentation fault?

(4) What could I be missing that the log file is empty? I am writing
the log file currently to the /tmp which won't cause any permission
issues. I tried both static calling boost::log::add_file_log(..) and
shared pointer boost::shared_ptr<FileSink_t> sink(new FileSink_t(...)
in the log initial function, it did not make any difference, none of
it works.

(5) Currently I built it using dynamic link, can it use static link?
What will be the build macro for static link?

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
12