Menu

Migrating to the latest version

Oleg
2013-04-23
2013-06-03
<< < 1 2 (Page 2 of 2)
  • Oleg

    Oleg - 2013-05-29

    I wanted to make the Scope attribute configurable from settings.  The snippet below is the code I had to write to have this pretty basic feature working. And still I couldn't add an extra flag for printing only the file name. Is it intended to be this hard or am I missing something:

      // This is used to convert a run-time map of named scope format flags to
      // the compile-time boost parameter pack, and then create a Boost.Log scope formatter 
      // from it.
    struct make_name_scope_actor_t
    {
      typedef blog::formatter_factory<char>::args_map args_map_t;
      mutable boost::optional<format_named_scope_actor> _actor;
      args_map_t const &_args;
      mutable args_map_t::const_iterator _curr;
      make_name_scope_actor_t(args_map_t const &args_)
        :_args(args_),_curr(_args.begin())
      {
        next(blog::aux::empty_arg_list());
      }
      operator format_named_scope_actor() const
      {
        BOOST_ASSERT(_actor);
        return *_actor;
      }
      template <typename _Keywords>
      void finalize(_Keywords const &kwords_) const
      {
        _actor = blog::expressions::aux::format_named_scope<char, boost::phoenix::actor>("Scope", blog::fallback_to_none(), add(kwords_, blog::keywords::format = "%n (%f:%l)"));
      }
      void finalize(blog::aux::empty_arg_list const &kwords_) const
      {
        finalize(blog::keywords::format = "%n (%f:%l)");
      }
      template <typename _Keywords, typename _Keyword> static
      typename boost::enable_if<mpl::contains<_Keywords, typename _Keyword::key_type>, _Keywords>::type
      add(_Keywords const &kwords_, _Keyword const &)
      {
        return kwords_;
      }
      template <typename _Keywords, typename _Keyword> static
      typename boost::disable_if<mpl::contains<_Keywords, typename _Keyword::key_type>, boost::parameter::aux::arg_list<_Keyword, _Keywords>>::type
      add(_Keywords const &kwords_, _Keyword const &kword_) 
      {
       return (kwords_, kword_);
      }
      template <typename _Keyword> static
      boost::parameter::aux::arg_list<_Keyword, blog::aux::empty_arg_list>
      add(blog::aux::empty_arg_list root_, _Keyword const &kword_)
      {
        return boost::parameter::aux::arg_list<_Keyword, blog::aux::empty_arg_list>(kword_, root_);
      }
      template <typename _Keywords>
      void next(_Keywords const &kwords_) const
      {
        using namespace blog;
        if (_curr == _args.end())
          finalize(kwords_);
        else{
          if (_curr->first == keywords::tag::format::keyword_name())
            next(add(kwords_, keywords::format = _curr++->second));
          else if (_curr->first == keywords::tag::delimiter::keyword_name())
            next(add(kwords_, keywords::delimiter = _curr++->second));
          else if (_curr->first == keywords::tag::depth::keyword_name())
            next(add(kwords_, keywords::depth = boost::lexical_cast<size_t>(_curr++->second)));
          else if (_curr->first == keywords::tag::iteration::keyword_name())
            next(add(kwords_, keywords::iteration = (_curr++->second == "reverse" ? blog::expressions::reverse : blog::expressions::forward)));
          else if (_curr->first == keywords::tag::MinSeverity::keyword_name())
            ++_curr, next(kwords_); // ignore
          else
            LOG_THROW(std::invalid_argument, "Unknown keyword " << _curr->first << " in Scope log config")
        }
      }
    };
    format_named_scope_actor
    make_name_scope_actor(std::map<std::string, std::string> const &args_)
    {
      return make_name_scope_actor_t(args_);
    }
    
     
  • Andrey Semashev

    Andrey Semashev - 2013-05-29

    I'm not sure why would you try to compose parameter pack like that. It could be simpler, really:

    class scopes_formatter_factory :
        public logging::formatter_factory< char >
    {
    public:
        formatter_type create_formatter(
            logging::attribute_name const& attr_name, args_map const& args)
        {
            std::string format = "%n (%f:%l)"
            auto it = args.find("format");
            if (it != end)
                format = it->second;
            expr::scope_iteration_direction iteration = expr::forward;
            it = args.find("iteration");
            if (it != end)
            {
                if (it->second == "reverse")
                    iteration = expr::reverse;
                else if (it->second != "forward")
                    throw std::invalid_argument("Invalid iteration direction");
            }
            std::string delimiter = iteration == expr::forward ? "->" : "<-";
            it = args.find("delimiter");
            if (it != end)
                delimiter = it->second;
            unsigned int depth = 0;
            it = args.find("depth");
            if (it != end)
                depth = boost::lexical_cast< unsigned int >(it->second);
            return expr::stream << expr::format_named_scope(attr_name, keywords::format = format,
                keywords::delimiter = delimiter, keywords::iteration = iteration, keywords::depth = depth);
        }
    };
    

    Also, I didn't understand the problem with the filename flag. You allow to set the scope list element format, it can just contain %f to display the filename only.

     
  • Andrey Semashev

    Andrey Semashev - 2013-05-29

    Oh, end is args.end().

     
  • Oleg

    Oleg - 2013-05-29

    I'm not sure why would you try to compose parameter pack like that

    Because my way is more correct since I don't have to duplicate the defaults and worry about them changing in the next release. But whichever way you do it, this code is boilerplate and, arguably, should live in the library and not in the user code.

    Also, I didn't understand the problem with the filename flag. You allow to set the scope list element format, it can just contain %f to display the filename only.

    How? The final parsing of the format string is done inside the library and I could find an easy way to add an extra flag.

     
  • Andrey Semashev

    Andrey Semashev - 2013-05-29

    Because my way is more correct since I don't have to duplicate the defaults and worry about them changing in the next release.

    Ok, have it your way.

    But whichever way you do it, this code is boilerplate and, arguably, should live in the library and not in the user code.

    Maybe.

    I could find an easy way to add an extra flag.

    What flag? I don't understand.

     
  • Oleg

    Oleg - 2013-05-29

    I'd like to add a flag, say %s, that works like %f but prints only the file name not the entire path.

     
  • Andrey Semashev

    Andrey Semashev - 2013-05-29

    I see. Please, create a ticket and I'll try to implement it in future versions. In the meantime you can implement your own formatter that suits your needs.

     
  • Oleg

    Oleg - 2013-05-29

    I will, thanks. It would be nice though if there were an easier way to get this done than filing a ticket. The way the formatter is done right now I'd have to reimplement the entire thing with a lot of copy/paste to get that flag added.

     
<< < 1 2 (Page 2 of 2)

Log in to post a comment.