how to customize “TimeStamp” format of Boost.Log

邮差的信 提交于 2020-01-02 00:54:09

问题


I want to get year-month-day hour:minute:second.fraction(2 digits), if I use "%Y-%m-%d %H:%M:%S.%f", I got almost what I want exception for the fraction( last part ) of seconds, it's showing 6 digits on my Windows XP, I don't know how to get 2 digits only, any idea?


回答1:


Boost.DateTime (upon which Boost.Log relies) doesn't seem to support specialized fractional seconds formatting, so the only way to do that would be to write your own custom attribute formatter, or (the easier, but less nice way) to slightly modify your formatting code.

Instead of something like this:

backend->set_formatter
(
    fmt::stream <<
      fmt::date_time<boost::posix_time::ptime>
        ("TimeStamp", keywords::format = "%Y-%m-%d %H:%M:%S.%f"));

backend->set_formatter
(
    fmt::stream <<
    fmt::date_time<boost::posix_time::ptime>
        ("TimeStamp", keywords::format = %Y-%m-%d %H:%M:%S.") <<
    (fmt::format("%.2s") % fmt::date_time<boost::posix_time::ptime>("%f"))
);

I haven't tested it myself, but I believe it should work: the first fmt::date_time() will return the timestamp without the fractional seconds, while the second fmt::date_time() will return just the fractional seconds, which will be cut to two digits by the fmt::format().




回答2:


We addressed it with this class:

    class TimeStamp : public boost::log::attributes::local_clock {
        public:
            typedef boost::log::attribute_value attribute_type;
            typedef boost::log::attributes::local_time_traits TimeTraitsT;
            typedef TimeTraitsT::time_type time_type;
            typedef boost::log::attributes::basic_attribute_value< std::string > result_value;

        public:
            boost::shared_ptr< attribute_type > get_value() {
                time_type posix_time = boost::date_time::microsec_clock< time_type >::universal_time();
                time_type::time_duration_type time = posix_time.time_of_day();
                time_type::date_type date = posix_time.date();
                std::stringstream formatter;

                formatter
                    << date.year() << "-"
                    << std::setfill('0') << std::setw(2) << int(date.month()) << "-"
                    << std::setfill('0') << std::setw(2) << date.day() << " "
                    << std::setfill('0') << std::setw(2) << boost::date_time::absolute_value(time.hours()) << ":"
                    << std::setfill('0') << std::setw(2) << boost::date_time::absolute_value(time.minutes()) << ":"
                    << std::setfill('0') << std::setw(2) << boost::date_time::absolute_value(time.seconds()) << ","
                    << std::setfill('0') << std::setw(2) << boost::date_time::absolute_value(time.fractional_seconds()) / 1000
                ;

                return boost::make_shared< result_value >(formatter.str());
            }
    };

Initialized like this:

boost::log::core::get()->add_global_attribute("TimeStamp", boost::make_shared< TimeStamp >());

And used like this:

backend_ptr->set_formatter(
    boost::log::formatters::stream
        << boost::log::formatters::attr< std::string >("TimeStamp")
        << boost::log::formatters::message();

The class, obviously, lets us access or format any portion of the date we wish




回答3:


I'm using this

namespace boost
{
    BOOST_LOG_OPEN_NAMESPACE

    namespace attributes
    {
        template <typename date_time_type>
        void format_time_ms( std::ostringstream& formatter, const date_time_type& date_time)
        {
            auto time = date_time.time_of_day();
            using namespace std;
            formatter
                << setfill( '0') << setw( 2) << time.hours()   << ':'
                << setfill( '0') << setw( 2) << time.minutes() << ':'
                << setfill( '0') << setw( 2) << time.seconds() << ','
                << setfill( '0') << setw( 3) << time.fractional_seconds() / 1000;
        }

        template <typename date_time_type>
        std::string format_time_ms( const date_time_type& date_time)
        {
            std::ostringstream formatter;
            format_time_ms( formatter, date_time);
            auto time = date_time.time_of_day();
            return formatter.str();
        }

        template <typename date_time_type>
        std::string format_date_time_ms( const date_time_type& date_time, const char date_time_sep = ' ')
        {
            using namespace std;
            ostringstream formatter;
            auto date = date_time.date();
            formatter
                << date.year() << '-'
                << setfill( '0') << setw( 2) << int( date.month()) << '-'
                << setfill( '0') << setw( 2) << date.day() << date_time_sep;
            format_time_ms( formatter, date_time);
            return formatter.str();
        }

        template <typename date_time_type, const char date_time_sep = ' '>
        struct date_time_ms_formatter
        {           
            std::string operator () ( const date_time_type& date_time) { return format_date_time_ms( date_time, date_time_sep); }
        };

        struct time_ms_formatter
        {
            template <typename date_time_type>
            std::string operator () ( const date_time_type& date_time) { return format_time_ms( date_time); }
        };

        template <typename time_type>
        struct local_clock_source
        {
            time_type operator () () const
            {
                return date_time::microsec_clock<time_type>::local_time();
            }
        };

        template <typename time_type>
        struct universal_clock_source
        {
            time_type operator () () const
            {
                return date_time::microsec_clock<time_type>::universal_time();
            }
        };

        template <typename time_type, typename clock_source_type, typename formater_type>
        class custom_clock: public attribute
        {
        public:
            class impl: public attribute::impl
            {
            public:
                attribute_value get_value()
                {
                    auto str = formater_type()( clock_source_type()());
                    return make_attribute_value( str);
                }
            };

            custom_clock(): attribute( new impl()) {}

            explicit custom_clock( const cast_source& source): attribute( source.as<impl>()) {}
        };


        typedef custom_clock<boost::posix_time::ptime, local_clock_source<boost::posix_time::ptime>, date_time_ms_formatter<boost::posix_time::ptime, '\t'> >       local_date_time_ms_clock;
        typedef custom_clock<boost::posix_time::ptime, universal_clock_source<boost::posix_time::ptime>, date_time_ms_formatter<boost::posix_time::ptime, '\t'> >   universal_date_time_ms_clock;

        typedef custom_clock<boost::posix_time::ptime, local_clock_source<boost::posix_time::ptime>, time_ms_formatter>     local_time_ms_clock;
        typedef custom_clock<boost::posix_time::ptime, universal_clock_source<boost::posix_time::ptime>, time_ms_formatter> universal_time_ms_clock;
    }

    BOOST_LOG_CLOSE_NAMESPACE // namespace log
}

initialized as

BOOST_LOG_ATTRIBUTE_KEYWORD( dateTimeStamp,     "DateTime",     boost::posix_time::ptime)
BOOST_LOG_ATTRIBUTE_KEYWORD( timeStamp,         "Time",         boost::posix_time::ptime)

core->add_global_attribute( dateTimeStamp.get_name(),   attrs::local_date_time_ms_clock());
core->add_global_attribute( timeStamp.get_name(),       attrs::local_time_ms_clock());

and used as

expr::stream << expr::attr<std::string>( dateTimeStamp.get_name())
expr::stream << expr::attr<std::string>( timeStamp.get_name())



回答4:


Try this one. It works for me under Linux.

sink->set_formatter(log_expr::format("%1%") % log_expr::max_size_decor<char>(22)[log_expr::stream << log_expr::format_date_time<boost::posix_time::ptime>("Timestamp", "%Y-%m-%d %H:%M:%S.%f")]);


来源:https://stackoverflow.com/questions/5947018/how-to-customize-timestamp-format-of-boost-log

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!