Merge branch 'master' of https://github.com/BitShares/fc
This commit is contained in:
commit
633c889ce3
12 changed files with 406 additions and 86 deletions
|
|
@ -86,15 +86,6 @@ ENDIF()
|
|||
|
||||
find_package(OpenSSL)
|
||||
|
||||
IF(APPLE)
|
||||
# As of 10.10 yosemite, the OpenSSL static libraries shipped with os x have a dependency
|
||||
# on zlib, so any time you link in openssl you also need to link zlib. . We really want to detect whether openssl was configured with the --no-zlib
|
||||
# option or not when it was built, but that's difficult to do in practice, so we
|
||||
# just always try to link it in on mac.
|
||||
find_package( ZLIB REQUIRED )
|
||||
ENDIF(APPLE)
|
||||
|
||||
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES ${ORIGINAL_LIB_SUFFIXES} )
|
||||
|
||||
option( UNITY_BUILD OFF )
|
||||
|
|
@ -137,6 +128,7 @@ set( fc_sources
|
|||
src/log/appender.cpp
|
||||
src/log/console_appender.cpp
|
||||
src/log/file_appender.cpp
|
||||
src/log/gelf_appender.cpp
|
||||
src/log/logger_config.cpp
|
||||
src/crypto/openssl.cpp
|
||||
src/crypto/aes.cpp
|
||||
|
|
@ -353,6 +345,14 @@ if(WIN32)
|
|||
|
||||
endif(WIN32)
|
||||
|
||||
IF(APPLE)
|
||||
# As of 10.10 yosemite, the OpenSSL static libraries shipped with os x have a dependency
|
||||
# on zlib, so any time you link in openssl you also need to link zlib. . We really want to detect whether openssl was configured with the --no-zlib
|
||||
# option or not when it was built, but that's difficult to do in practice, so we
|
||||
# just always try to link it in on mac.
|
||||
find_package( ZLIB REQUIRED )
|
||||
ENDIF(APPLE)
|
||||
|
||||
SET(OPENSSL_CONF_TARGET )
|
||||
IF(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
|
||||
SET (OPENSSL_CONF_TARGET ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
|
|
|
|||
|
|
@ -298,21 +298,26 @@ namespace fc
|
|||
* @brief Checks a condition and throws an assert_exception if the test is FALSE
|
||||
*/
|
||||
#define FC_ASSERT( TEST, ... ) \
|
||||
FC_EXPAND_MACRO( \
|
||||
do { if( !(TEST) ) { FC_THROW_EXCEPTION( fc::assert_exception, #TEST ": " __VA_ARGS__ ); } } while(0) \
|
||||
)
|
||||
FC_EXPAND_MACRO( \
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
if( !(TEST) ) \
|
||||
FC_THROW_EXCEPTION( fc::assert_exception, #TEST ": " __VA_ARGS__ ); \
|
||||
FC_MULTILINE_MACRO_END \
|
||||
)
|
||||
|
||||
#define FC_CAPTURE_AND_THROW( EXCEPTION_TYPE, ... ) \
|
||||
do { throw EXCEPTION_TYPE( FC_LOG_MESSAGE( error, "", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ) ); } while(0)
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
throw EXCEPTION_TYPE( FC_LOG_MESSAGE( error, "", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ) ); \
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
//#define FC_THROW( FORMAT, ... )
|
||||
// FC_INDIRECT_EXPAND workas around a bug in Visual C++ variadic macro processing that prevents it
|
||||
// from separating __VA_ARGS__ into separate tokens
|
||||
#define FC_INDIRECT_EXPAND(MACRO, ARGS) MACRO ARGS
|
||||
#define FC_THROW( ... ) \
|
||||
do { \
|
||||
throw fc::exception( FC_INDIRECT_EXPAND(FC_LOG_MESSAGE, ( error, __VA_ARGS__ )) ); \
|
||||
} while(0)
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
throw fc::exception( FC_INDIRECT_EXPAND(FC_LOG_MESSAGE, ( error, __VA_ARGS__ )) ); \
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
#define FC_EXCEPTION( EXCEPTION_TYPE, FORMAT, ... ) \
|
||||
EXCEPTION_TYPE( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) )
|
||||
|
|
@ -322,9 +327,9 @@ namespace fc
|
|||
* @param format - a const char* string with "${keys}"
|
||||
*/
|
||||
#define FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... ) \
|
||||
do { \
|
||||
throw EXCEPTION( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
|
||||
} while(0)
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
throw EXCEPTION( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -332,10 +337,10 @@ namespace fc
|
|||
* @brief Appends a log_message to the exception ER and rethrows it.
|
||||
*/
|
||||
#define FC_RETHROW_EXCEPTION( ER, LOG_LEVEL, FORMAT, ... ) \
|
||||
do { \
|
||||
ER.append_log( FC_LOG_MESSAGE( LOG_LEVEL, FORMAT, __VA_ARGS__ ) ); \
|
||||
throw;\
|
||||
} while(0)
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
ER.append_log( FC_LOG_MESSAGE( LOG_LEVEL, FORMAT, __VA_ARGS__ ) ); \
|
||||
throw; \
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
#define FC_LOG_AND_RETHROW( ) \
|
||||
catch( fc::exception& er ) { \
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
#include <fc/string.hpp>
|
||||
#include <fc/reflect/typename.hpp>
|
||||
#include <fc/optional.hpp>
|
||||
|
|
@ -226,5 +228,37 @@ namespace fc {
|
|||
temp_directory(const fc::path& tempFolder = fc::temp_directory_path());
|
||||
};
|
||||
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
// this code is known to work on linux and windows. It may work correctly on mac,
|
||||
// or it may need slight tweaks or extra includes. It's disabled now to avoid giving
|
||||
// a false sense of security.
|
||||
# define FC_HAS_SIMPLE_FILE_LOCK
|
||||
#endif
|
||||
#ifdef FC_HAS_SIMPLE_FILE_LOCK
|
||||
/** simple class which only allows one process to open any given file.
|
||||
* approximate usage:
|
||||
* int main() {
|
||||
* fc::simple_file_lock instance_lock("~/.my_app/.lock");
|
||||
* if (!instance_lock.try_lock()) {
|
||||
* elog("my_app is already running");
|
||||
* return 1;
|
||||
* }
|
||||
* // do stuff here, file will be unlocked when instance_lock goes out of scope
|
||||
* }
|
||||
*/
|
||||
class simple_lock_file
|
||||
{
|
||||
public:
|
||||
simple_lock_file(const path& lock_file_path);
|
||||
~simple_lock_file();
|
||||
bool try_lock();
|
||||
void unlock();
|
||||
private:
|
||||
class impl;
|
||||
std::unique_ptr<impl> my;
|
||||
};
|
||||
#endif // FC_HAS_SIMPLE_FILE_LOCK
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
32
include/fc/log/gelf_appender.hpp
Normal file
32
include/fc/log/gelf_appender.hpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include <fc/log/appender.hpp>
|
||||
#include <fc/log/logger.hpp>
|
||||
#include <fc/time.hpp>
|
||||
|
||||
namespace fc
|
||||
{
|
||||
// Log appender that sends log messages in JSON format over UDP
|
||||
// https://www.graylog2.org/resources/gelf/specification
|
||||
class gelf_appender : public appender
|
||||
{
|
||||
public:
|
||||
struct config
|
||||
{
|
||||
string endpoint = "127.0.0.1:12201";
|
||||
string host = "fc"; // the name of the host, source or application that sent this message (just passed through to GELF server)
|
||||
};
|
||||
|
||||
gelf_appender(const variant& args);
|
||||
~gelf_appender();
|
||||
virtual void log(const log_message& m) override;
|
||||
|
||||
private:
|
||||
class impl;
|
||||
fc::shared_ptr<impl> my;
|
||||
};
|
||||
} // namespace fc
|
||||
|
||||
#include <fc/reflect/reflect.hpp>
|
||||
FC_REFLECT(fc::gelf_appender::config,
|
||||
(endpoint)(host))
|
||||
|
|
@ -61,74 +61,77 @@ namespace fc
|
|||
#define DEFAULT_LOGGER
|
||||
#endif
|
||||
|
||||
|
||||
// suppress warning "conditional expression is constant" in the while(0) for visual c++
|
||||
// http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/
|
||||
#define FC_MULTILINE_MACRO_BEGIN do {
|
||||
#ifdef _MSC_VER
|
||||
# define FC_MULTILINE_MACRO_END \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable:4127)) \
|
||||
} while (0) \
|
||||
__pragma(warning(pop))
|
||||
#else
|
||||
# define FC_MULTILINE_MACRO_END } while (0)
|
||||
#endif
|
||||
|
||||
#define fc_dlog( LOGGER, FORMAT, ... ) \
|
||||
do { \
|
||||
if( (LOGGER).is_enabled( fc::log_level::debug ) ) { \
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
if( (LOGGER).is_enabled( fc::log_level::debug ) ) \
|
||||
(LOGGER).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
|
||||
} \
|
||||
} while (0)
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
#define fc_ilog( LOGGER, FORMAT, ... ) \
|
||||
do { \
|
||||
if( (LOGGER).is_enabled( fc::log_level::info ) ) { \
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
if( (LOGGER).is_enabled( fc::log_level::info ) ) \
|
||||
(LOGGER).log( FC_LOG_MESSAGE( info, FORMAT, __VA_ARGS__ ) ); \
|
||||
} \
|
||||
} while (0)
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
#define fc_wlog( LOGGER, FORMAT, ... ) \
|
||||
do { \
|
||||
if( (LOGGER).is_enabled( fc::log_level::warn ) ) { \
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
if( (LOGGER).is_enabled( fc::log_level::warn ) ) \
|
||||
(LOGGER).log( FC_LOG_MESSAGE( warn, FORMAT, __VA_ARGS__ ) ); \
|
||||
} \
|
||||
} while (0)
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
#define fc_elog( LOGGER, FORMAT, ... ) \
|
||||
do { \
|
||||
if( (LOGGER).is_enabled( fc::log_level::error ) ) { \
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
if( (LOGGER).is_enabled( fc::log_level::error ) ) \
|
||||
(LOGGER).log( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
|
||||
} \
|
||||
} while (0)
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
#define dlog( FORMAT, ... ) \
|
||||
do { \
|
||||
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::debug ) ) { \
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::debug ) ) \
|
||||
(fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
|
||||
} \
|
||||
} while (0)
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
/**
|
||||
* Sends the log message to a special 'user' log stream designed for messages that
|
||||
* the end user may like to see.
|
||||
*/
|
||||
#define ulog( FORMAT, ... ) \
|
||||
do { \
|
||||
if( (fc::logger::get("user")).is_enabled( fc::log_level::debug ) ) { \
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
if( (fc::logger::get("user")).is_enabled( fc::log_level::debug ) ) \
|
||||
(fc::logger::get("user")).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
|
||||
} \
|
||||
} while (0)
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
|
||||
#define ilog( FORMAT, ... ) \
|
||||
do { \
|
||||
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::info ) ) { \
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::info ) ) \
|
||||
(fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( info, FORMAT, __VA_ARGS__ ) ); \
|
||||
} \
|
||||
} while (0)
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
#define wlog( FORMAT, ... ) \
|
||||
do { \
|
||||
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::warn ) ) { \
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::warn ) ) \
|
||||
(fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( warn, FORMAT, __VA_ARGS__ ) ); \
|
||||
} \
|
||||
} while (0)
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
#define elog( FORMAT, ... ) \
|
||||
do { \
|
||||
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::error ) ) { \
|
||||
FC_MULTILINE_MACRO_BEGIN \
|
||||
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::error ) ) \
|
||||
(fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
|
||||
} \
|
||||
} while (0)
|
||||
FC_MULTILINE_MACRO_END
|
||||
|
||||
#include <boost/preprocessor/seq/for_each.hpp>
|
||||
#include <boost/preprocessor/seq/enum.hpp>
|
||||
|
|
@ -164,13 +167,13 @@ namespace fc
|
|||
// a slowdown.
|
||||
#ifdef FC_DISABLE_LOGGING
|
||||
# undef ulog
|
||||
# define ulog(...) do {} while(0)
|
||||
# define ulog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
|
||||
# undef elog
|
||||
# define elog(...) do {} while(0)
|
||||
# define elog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
|
||||
# undef wlog
|
||||
# define wlog(...) do {} while(0)
|
||||
# define wlog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
|
||||
# undef ilog
|
||||
# define ilog(...) do {} while(0)
|
||||
# define ilog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
|
||||
# undef dlog
|
||||
# define dlog(...) do {} while(0)
|
||||
# define dlog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
|
||||
#endif
|
||||
|
|
@ -618,7 +618,7 @@ std::string to_base58( const std::vector<char>& d )
|
|||
std::vector<char> from_base58( const std::string& base58_str ) {
|
||||
std::vector<unsigned char> out;
|
||||
if( !DecodeBase58( base58_str.c_str(), out ) ) {
|
||||
FC_THROW_EXCEPTION( exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) );
|
||||
FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) );
|
||||
}
|
||||
return std::vector<char>((const char*)out.data(), ((const char*)out.data())+out.size() );
|
||||
}
|
||||
|
|
@ -629,7 +629,7 @@ size_t from_base58( const std::string& base58_str, char* out_data, size_t out_da
|
|||
//slog( "%s", base58_str.c_str() );
|
||||
std::vector<unsigned char> out;
|
||||
if( !DecodeBase58( base58_str.c_str(), out ) ) {
|
||||
FC_THROW_EXCEPTION( exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) );
|
||||
FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) );
|
||||
}
|
||||
|
||||
memcpy( out_data, out.data(), out.size() );
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
# ifdef FC_HAS_SIMPLE_FILE_LOCK
|
||||
#include <sys/file.h>
|
||||
#include <fcntl.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace fc {
|
||||
|
|
@ -495,4 +499,101 @@ namespace fc {
|
|||
return appCurrentPath;
|
||||
}
|
||||
|
||||
|
||||
#ifdef FC_HAS_SIMPLE_FILE_LOCK
|
||||
class simple_lock_file::impl
|
||||
{
|
||||
public:
|
||||
#ifdef _WIN32
|
||||
HANDLE file_handle;
|
||||
#else
|
||||
int file_handle;
|
||||
#endif
|
||||
bool is_locked;
|
||||
path lock_file_path;
|
||||
|
||||
impl(const path& lock_file_path);
|
||||
~impl();
|
||||
|
||||
bool try_lock();
|
||||
void unlock();
|
||||
};
|
||||
|
||||
simple_lock_file::impl::impl(const path& lock_file_path) :
|
||||
is_locked(false),
|
||||
lock_file_path(lock_file_path),
|
||||
#ifdef _WIN32
|
||||
file_handle(INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
file_handle(-1)
|
||||
#endif
|
||||
{}
|
||||
|
||||
simple_lock_file::impl::~impl()
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
|
||||
bool simple_lock_file::impl::try_lock()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HANDLE fh = CreateFileA(lock_file_path.to_native_ansi_path().c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0, 0,
|
||||
OPEN_ALWAYS, 0, NULL);
|
||||
if (fh == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
is_locked = true;
|
||||
file_handle = fh;
|
||||
return true;
|
||||
#else
|
||||
int fd = open(lock_file_path.string().c_str(), O_RDWR|O_CREAT, 0644);
|
||||
if (fd < 0)
|
||||
return false;
|
||||
if (flock(fd, LOCK_EX|LOCK_NB) == -1)
|
||||
{
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
is_locked = true;
|
||||
file_handle = fd;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void simple_lock_file::impl::unlock()
|
||||
{
|
||||
#ifdef WIN32
|
||||
CloseHandle(file_handle);
|
||||
file_handle = INVALID_HANDLE_VALUE;
|
||||
is_locked = false;
|
||||
#else
|
||||
flock(file_handle, LOCK_UN);
|
||||
close(file_handle);
|
||||
file_handle = -1;
|
||||
is_locked = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
simple_lock_file::simple_lock_file(const path& lock_file_path) :
|
||||
my(new impl(lock_file_path))
|
||||
{
|
||||
}
|
||||
|
||||
simple_lock_file::~simple_lock_file()
|
||||
{
|
||||
}
|
||||
|
||||
bool simple_lock_file::try_lock()
|
||||
{
|
||||
return my->try_lock();
|
||||
}
|
||||
|
||||
void simple_lock_file::unlock()
|
||||
{
|
||||
my->unlock();
|
||||
}
|
||||
#endif // FC_HAS_SIMPLE_FILE_LOCK
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <fc/thread/scoped_lock.hpp>
|
||||
#include <fc/log/console_appender.hpp>
|
||||
#include <fc/log/file_appender.hpp>
|
||||
#include <fc/log/gelf_appender.hpp>
|
||||
#include <fc/variant.hpp>
|
||||
#include "console_defines.h"
|
||||
|
||||
|
|
@ -45,4 +46,6 @@ namespace fc {
|
|||
|
||||
static bool reg_console_appender = appender::register_appender<console_appender>( "console" );
|
||||
static bool reg_file_appender = appender::register_appender<file_appender>( "file" );
|
||||
static bool reg_gelf_appender = appender::register_appender<gelf_appender>( "gelf" );
|
||||
|
||||
} // namespace fc
|
||||
|
|
|
|||
139
src/log/gelf_appender.cpp
Normal file
139
src/log/gelf_appender.cpp
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
#include <fc/network/udp_socket.hpp>
|
||||
#include <fc/network/ip.hpp>
|
||||
#include <fc/network/resolve.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
#include <fc/log/gelf_appender.hpp>
|
||||
#include <fc/reflect/variant.hpp>
|
||||
#include <fc/thread/scoped_lock.hpp>
|
||||
#include <fc/thread/thread.hpp>
|
||||
#include <fc/variant.hpp>
|
||||
#include <fc/io/json.hpp>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <iomanip>
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
|
||||
namespace fc
|
||||
{
|
||||
|
||||
class gelf_appender::impl : public retainable
|
||||
{
|
||||
public:
|
||||
config cfg;
|
||||
optional<ip::endpoint> gelf_endpoint;
|
||||
udp_socket gelf_socket;
|
||||
boost::mutex socket_mutex;
|
||||
|
||||
impl(const config& c) :
|
||||
cfg(c)
|
||||
{
|
||||
}
|
||||
|
||||
~impl()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
gelf_appender::gelf_appender(const variant& args) :
|
||||
my(new impl(args.as<config>()))
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
// if it's a numeric address:port, this will parse it
|
||||
my->gelf_endpoint = ip::endpoint::from_string(my->cfg.endpoint);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
if (!my->gelf_endpoint)
|
||||
{
|
||||
// couldn't parse as a numeric ip address, try resolving as a DNS name.
|
||||
// This can yield, so don't do it in the catch block above
|
||||
string::size_type colon_pos = my->cfg.endpoint.find(':');
|
||||
try
|
||||
{
|
||||
uint16_t port = boost::lexical_cast<uint16_t>(my->cfg.endpoint.substr(colon_pos + 1, my->cfg.endpoint.size()));
|
||||
|
||||
string hostname = my->cfg.endpoint.substr( 0, colon_pos );
|
||||
std::vector<ip::endpoint> endpoints = resolve(hostname, port);
|
||||
if (endpoints.empty())
|
||||
FC_THROW_EXCEPTION(unknown_host_exception, "The host name can not be resolved: ${hostname}",
|
||||
("hostname", hostname));
|
||||
my->gelf_endpoint = endpoints.back();
|
||||
}
|
||||
catch (const boost::bad_lexical_cast&)
|
||||
{
|
||||
FC_THROW("Bad port: ${port}", ("port", my->cfg.endpoint.substr(colon_pos + 1, my->cfg.endpoint.size())));
|
||||
}
|
||||
}
|
||||
|
||||
if (my->gelf_endpoint)
|
||||
my->gelf_socket.open();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << "error opening GELF socket to endpoint ${endpoint}" << my->cfg.endpoint << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
gelf_appender::~gelf_appender()
|
||||
{}
|
||||
|
||||
void gelf_appender::log(const log_message& message)
|
||||
{
|
||||
if (!my->gelf_endpoint)
|
||||
return;
|
||||
|
||||
log_context context = message.get_context();
|
||||
|
||||
mutable_variant_object gelf_message;
|
||||
gelf_message["version"] = "1.1";
|
||||
gelf_message["host"] = my->cfg.host;
|
||||
gelf_message["short_message"] = format_string(message.get_format(), message.get_data());
|
||||
|
||||
gelf_message["timestamp"] = context.get_timestamp().time_since_epoch().count() / 1000000.;
|
||||
|
||||
switch (context.get_log_level())
|
||||
{
|
||||
case log_level::debug:
|
||||
gelf_message["level"] = 7; // debug
|
||||
break;
|
||||
case log_level::info:
|
||||
gelf_message["level"] = 6; // info
|
||||
break;
|
||||
case log_level::warn:
|
||||
gelf_message["level"] = 4; // warning
|
||||
break;
|
||||
case log_level::error:
|
||||
gelf_message["level"] = 3; // error
|
||||
break;
|
||||
case log_level::all:
|
||||
case log_level::off:
|
||||
// these shouldn't be used in log messages, but do something deterministic just in case
|
||||
gelf_message["level"] = 6; // info
|
||||
break;
|
||||
}
|
||||
|
||||
if (!context.get_context().empty())
|
||||
gelf_message["context"] = context.get_context();
|
||||
gelf_message["_line"] = context.get_line_number();
|
||||
gelf_message["_file"] = context.get_file();
|
||||
gelf_message["_method_name"] = context.get_method();
|
||||
gelf_message["_thread_name"] = context.get_thread_name();
|
||||
if (!context.get_task_name().empty())
|
||||
gelf_message["_task_name"] = context.get_task_name();
|
||||
|
||||
string gelf_message_as_string = json::to_string(gelf_message);
|
||||
std::shared_ptr<char> send_buffer(new char[gelf_message_as_string.size()], [](char* p){ delete[] p; });
|
||||
memcpy(send_buffer.get(), gelf_message_as_string.c_str(), gelf_message_as_string.size());
|
||||
|
||||
{
|
||||
scoped_lock<boost::mutex> lock(my->socket_mutex);
|
||||
my->gelf_socket.send_to(send_buffer, gelf_message_as_string.size(), *my->gelf_endpoint);
|
||||
}
|
||||
}
|
||||
} // fc
|
||||
|
|
@ -83,7 +83,9 @@ namespace fc
|
|||
|
||||
void log_context::append_context( const fc::string& s )
|
||||
{
|
||||
my->context += "->" + s;
|
||||
if (!my->context.empty())
|
||||
my->context += " -> ";
|
||||
my->context += s;
|
||||
}
|
||||
|
||||
log_context::~log_context(){}
|
||||
|
|
@ -158,6 +160,7 @@ namespace fc
|
|||
string log_context::get_host_name()const { return my->hostname; }
|
||||
time_point log_context::get_timestamp()const { return my->timestamp; }
|
||||
log_level log_context::get_log_level()const{ return my->level; }
|
||||
string log_context::get_context()const { return my->context; }
|
||||
|
||||
|
||||
variant log_context::to_variant()const
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace fc { namespace http {
|
|||
case fc::http::reply::RecordCreated: ss << "Record Created\r\n"; break;
|
||||
case fc::http::reply::NotFound: ss << "Not Found\r\n"; break;
|
||||
case fc::http::reply::Found: ss << "Found\r\n"; break;
|
||||
case fc::http::reply::InternalServerError: ss << "Internal Server Error\r\n"; break;
|
||||
default: ss << "Internal Server Error\r\n"; break;
|
||||
}
|
||||
for( uint32_t i = 0; i < rep.headers.size(); ++i ) {
|
||||
ss << rep.headers[i].key <<": "<<rep.headers[i].val <<"\r\n";
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ namespace fc { namespace rpc {
|
|||
*_out << ",\"result\":";
|
||||
json::to_stream( *_out, result);
|
||||
*_out << "}\n";
|
||||
_out->flush();
|
||||
}
|
||||
_out->flush();
|
||||
}
|
||||
void send_error( variant id, fc::exception& e )
|
||||
{
|
||||
|
|
@ -59,9 +59,9 @@ namespace fc { namespace rpc {
|
|||
*_out <<",\"code\":0,\"data\":";
|
||||
json::to_stream( *_out, variant(e));
|
||||
*_out << "}}\n";
|
||||
_out->flush();
|
||||
}
|
||||
//wlog( "exception: ${except}", ("except", variant(e)) );
|
||||
_out->flush();
|
||||
}
|
||||
|
||||
void handle_message( const variant_object& obj )
|
||||
|
|
@ -306,8 +306,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",\"params\":";
|
||||
fc::json::to_stream( *my->_out, named_args );
|
||||
*my->_out << "}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
}
|
||||
void json_connection::notice( const fc::string& method )
|
||||
{
|
||||
|
|
@ -316,8 +316,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << "{\"method\":";
|
||||
json::to_stream( *my->_out, method );
|
||||
*my->_out << "}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -342,8 +342,8 @@ namespace fc { namespace rpc {
|
|||
{
|
||||
*my->_out << ",\"params\":[]}\n";
|
||||
}
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
|
||||
|
|
@ -361,8 +361,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",\"params\":[";
|
||||
fc::json::to_stream( *my->_out, a1 );
|
||||
*my->_out << "]}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
future<variant> json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2 )
|
||||
|
|
@ -381,8 +381,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a2 );
|
||||
*my->_out << "]}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
future<variant> json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2, const variant& a3 )
|
||||
|
|
@ -403,8 +403,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a3 );
|
||||
*my->_out << "]}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
|
||||
|
|
@ -428,8 +428,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a4 );
|
||||
*my->_out << "]}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
|
||||
|
|
@ -455,8 +455,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a5 );
|
||||
*my->_out << "]}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
|
||||
|
|
@ -484,8 +484,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a6 );
|
||||
*my->_out << "]}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
future<variant> json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2, const variant& a3, const variant& a4, const variant& a5, const variant& a6, const variant& a7 )
|
||||
|
|
@ -514,8 +514,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a7 );
|
||||
*my->_out << "]}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
future<variant> json_connection::async_call( const fc::string& method,
|
||||
|
|
@ -554,8 +554,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a8 );
|
||||
*my->_out << "]}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
future<variant> json_connection::async_call( const fc::string& method,
|
||||
|
|
@ -597,8 +597,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a9 );
|
||||
*my->_out << "]}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
future<variant> json_connection::async_call( const fc::string& method,
|
||||
|
|
@ -643,8 +643,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a10 );
|
||||
*my->_out << "]}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
|
||||
|
|
@ -665,8 +665,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",\"params\":";
|
||||
fc::json::to_stream( *my->_out, named_args );
|
||||
*my->_out << "}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
future<variant> json_connection::async_call( const fc::string& method )
|
||||
|
|
@ -680,8 +680,8 @@ namespace fc { namespace rpc {
|
|||
*my->_out << ",\"method\":";
|
||||
json::to_stream( *my->_out, method );
|
||||
*my->_out << "}\n";
|
||||
my->_out->flush();
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue