2014-07-15 16 views
12

부스트 (1.55.0)를 사용하고 있습니다. C++ 애플리케이션을 로깅합니다. 나는이 형식 I 소스 파일 이름과 로그가 생성됩니다 줄 번호를 추가 할 수 있도록소스 코드 파일 이름과 행 번호를 인쇄하기위한 부스트 로그

[2014-Jul-15 10:47:26.137959]: <debug> A regular message 

의 로그를 생성 할 수있게되었습니다.

[2014-Jul-15 10:47:26.137959]: <debug> [filename:line_no] A regular message 

예 :

[2014-Jul-15 10:47:26.137959]: <debug> [helloworld.cpp : 12] A regular message 

소스 코드 :

#include <boost/log/core.hpp> 
#include <boost/log/trivial.hpp> 
#include <boost/log/expressions.hpp> 
#include <boost/log/sinks/text_file_backend.hpp> 
#include <boost/log/utility/setup/file.hpp> 
#include <boost/log/utility/setup/common_attributes.hpp> 
#include <boost/log/sources/severity_logger.hpp> 
#include <boost/log/sources/record_ostream.hpp> 
#include <boost/log/expressions.hpp> 
#include <boost/log/support/date_time.hpp> 
#include <boost/log/attributes/attribute.hpp> 
#include <boost/log/attributes/attribute_cast.hpp> 
#include <boost/log/attributes/attribute_value.hpp> 
#include <boost/make_shared.hpp> 
#include <boost/property_tree/ptree.hpp> 

namespace logging = boost::log; 
namespace src = boost::log::sources; 
namespace sinks = boost::log::sinks; 
namespace keywords = boost::log::keywords; 

void init() 
{ 
    logging::add_file_log 
    (
     keywords::file_name = "sample_%N.log",          /*< file name pattern >*/ 
     keywords::rotation_size = 10*1024*1204,         /*< rotate files every 10 MiB... >*/ 
     keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0), /*< ...or at midnight >*/ 
     keywords::format = 
     (
      boost::log::expressions::stream 
       << boost::log::expressions::format_date_time<boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d_%H:%M:%S.%f") 
       << ": <" << boost::log::trivial::severity << "> " 
       << boost::log::expressions::smessage 
     ) 
    ); 
} 

int main(int, char*[]) 
{ 
    init(); 
    logging::add_common_attributes(); 

    using namespace logging::trivial; 
    src::severity_logger<severity_level> lg; 

    BOOST_LOG_SEV(lg, debug) << "A regular message"; 
    return 0; 
} 
+0

가능한 [Boost.Log : 지원 파일 이름 및 행 번호] (http://stackoverflow.com/questions/31154429/boost-log-support-file-name-and-line-number) 중복 가능 – Paladin

답변

1

namespace attrs = boost::logging::attributes; 
namespace expr = boost::logging::expressions; 

정의 추가

<< expr::format_named_scope("Scope", keywords::format = "[%f:%l]") 

에서 keywords::format = (...)까지 init

그런 다음 mainadd_common_attributes()

logging::core::get()->add_global_attribute("Scope", attrs::named_scope()); 

를 추가합니다.

BOOST_LOG_SEV 줄 바로 앞에 BOOST_LOG_NAMED_SCOPE("whatever")을 추가하십시오.

BOOST_LOG_NAMED_SCOPE("whatever")은 "무엇이든"이라는 "범위"를 만듭니다. 범위는 범위 이름, 파일 및 범위가 정의 된 줄이 포함 된 사용되지 않는 변수로 구현됩니다.

format_named_scope 행은 범위를 로그 라인에서 형식화하는 방법을 지정합니다. % f는 파일, % l은 줄, % n은 범위 이름입니다.

로그 레코드에 나타나는 파일 줄은 매크로 BOOST_LOG_NAMED_SCOPE이 나타나고 BOOST_LOG_SEV 매크로의 줄이 아닌 줄입니다.

BOOST_LOG_NAMED_SCOPE을 사용하지 않고 파일과 줄을 기록하는 간단한 방법을 모르겠습니다.

+0

나는 이것을 시도 할 것이다. 고맙습니다. –

4

user2943014가 지적했듯이 scope를 사용하면 BOOST_LOG_SEV를 사용하여 로그 메시지를 내 보낸 행 번호가 아닌 해당 범위를 연 줄 번호가 인쇄됩니다.

실제로 기록한 위치에서 줄 번호 등을 기록하기 위해 속성을 사용할 수 있습니다.

등록 로깅 초기화 함수에서 전역 속성 :

using namespace boost::log; 
core::get()->add_global_attribute("Line", attributes::mutable_constant<int>(5)); 
core::get()->add_global_attribute("File", attributes::mutable_constant<std::string>("")); 
core::get()->add_global_attribute("Function", attributes::mutable_constant<std::string>("")); 

로깅 매크로에서 이러한 속성을 설정 :

#define logInfo(methodname, message)       \ 
    LOG_LOCATION;            \ 
    BOOST_LOG_SEV(_log, boost::log::trivial::severity_level::trace) << message 

#define LOG_LOCATION       \ 
    boost::log::attribute_cast<boost::log::attributes::mutable_constant<int>>(boost::log::core::get()->get_global_attributes()["Line"]).set(__LINE__); \ 
    boost::log::attribute_cast<boost::log::attributes::mutable_constant<std::string>>(boost::log::core::get()->get_global_attributes()["File"]).set(__FILE__); \ 
    boost::log::attribute_cast<boost::log::attributes::mutable_constant<std::string>>(boost::log::core::get()->get_global_attributes()["Function"]).set(__func__); 

정확히 아름다운하지 않습니다, 그러나 그것은 작동하고 나를 위해 먼 길이었다 . 동정 후원은이 기능을 상자 밖으로 제공하지 않습니다.

+0

나에게 잘 어울립니다. 이 순간에 시도해 보겠습니다. –

11

Horus으로 지적하면 파일과 줄 번호를 기록하기 위해 특성을 사용할 수 있습니다. 그러나 이런 식의 문제를 방지하기 위해 다중 문 매크로를 사용하지 않는 것이 좋습니다 :

if (something) 
    LOG_FILE_LINE(debug) << "It's true"; // Only the first statement is conditional! 

당신은 부스트 ​​로그 라이브러리의 기본 동작을 활용하는 매크로를 만드는 더 잘 할 수 있습니다. 예를 들어, BOOST_LOG_SEV은 다음과 같습니다

// New macro that includes severity, filename and line number 
#define CUSTOM_LOG(logger, sev) \ 
    BOOST_LOG_STREAM_WITH_PARAMS(\ 
     (logger), \ 
     (set_get_attrib("File", path_to_filename(__FILE__))) \ 
     (set_get_attrib("Line", __LINE__)) \ 
     (::boost::log::keywords::severity = (boost::log::trivial::sev)) \ 
    ) 

// Set attribute and return the new value 
template<typename ValueType> 
ValueType set_get_attrib(const char* name, ValueType value) { 
    auto attr = logging::attribute_cast<attrs::mutable_constant<ValueType>>(logging::core::get()->get_thread_attributes()[name]); 
    attr.set(value); 
    return attr.get(); 
} 

// Convert file path to only the filename 
std::string path_to_filename(std::string path) { 
    return path.substr(path.find_last_of("/\\")+1); 
} 

완전한 소스 코드는 다음과 같습니다 :

#include <boost/log/trivial.hpp> 
#include <boost/log/sources/severity_logger.hpp> 
#include <boost/log/utility/setup/file.hpp> 
#include <boost/log/utility/setup/console.hpp> 
#include <boost/log/expressions.hpp> 
#include <boost/log/utility/setup/common_attributes.hpp> 
#include <boost/log/attributes/mutable_constant.hpp> 
#include <boost/date_time/posix_time/posix_time_types.hpp> 
#include <boost/log/support/date_time.hpp> 
#include <boost/log/attributes/mutable_constant.hpp> 

namespace logging = boost::log; 
namespace attrs = boost::log::attributes; 
namespace expr  = boost::log::expressions; 
namespace src  = boost::log::sources; 
namespace keywords = boost::log::keywords; 

// New macro that includes severity, filename and line number 
#define CUSTOM_LOG(logger, sev) \ 
    BOOST_LOG_STREAM_WITH_PARAMS(\ 
     (logger), \ 
     (set_get_attrib("File", path_to_filename(__FILE__))) \ 
     (set_get_attrib("Line", __LINE__)) \ 
     (::boost::log::keywords::severity = (boost::log::trivial::sev)) \ 
    ) 

// Set attribute and return the new value 
template<typename ValueType> 
ValueType set_get_attrib(const char* name, ValueType value) { 
    auto attr = logging::attribute_cast<attrs::mutable_constant<ValueType>>(logging::core::get()->get_thread_attributes()[name]); 
    attr.set(value); 
    return attr.get(); 
} 

// Convert file path to only the filename 
std::string path_to_filename(std::string path) { 
    return path.substr(path.find_last_of("/\\")+1); 
} 

void init() { 
    // New attributes that hold filename and line number 
    logging::core::get()->add_thread_attribute("File", attrs::mutable_constant<std::string>("")); 
    logging::core::get()->add_thread_attribute("Line", attrs::mutable_constant<int>(0)); 

    logging::add_file_log (
    keywords::file_name = "sample.log", 
    keywords::format = (
    expr::stream 
     << expr::format_date_time<boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d_%H:%M:%S.%f") 
     << ": <" << boost::log::trivial::severity << "> " 
     << '[' << expr::attr<std::string>("File") 
       << ':' << expr::attr<int>("Line") << "] " 
     << expr::smessage 
    ) 
    ); 
    logging::add_common_attributes(); 
} 

int main(int argc, char* argv[]) { 
    init(); 
    src::severity_logger<logging::trivial::severity_level> lg; 

    CUSTOM_LOG(lg, debug) << "A regular message"; 
    return 0; 
} 

이 같은 설정 및 더 많은 특성을 얻을 수BOOST_LOG_STREAM_WITH_PARAMS를 사용

#define BOOST_LOG_SEV(logger, lvl) BOOST_LOG_STREAM_SEV(logger, lvl) 
#define BOOST_LOG_STREAM_SEV(logger, lvl)\ 
    BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::severity = (lvl))) 

이렇게하면 다음과 같은 로그가 생성됩니다.

2015-10-15_15:25:12.743153: <debug> [main.cpp:61] A regular message 
+1

+1. 구현 방식을 살펴보면 속성 유형을'mutable_constant '으로 정의하고'boost :: log :: string_literal (__ FILE __)'등으로 할당하면 더 빨리 작동해야합니다. 각 로그 행에 문자열 할당/복사를 중지하십시오. – bobah

+0

좋은 지적. 그러나'__LINE__'은 정수이고'__FILE__'는이 샘플에서 부분 문자열을 얻는 데 사용됩니다. 'boost :: log :: string_literal'는'char value [N]'과 같은 배열 상수로부터 생성됩니다. –

+0

@ Nature.Li는 코드가 스레드로부터 안전하지 않다고 지적했습니다. 코드의 스레드 속성에 대한 전역 속성을 변경했지만 여러 스레드로 테스트하지 않았습니다. –