开发者

how to customize "TimeStamp" format of Boost.Log

I want to get year-month-day hour:minute:second.fract开发者_C百科ion(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?


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())


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().


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


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")]);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜