Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
S
spdlog
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
spdlog
Commits
c962c883
Commit
c962c883
authored
Apr 20, 2018
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed linux port of v1.x
parent
c80cc330
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
915 additions
and
935 deletions
+915
-935
bench.cpp
example/bench.cpp
+1
-0
example.cpp
example/example.cpp
+102
-104
async.h
include/spdlog/async.h
+1
-1
async_logger_impl.h
include/spdlog/details/async_logger_impl.h
+14
-14
logger_impl.h
include/spdlog/details/logger_impl.h
+0
-3
os.h
include/spdlog/details/os.h
+1
-13
registry.h
include/spdlog/details/registry.h
+9
-10
traits.h
include/spdlog/details/traits.h
+43
-31
logger.h
include/spdlog/logger.h
+1
-1
android_sink.h
include/spdlog/sinks/android_sink.h
+73
-75
ansicolor_sink.h
include/spdlog/sinks/ansicolor_sink.h
+122
-128
file_sinks.h
include/spdlog/sinks/file_sinks.h
+283
-283
stdout_color_sinks.h
include/spdlog/sinks/stdout_color_sinks.h
+34
-35
stdout_sinks.h
include/spdlog/sinks/stdout_sinks.h
+68
-63
syslog_sink.h
include/spdlog/sinks/syslog_sink.h
+54
-58
wincolor_sink.h
include/spdlog/sinks/wincolor_sink.h
+106
-110
spdlog.h
include/spdlog/spdlog.h
+1
-3
includes.h
tests/includes.h
+2
-3
No files found.
example/bench.cpp
View file @
c962c883
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
// bench.cpp : spdlog benchmarks
// bench.cpp : spdlog benchmarks
//
//
#include "spdlog/async.h"
#include "spdlog/async.h"
#include "spdlog/sinks/file_sinks.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/spdlog.h"
#include "spdlog/spdlog.h"
...
...
example/example.cpp
View file @
c962c883
//
//
// Copyright(c) 2015 Gabi Melman.
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
//
...
@@ -10,9 +10,8 @@
...
@@ -10,9 +10,8 @@
#define SPDLOG_TRACE_ON
#define SPDLOG_TRACE_ON
#define SPDLOG_DEBUG_ON
#define SPDLOG_DEBUG_ON
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/file_sinks.h"
#include "spdlog/sinks/file_sinks.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include <iostream>
#include <iostream>
#include <memory>
#include <memory>
...
@@ -25,104 +24,103 @@ namespace spd = spdlog;
...
@@ -25,104 +24,103 @@ namespace spd = spdlog;
int
main
(
int
,
char
*
[])
int
main
(
int
,
char
*
[])
{
{
try
try
{
{
auto
console
=
spdlog
::
stdout_color_st
(
"console"
);
auto
console
=
spdlog
::
stdout_color_st
(
"console"
);
console
->
info
(
"Welcome to spdlog!"
);
console
->
info
(
"Welcome to spdlog!"
);
console
->
info
(
"Welcome to spdlog!"
);
console
->
info
(
"Welcome to spdlog!"
);
console
->
error
(
"Some error message with arg: {}"
,
1
);
console
->
error
(
"Some error message with arg: {}"
,
1
);
err_handler_example
();
err_handler_example
();
// Formatting examples
// Formatting examples
console
->
warn
(
"Easy padding in numbers like {:08d}"
,
12
);
console
->
warn
(
"Easy padding in numbers like {:08d}"
,
12
);
console
->
critical
(
"Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}"
,
42
);
console
->
critical
(
"Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}"
,
42
);
console
->
info
(
"Support for floats {:03.2f}"
,
1.23456
);
console
->
info
(
"Support for floats {:03.2f}"
,
1.23456
);
console
->
info
(
"Positional args are {1} {0}.."
,
"too"
,
"supported"
);
console
->
info
(
"Positional args are {1} {0}.."
,
"too"
,
"supported"
);
console
->
info
(
"{:<30}"
,
"left aligned"
);
console
->
info
(
"{:<30}"
,
"left aligned"
);
spd
::
get
(
"console"
)
->
info
(
"loggers can be retrieved from a global registry using the spdlog::get(logger_name) function"
);
spd
::
get
(
"console"
)
->
info
(
"loggers can be retrieved from a global registry using the spdlog::get(logger_name) function"
);
// Create basic file logger (not rotated)
// Create basic file logger (not rotated)
auto
my_logger
=
spd
::
basic_logger_mt
(
"basic_logger"
,
"logs/basic-log.txt"
);
auto
my_logger
=
spd
::
basic_logger_mt
(
"basic_logger"
,
"logs/basic-log.txt"
);
my_logger
->
info
(
"Some log message"
);
my_logger
->
info
(
"Some log message"
);
// Create a file rotating logger with 5mb size max and 3 rotated files
// Create a file rotating logger with 5mb size max and 3 rotated files
auto
rotating_logger
=
spd
::
rotating_logger_mt
(
"some_logger_name"
,
"logs/rotating.txt"
,
1048576
*
5
,
3
);
auto
rotating_logger
=
spd
::
rotating_logger_mt
(
"some_logger_name"
,
"logs/rotating.txt"
,
1048576
*
5
,
3
);
for
(
int
i
=
0
;
i
<
10
;
++
i
)
for
(
int
i
=
0
;
i
<
10
;
++
i
)
{
{
rotating_logger
->
info
(
"{} * {} equals {:>10}"
,
i
,
i
,
i
*
i
);
rotating_logger
->
info
(
"{} * {} equals {:>10}"
,
i
,
i
,
i
*
i
);
}
}
// Create a daily logger - a new file is created every day on 2:30am
// Create a daily logger - a new file is created every day on 2:30am
auto
daily_logger
=
spd
::
daily_logger_mt
(
"daily_logger"
,
"logs/daily.txt"
,
2
,
30
);
auto
daily_logger
=
spd
::
daily_logger_mt
(
"daily_logger"
,
"logs/daily.txt"
,
2
,
30
);
// trigger flush if the log severity is error or higher
// trigger flush if the log severity is error or higher
daily_logger
->
flush_on
(
spd
::
level
::
err
);
daily_logger
->
flush_on
(
spd
::
level
::
err
);
daily_logger
->
info
(
123.44
);
daily_logger
->
info
(
123.44
);
// Customize msg format for all messages
// Customize msg format for all messages
//spd::set_pattern("[%^+++%$] [%H:%M:%S %z] [thread %t] %v"); //crash
// spd::set_pattern("[%^+++%$] [%H:%M:%S %z] [thread %t] %v"); //crash
console
->
info
(
"This an info message with custom format"
);
console
->
info
(
"This an info message with custom format"
);
console
->
error
(
"This an error message with custom format"
);
console
->
error
(
"This an error message with custom format"
);
// Runtime log levels
// Runtime log levels
spd
::
set_level
(
spd
::
level
::
info
);
// Set global log level to info
spd
::
set_level
(
spd
::
level
::
info
);
// Set global log level to info
console
->
debug
(
"This message should not be displayed!"
);
console
->
debug
(
"This message should not be displayed!"
);
console
->
set_level
(
spd
::
level
::
debug
);
// Set specific logger's log level
console
->
set_level
(
spd
::
level
::
debug
);
// Set specific logger's log level
console
->
debug
(
"This message should be displayed.."
);
console
->
debug
(
"This message should be displayed.."
);
// Compile time log levels
// Compile time log levels
// define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON
// define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON
SPDLOG_TRACE
(
console
,
"Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}"
,
1
,
3.23
);
SPDLOG_TRACE
(
console
,
"Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}"
,
1
,
3.23
);
SPDLOG_DEBUG
(
console
,
"Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}"
,
1
,
3.23
);
SPDLOG_DEBUG
(
console
,
"Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}"
,
1
,
3.23
);
// Asynchronous logging is very fast..
// Asynchronous logging is very fast..
// Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
// Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
async_example
();
async_example
();
// Log user-defined types example
// Log user-defined types example
user_defined_example
();
user_defined_example
();
// Change default log error handler
// Change default log error handler
err_handler_example
();
err_handler_example
();
// Apply a function on all registered loggers
// Apply a function on all registered loggers
spd
::
apply_all
([
&
](
std
::
shared_ptr
<
spdlog
::
logger
>
l
)
{
l
->
info
(
"End of example."
);
});
spd
::
apply_all
([
&
](
std
::
shared_ptr
<
spdlog
::
logger
>
l
)
{
l
->
info
(
"End of example."
);
});
// Release and close all loggers
// Release and close all loggers
spdlog
::
drop_all
();
spdlog
::
drop_all
();
}
}
// Exceptions will only be thrown upon failed logger or sink construction (not during logging)
// Exceptions will only be thrown upon failed logger or sink construction (not during logging)
catch
(
const
spd
::
spdlog_ex
&
ex
)
catch
(
const
spd
::
spdlog_ex
&
ex
)
{
{
std
::
cout
<<
"Log init failed: "
<<
ex
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"Log init failed: "
<<
ex
.
what
()
<<
std
::
endl
;
return
1
;
return
1
;
}
}
}
}
// must be included to use async logger
// must be included to use async logger
#include "spdlog/async.h"
#include "spdlog/async.h"
void
async_example
()
void
async_example
()
{
{
auto
async_file
=
spd
::
basic_logger_mt
<
spdlog
::
create_async
>
(
"async_file_logger"
,
"logs/async_log.txt"
);
auto
async_file
=
spd
::
basic_logger_mt
<
spdlog
::
create_async
>
(
"async_file_logger"
,
"logs/async_log.txt"
);
for
(
int
i
=
0
;
i
<
100
;
++
i
)
for
(
int
i
=
0
;
i
<
100
;
++
i
)
{
{
async_file
->
info
(
"Async message #{}"
,
i
);
async_file
->
info
(
"Async message #{}"
,
i
);
}
}
// you can also modify thread pool settings *before* creating the logger:
// you can also modify thread pool settings *before* creating the logger:
// spdlog::init_thread_pool(32768, 4); // queue with 32k of pre allocated items and 4 backing threads.
// spdlog::init_thread_pool(32768, 4); // queue with 32k of pre allocated items and 4 backing threads.
// if not called a defaults are: preallocated 8192 queue items and 1 worker thread.
// if not called a defaults are: preallocated 8192 queue items and 1 worker thread.
}
}
// syslog example (linux/osx/freebsd)
// syslog example (linux/osx/freebsd)
#ifndef _WIN32
#ifndef _WIN32
#incude "spdlog/sinks/syslog_sink.h"
#inc
l
ude "spdlog/sinks/syslog_sink.h"
void
syslog_example
()
void
syslog_example
()
{
{
std
::
string
ident
=
"spdlog-example"
;
std
::
string
ident
=
"spdlog-example"
;
auto
syslog_logger
=
spd
::
syslog_logger
(
"syslog"
,
ident
,
LOG_PID
);
auto
syslog_logger
=
spd
::
syslog_logger
(
"syslog"
,
ident
,
LOG_PID
);
syslog_logger
->
warn
(
"This is warning that will end up in syslog."
);
syslog_logger
->
warn
(
"This is warning that will end up in syslog."
);
}
}
#endif
#endif
...
@@ -131,9 +129,9 @@ void syslog_example()
...
@@ -131,9 +129,9 @@ void syslog_example()
#incude "spdlog/sinks/android_sink.h"
#incude "spdlog/sinks/android_sink.h"
void
android_example
()
void
android_example
()
{
{
std
::
string
tag
=
"spdlog-android"
;
std
::
string
tag
=
"spdlog-android"
;
auto
android_logger
=
spd
::
android_logger
(
"android"
,
tag
);
auto
android_logger
=
spd
::
android_logger
(
"android"
,
tag
);
android_logger
->
critical
(
"Use
\"
adb shell logcat
\"
to view this message."
);
android_logger
->
critical
(
"Use
\"
adb shell logcat
\"
to view this message."
);
}
}
#endif
#endif
...
@@ -141,18 +139,18 @@ void android_example()
...
@@ -141,18 +139,18 @@ void android_example()
// user defined types logging by implementing operator<<
// user defined types logging by implementing operator<<
struct
my_type
struct
my_type
{
{
int
i
;
int
i
;
template
<
typename
OStream
>
template
<
typename
OStream
>
friend
OStream
&
operator
<<
(
OStream
&
os
,
const
my_type
&
c
)
friend
OStream
&
operator
<<
(
OStream
&
os
,
const
my_type
&
c
)
{
{
return
os
<<
"[my_type i="
<<
c
.
i
<<
"]"
;
return
os
<<
"[my_type i="
<<
c
.
i
<<
"]"
;
}
}
};
};
#include "spdlog/fmt/ostr.h" // must be included
#include "spdlog/fmt/ostr.h" // must be included
void
user_defined_example
()
void
user_defined_example
()
{
{
spd
::
get
(
"console"
)
->
info
(
"user defined type: {}"
,
my_type
{
14
});
spd
::
get
(
"console"
)
->
info
(
"user defined type: {}"
,
my_type
{
14
});
}
}
//
//
...
@@ -160,8 +158,8 @@ void user_defined_example()
...
@@ -160,8 +158,8 @@ void user_defined_example()
//
//
void
err_handler_example
()
void
err_handler_example
()
{
{
// can be set globaly or per logger(logger->set_error_handler(..))
// can be set globaly or per logger(logger->set_error_handler(..))
spdlog
::
set_error_handler
([](
const
std
::
string
&
msg
)
{
spd
::
get
(
"console"
)
->
error
(
"*******my err handler: {}"
,
msg
);
});
spdlog
::
set_error_handler
([](
const
std
::
string
&
msg
)
{
spd
::
get
(
"console"
)
->
error
(
"*******my err handler: {}"
,
msg
);
});
spd
::
get
(
"console"
)
->
info
(
"some invalid message to trigger an error {}{}{}{}"
,
3
);
spd
::
get
(
"console"
)
->
info
(
"some invalid message to trigger an error {}{}{}{}"
,
3
);
//
spd::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
//
spd::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
}
}
include/spdlog/async.h
View file @
c962c883
...
@@ -41,7 +41,7 @@ struct create_async
...
@@ -41,7 +41,7 @@ struct create_async
auto
new_logger
=
std
::
make_shared
<
async_logger
>
(
logger_name
,
std
::
move
(
sink
),
std
::
move
(
tp
),
async_overflow_policy
::
block_retry
);
auto
new_logger
=
std
::
make_shared
<
async_logger
>
(
logger_name
,
std
::
move
(
sink
),
std
::
move
(
tp
),
async_overflow_policy
::
block_retry
);
registry
::
instance
().
register_and_init
(
new_logger
);
registry
::
instance
().
register_and_init
(
new_logger
);
return
new_logger
;
return
new_logger
;
}
}
};
};
template
<
typename
Sink
,
typename
...
SinkArgs
>
template
<
typename
Sink
,
typename
...
SinkArgs
>
...
...
include/spdlog/details/async_logger_impl.h
View file @
c962c883
...
@@ -37,18 +37,18 @@ inline spdlog::async_logger::async_logger(
...
@@ -37,18 +37,18 @@ inline spdlog::async_logger::async_logger(
// send the log message to the thread pool
// send the log message to the thread pool
inline
void
spdlog
::
async_logger
::
_sink_it
(
details
::
log_msg
&
msg
)
inline
void
spdlog
::
async_logger
::
_sink_it
(
details
::
log_msg
&
msg
)
{
{
#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
_incr_msg_counter
(
msg
);
_incr_msg_counter
(
msg
);
#endif
#endif
if
(
auto
pool_ptr
=
_thread_pool
.
lock
())
if
(
auto
pool_ptr
=
_thread_pool
.
lock
())
{
{
pool_ptr
->
post_log
(
shared_from_this
(),
std
::
move
(
msg
),
_overflow_policy
);
pool_ptr
->
post_log
(
shared_from_this
(),
std
::
move
(
msg
),
_overflow_policy
);
}
}
else
else
{
{
throw
spdlog_ex
(
"async log: thread pool doens't exist anymore"
);
throw
spdlog_ex
(
"async log: thread pool doens't exist anymore"
);
}
}
}
}
// send flush request to the thread pool
// send flush request to the thread pool
...
@@ -89,10 +89,10 @@ inline void spdlog::async_logger::_backend_log(details::log_msg &incoming_log_ms
...
@@ -89,10 +89,10 @@ inline void spdlog::async_logger::_backend_log(details::log_msg &incoming_log_ms
_err_handler
(
"Unknown exception in async logger "
+
_name
);
_err_handler
(
"Unknown exception in async logger "
+
_name
);
}
}
if
(
_should_flush
(
incoming_log_msg
))
if
(
_should_flush
(
incoming_log_msg
))
{
{
_backend_flush
();
_backend_flush
();
}
}
}
}
inline
void
spdlog
::
async_logger
::
_backend_flush
()
inline
void
spdlog
::
async_logger
::
_backend_flush
()
...
...
include/spdlog/details/logger_impl.h
View file @
c962c883
...
@@ -5,9 +5,6 @@
...
@@ -5,9 +5,6 @@
#pragma once
#pragma once
#include "../logger.h"
#include "../sinks/stdout_sinks.h"
#include <memory>
#include <memory>
#include <string>
#include <string>
...
...
include/spdlog/details/os.h
View file @
c962c883
...
@@ -13,11 +13,11 @@
...
@@ -13,11 +13,11 @@
#include <cstring>
#include <cstring>
#include <ctime>
#include <ctime>
#include <functional>
#include <functional>
#include <mutex>
#include <string>
#include <string>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/types.h>
#include <thread>
#include <thread>
#include <mutex>
#ifdef _WIN32
#ifdef _WIN32
...
@@ -476,18 +476,6 @@ inline bool in_terminal(FILE *file)
...
@@ -476,18 +476,6 @@ inline bool in_terminal(FILE *file)
#endif
#endif
}
}
// stdout/stderr global mutexes
inline
std
::
mutex
&
stdout_mutex
()
{
static
std
::
mutex
&
mutex
=
std
::
mutex
{};
return
mutex
;
}
inline
std
::
mutex
&
stderr_mutex
()
{
static
std
::
mutex
&
mutex
=
std
::
mutex
{};
return
mutex
;
}
}
// namespace os
}
// namespace os
}
// namespace details
}
// namespace details
}
// namespace spdlog
}
// namespace spdlog
include/spdlog/details/registry.h
View file @
c962c883
...
@@ -148,16 +148,15 @@ public:
...
@@ -148,16 +148,15 @@ public:
void
drop_all
()
void
drop_all
()
{
{
{
{
std
::
lock_guard
<
Mutex
>
lock
(
_mutex
);
std
::
lock_guard
<
Mutex
>
lock
(
_mutex
);
_loggers
.
clear
();
_loggers
.
clear
();
}
}
{
{
std
::
lock_guard
<
Mutex
>
lock
(
_tp_mutex
);
std
::
lock_guard
<
Mutex
>
lock
(
_tp_mutex
);
_tp
.
reset
();
_tp
.
reset
();
}
}
}
}
Mutex
&
tp_mutex
()
Mutex
&
tp_mutex
()
...
...
include/spdlog/details/traits.h
View file @
c962c883
...
@@ -6,41 +6,53 @@
...
@@ -6,41 +6,53 @@
#include "stdio.h"
#include "stdio.h"
namespace
spdlog
{
namespace
spdlog
{
namespace
details
{
namespace
details
{
struct
console_stdout_trait
struct
console_stdout_trait
{
{
static
FILE
*
stream
()
{
return
stdout
;}
static
FILE
*
stream
()
{
return
stdout
;
}
#ifdef _WIN32
#ifdef _WIN32
static
HANDLE
handle
()
{
return
::
GetStdHandle
(
STD_OUTPUT_HANDLE
);
}
static
HANDLE
handle
()
{
return
::
GetStdHandle
(
STD_OUTPUT_HANDLE
);
}
#endif
#endif
};
};
struct
console_stderr_trait
struct
console_stderr_trait
{
{
static
FILE
*
stream
()
{
return
stdout
;
}
static
FILE
*
stream
()
{
return
stdout
;
}
#ifdef _WIN32
#ifdef _WIN32
static
HANDLE
handle
()
{
return
::
GetStdHandle
(
STD_ERROR_HANDLE
);
}
static
HANDLE
handle
()
{
return
::
GetStdHandle
(
STD_ERROR_HANDLE
);
}
#endif
#endif
};
};
struct
console_mutex_trait
struct
console_mutex_trait
{
{
using
mutex_t
=
std
::
mutex
;
using
mutex_t
=
std
::
mutex
;
static
mutex_t
&
console_mutex
()
static
mutex_t
&
console_mutex
()
{
{
static
auto
&
mutex
=
mutex_t
{}
;
static
mutex_t
mutex
;
return
mutex
;
return
mutex
;
}
}
};
};
struct
console_null_mutex_trait
struct
console_null_mutex_trait
{
{
using
mutex_t
=
null_mutex
;
using
mutex_t
=
null_mutex
;
static
mutex_t
&
console_mutex
()
static
mutex_t
&
console_mutex
()
{
{
static
auto
mutex
=
mutex_t
{}
;
static
mutex_t
mutex
;
return
mutex
;
return
mutex
;
}
}
};
};
}
}
// namespace details
}
}
// namespace spdlog
include/spdlog/logger.h
View file @
c962c883
...
@@ -13,8 +13,8 @@
...
@@ -13,8 +13,8 @@
// 3. Pass the formatted message to its sinks to performa the actual logging
// 3. Pass the formatted message to its sinks to performa the actual logging
#include "common.h"
#include "common.h"
#include "sinks/sink.h"
#include "formatter.h"
#include "formatter.h"
#include "sinks/sink.h"
#include <memory>
#include <memory>
#include <string>
#include <string>
...
...
include/spdlog/sinks/android_sink.h
View file @
c962c883
...
@@ -21,81 +21,79 @@
...
@@ -21,81 +21,79 @@
#endif
#endif
namespace
spdlog
{
namespace
spdlog
{
namespace
sinks
{
namespace
sinks
{
/*
/*
* Android sink (logging using __android_log_write)
* Android sink (logging using __android_log_write)
* __android_log_write is thread-safe. No lock is needed.
* __android_log_write is thread-safe. No lock is needed.
*/
*/
class
android_sink
:
public
sink
class
android_sink
:
public
sink
{
{
public
:
public
:
explicit
android_sink
(
const
std
::
string
&
tag
=
"spdlog"
,
bool
use_raw_msg
=
false
)
explicit
android_sink
(
const
std
::
string
&
tag
=
"spdlog"
,
bool
use_raw_msg
=
false
)
:
_tag
(
tag
)
:
_tag
(
tag
)
,
_use_raw_msg
(
use_raw_msg
)
,
_use_raw_msg
(
use_raw_msg
)
{
{
}
}
void
log
(
const
details
::
log_msg
&
msg
)
override
void
log
(
const
details
::
log_msg
&
msg
)
override
{
{
const
android_LogPriority
priority
=
convert_to_android
(
msg
.
level
);
const
android_LogPriority
priority
=
convert_to_android
(
msg
.
level
);
const
char
*
msg_output
=
(
_use_raw_msg
?
msg
.
raw
.
c_str
()
:
msg
.
formatted
.
c_str
());
const
char
*
msg_output
=
(
_use_raw_msg
?
msg
.
raw
.
c_str
()
:
msg
.
formatted
.
c_str
());
// See system/core/liblog/logger_write.c for explanation of return value
// See system/core/liblog/logger_write.c for explanation of return value
int
ret
=
__android_log_write
(
priority
,
_tag
.
c_str
(),
msg_output
);
int
ret
=
__android_log_write
(
priority
,
_tag
.
c_str
(),
msg_output
);
int
retry_count
=
0
;
int
retry_count
=
0
;
while
((
ret
==
-
11
/*EAGAIN*/
)
&&
(
retry_count
<
SPDLOG_ANDROID_RETRIES
))
while
((
ret
==
-
11
/*EAGAIN*/
)
&&
(
retry_count
<
SPDLOG_ANDROID_RETRIES
))
{
{
details
::
os
::
sleep_for_millis
(
5
);
details
::
os
::
sleep_for_millis
(
5
);
ret
=
__android_log_write
(
priority
,
_tag
.
c_str
(),
msg_output
);
ret
=
__android_log_write
(
priority
,
_tag
.
c_str
(),
msg_output
);
retry_count
++
;
retry_count
++
;
}
}
if
(
ret
<
0
)
if
(
ret
<
0
)
{
{
throw
spdlog_ex
(
"__android_log_write() failed"
,
ret
);
throw
spdlog_ex
(
"__android_log_write() failed"
,
ret
);
}
}
}
}
void
flush
()
override
{}
void
flush
()
override
{}
private
:
private
:
static
android_LogPriority
convert_to_android
(
spdlog
::
level
::
level_enum
level
)
static
android_LogPriority
convert_to_android
(
spdlog
::
level
::
level_enum
level
)
{
{
switch
(
level
)
switch
(
level
)
{
{
case
spdlog
:
:
level
::
trace
:
case
spdlog
:
:
level
::
trace
:
return
ANDROID_LOG_VERBOSE
;
return
ANDROID_LOG_VERBOSE
;
case
spdlog
:
:
level
::
debug
:
case
spdlog
:
:
level
::
debug
:
return
ANDROID_LOG_DEBUG
;
return
ANDROID_LOG_DEBUG
;
case
spdlog
:
:
level
::
info
:
case
spdlog
:
:
level
::
info
:
return
ANDROID_LOG_INFO
;
return
ANDROID_LOG_INFO
;
case
spdlog
:
:
level
::
warn
:
case
spdlog
:
:
level
::
warn
:
return
ANDROID_LOG_WARN
;
return
ANDROID_LOG_WARN
;
case
spdlog
:
:
level
::
err
:
case
spdlog
:
:
level
::
err
:
return
ANDROID_LOG_ERROR
;
return
ANDROID_LOG_ERROR
;
case
spdlog
:
:
level
::
critical
:
case
spdlog
:
:
level
::
critical
:
return
ANDROID_LOG_FATAL
;
return
ANDROID_LOG_FATAL
;
default
:
default
:
return
ANDROID_LOG_DEFAULT
;
return
ANDROID_LOG_DEFAULT
;
}
}
}
}
std
::
string
_tag
;
std
::
string
_tag
;
bool
_use_raw_msg
;
bool
_use_raw_msg
;
};
};
}
// namespace sinks
}
// namespace sinks
// Create and register android syslog logger
// Create and register android syslog logger
template
<
typename
Factory
=
default_factory
>
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
android_logger
(
const
std
::
string
&
logger_name
,
const
std
::
string
&
tag
=
"spdlog"
)
inline
std
::
shared_ptr
<
logger
>
android_logger
(
const
std
::
string
&
logger_name
,
const
std
::
string
&
tag
=
"spdlog"
)
{
{
return
return
Factory
::
template
create
<
sinks
::
android_sink
>
(
logger_name
,
tag
);
return
return
Factory
::
template
create
<
sinks
::
android_sink
>
(
logger_name
,
tag
);
}
}
}
// namespace spdlog
}
// namespace spdlog
...
...
include/spdlog/sinks/ansicolor_sink.h
View file @
c962c883
...
@@ -9,137 +9,131 @@
...
@@ -9,137 +9,131 @@
#include "../details/os.h"
#include "../details/os.h"
#include "../details/traits.h"
#include "../details/traits.h"
#include <string>
#include <unordered_map>
#include <memory>
#include <memory>
#include <mutex>
#include <mutex>
#include <string>
#include <unordered_map>
namespace
spdlog
{
namespace
spdlog
{
namespace
sinks
{
namespace
sinks
{
/**
/**
* This sink prefixes the output with an ANSI escape sequence color code depending on the severity
* This sink prefixes the output with an ANSI escape sequence color code depending on the severity
* of the message.
* of the message.
* If no color terminal detected, omit the escape codes.
* If no color terminal detected, omit the escape codes.
*/
*/
template
<
class
StdoutTrait
,
class
ConsoleMutexTrait
>
template
<
class
StdoutTrait
,
class
ConsoleMutexTrait
>
class
ansicolor_sink
:
public
sink
class
ansicolor_sink
:
public
sink
{
{
public
:
public
:
using
mutex_t
=
typename
ConsoleMutexTrait
::
mutex_t
;
using
mutex_t
=
typename
ConsoleMutexTrait
::
mutex_t
;
ansicolor_sink
()
ansicolor_sink
()
:
target_file_
(
StdoutTrait
::
stream
()),
:
target_file_
(
StdoutTrait
::
stream
())
_mutex
(
ConsoleMutexTrait
::
mutex
())
,
_mutex
(
ConsoleMutexTrait
::
console_mutex
())
{
{
should_do_colors_
=
details
::
os
::
in_terminal
(
file
)
&&
details
::
os
::
is_color_terminal
();
should_do_colors_
=
details
::
os
::
in_terminal
(
target_file_
)
&&
details
::
os
::
is_color_terminal
();
colors_
[
level
::
trace
]
=
white
;
colors_
[
level
::
trace
]
=
white
;
colors_
[
level
::
debug
]
=
cyan
;
colors_
[
level
::
debug
]
=
cyan
;
colors_
[
level
::
info
]
=
green
;
colors_
[
level
::
info
]
=
green
;
colors_
[
level
::
warn
]
=
yellow
+
bold
;
colors_
[
level
::
warn
]
=
yellow
+
bold
;
colors_
[
level
::
err
]
=
red
+
bold
;
colors_
[
level
::
err
]
=
red
+
bold
;
colors_
[
level
::
critical
]
=
bold
+
on_red
;
colors_
[
level
::
critical
]
=
bold
+
on_red
;
colors_
[
level
::
off
]
=
reset
;
colors_
[
level
::
off
]
=
reset
;
}
}
~
ansicolor_sink
()
override
~
ansicolor_sink
()
override
=
default
;
{
_flush
();
ansicolor_sink
(
const
ansicolor_sink
&
other
)
=
delete
;
}
ansicolor_sink
&
operator
=
(
const
ansicolor_sink
&
other
)
=
delete
;
ansicolor_sink
(
const
ansicolor_sink
&
other
)
=
delete
;
void
set_color
(
level
::
level_enum
color_level
,
const
std
::
string
&
color
)
ansicolor_sink
&
operator
=
(
const
ansicolor_sink
&
other
)
=
delete
;
{
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
void
set_color
(
level
::
level_enum
color_level
,
const
std
::
string
&
color
)
colors_
[
color_level
]
=
color
;
{
}
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
colors_
[
color_level
]
=
color
;
/// Formatting codes
}
const
std
::
string
reset
=
"
\033
[m"
;
const
std
::
string
bold
=
"
\033
[1m"
;
/// Formatting codes
const
std
::
string
dark
=
"
\033
[2m"
;
const
std
::
string
reset
=
"
\033
[m"
;
const
std
::
string
underline
=
"
\033
[4m"
;
const
std
::
string
bold
=
"
\033
[1m"
;
const
std
::
string
blink
=
"
\033
[5m"
;
const
std
::
string
dark
=
"
\033
[2m"
;
const
std
::
string
reverse
=
"
\033
[7m"
;
const
std
::
string
underline
=
"
\033
[4m"
;
const
std
::
string
concealed
=
"
\033
[8m"
;
const
std
::
string
blink
=
"
\033
[5m"
;
const
std
::
string
clear_line
=
"
\033
[K"
;
const
std
::
string
reverse
=
"
\033
[7m"
;
const
std
::
string
concealed
=
"
\033
[8m"
;
// Foreground colors
const
std
::
string
clear_line
=
"
\033
[K"
;
const
std
::
string
black
=
"
\033
[30m"
;
const
std
::
string
red
=
"
\033
[31m"
;
// Foreground colors
const
std
::
string
green
=
"
\033
[32m"
;
const
std
::
string
black
=
"
\033
[30m"
;
const
std
::
string
yellow
=
"
\033
[33m"
;
const
std
::
string
red
=
"
\033
[31m"
;
const
std
::
string
blue
=
"
\033
[34m"
;
const
std
::
string
green
=
"
\033
[32m"
;
const
std
::
string
magenta
=
"
\033
[35m"
;
const
std
::
string
yellow
=
"
\033
[33m"
;
const
std
::
string
cyan
=
"
\033
[36m"
;
const
std
::
string
blue
=
"
\033
[34m"
;
const
std
::
string
white
=
"
\033
[37m"
;
const
std
::
string
magenta
=
"
\033
[35m"
;
const
std
::
string
cyan
=
"
\033
[36m"
;
/// Background colors
const
std
::
string
white
=
"
\033
[37m"
;
const
std
::
string
on_black
=
"
\033
[40m"
;
const
std
::
string
on_red
=
"
\033
[41m"
;
/// Background colors
const
std
::
string
on_green
=
"
\033
[42m"
;
const
std
::
string
on_black
=
"
\033
[40m"
;
const
std
::
string
on_yellow
=
"
\033
[43m"
;
const
std
::
string
on_red
=
"
\033
[41m"
;
const
std
::
string
on_blue
=
"
\033
[44m"
;
const
std
::
string
on_green
=
"
\033
[42m"
;
const
std
::
string
on_magenta
=
"
\033
[45m"
;
const
std
::
string
on_yellow
=
"
\033
[43m"
;
const
std
::
string
on_cyan
=
"
\033
[46m"
;
const
std
::
string
on_blue
=
"
\033
[44m"
;
const
std
::
string
on_white
=
"
\033
[47m"
;
const
std
::
string
on_magenta
=
"
\033
[45m"
;
const
std
::
string
on_cyan
=
"
\033
[46m"
;
void
log
(
const
details
::
log_msg
&
msg
)
SPDLOG_FINAL
override
const
std
::
string
on_white
=
"
\033
[47m"
;
{
// Wrap the originally formatted message in color codes.
// If color is not supported in the terminal, log as is instead.
void
log
(
const
details
::
log_msg
&
msg
)
SPDLOG_FINAL
override
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
{
if
(
should_do_colors_
&&
msg
.
color_range_end
>
msg
.
color_range_start
)
// Wrap the originally formatted message in color codes.
{
// If color is not supported in the terminal, log as is instead.
// before color range
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
_print_range
(
msg
,
0
,
msg
.
color_range_start
);
if
(
should_do_colors_
&&
msg
.
color_range_end
>
msg
.
color_range_start
)
// in color range
{
_print_ccode
(
colors_
[
msg
.
level
]);
// before color range
_print_range
(
msg
,
msg
.
color_range_start
,
msg
.
color_range_end
);
_print_range
(
msg
,
0
,
msg
.
color_range_start
);
_print_ccode
(
reset
);
// in color range
// after color range
_print_ccode
(
colors_
[
msg
.
level
]);
_print_range
(
msg
,
msg
.
color_range_end
,
msg
.
formatted
.
size
());
_print_range
(
msg
,
msg
.
color_range_start
,
msg
.
color_range_end
);
}
_print_ccode
(
reset
);
else
// no color
// after color range
{
_print_range
(
msg
,
msg
.
color_range_end
,
msg
.
formatted
.
size
());
_print_range
(
msg
,
0
,
msg
.
formatted
.
size
());
}
}
else
// no color
fflush
(
target_file_
);
{
}
_print_range
(
msg
,
0
,
msg
.
formatted
.
size
());
}
void
flush
()
SPDLOG_FINAL
override
fflush
(
target_file_
);
{
}
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
fflush
(
target_file_
);
void
flush
()
SPDLOG_FINAL
override
}
{
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
private
:
fflush
(
target_file_
);
void
_print_ccode
(
const
std
::
string
&
color_code
)
}
{
fwrite
(
color_code
.
data
(),
sizeof
(
char
),
color_code
.
size
(),
target_file_
);
}
private
:
void
_print_range
(
const
details
::
log_msg
&
msg
,
size_t
start
,
size_t
end
)
{
void
_print_ccode
(
const
std
::
string
&
color_code
)
fwrite
(
msg
.
formatted
.
data
()
+
start
,
sizeof
(
char
),
end
-
start
,
target_file_
);
{
}
fwrite
(
color_code
.
data
(),
sizeof
(
char
),
color_code
.
size
(),
target_file_
);
}
FILE
*
target_file_
;
void
_print_range
(
const
details
::
log_msg
&
msg
,
size_t
start
,
size_t
end
)
mutex_t
&
_mutex
;
{
fwrite
(
msg
.
formatted
.
data
()
+
start
,
sizeof
(
char
),
end
-
start
,
target_file_
);
bool
should_do_colors_
;
}
std
::
unordered_map
<
level
::
level_enum
,
std
::
string
,
level
::
level_hasher
>
colors_
;
};
FILE
*
target_file_
;
mutex_t
&
_mutex
;
using
ansicolor_stdout_sink_mt
=
ansicolor_sink
<
details
::
console_stdout_trait
,
details
::
console_mutex_trait
>
;
using
ansicolor_stdout_sink_st
=
ansicolor_sink
<
details
::
console_stdout_trait
,
details
::
console_null_mutex_trait
>
;
bool
should_do_colors_
;
using
ansicolor_stderr_sink_mt
=
ansicolor_sink
<
details
::
console_stderr_trait
,
details
::
console_mutex_trait
>
;
std
::
unordered_map
<
level
::
level_enum
,
std
::
string
,
level
::
level_hasher
>
colors_
;
using
ansicolor_stderr_sink_st
=
ansicolor_sink
<
details
::
console_stderr_trait
,
details
::
console_null_mutex_trait
>
;
};
}
// namespace sinks
using
ansicolor_stdout_sink_mt
=
ansicolor_sink
<
details
::
console_stdout_trait
,
details
::
console_mutex_trait
>
;
using
ansicolor_stdout_sink_st
=
ansicolor_sink
<
details
::
console_stdout_trait
,
details
::
console_null_mutex_trait
>
;
using
ansicolor_stderr_sink_mt
=
ansicolor_sink
<
details
::
console_stderr_trait
,
details
::
console_mutex_trait
>
;
using
ansicolor_stderr_sink_st
=
ansicolor_sink
<
details
::
console_stderr_trait
,
details
::
console_null_mutex_trait
>
;
}
// namespace sinks
}
// namespace spdlog
}
// namespace spdlog
include/spdlog/sinks/file_sinks.h
View file @
c962c883
...
@@ -4,10 +4,10 @@
...
@@ -4,10 +4,10 @@
//
//
#pragma once
#pragma once
#include "../details/file_helper.h"
#include "../details/file_helper.h"
#include "../details/null_mutex.h"
#include "../details/null_mutex.h"
#include "../fmt/fmt.h"
#include "../fmt/fmt.h"
#include "../spdlog.h"
#include "base_sink.h"
#include "base_sink.h"
#include <algorithm>
#include <algorithm>
...
@@ -19,286 +19,286 @@
...
@@ -19,286 +19,286 @@
#include <string>
#include <string>
namespace
spdlog
{
namespace
spdlog
{
namespace
sinks
{
namespace
sinks
{
/*
/*
* Trivial file sink with single file as target
* Trivial file sink with single file as target
*/
*/
template
<
class
Mutex
>
template
<
class
Mutex
>
class
simple_file_sink
SPDLOG_FINAL
:
public
base_sink
<
Mutex
>
class
simple_file_sink
SPDLOG_FINAL
:
public
base_sink
<
Mutex
>
{
{
public
:
public
:
explicit
simple_file_sink
(
const
filename_t
&
filename
,
bool
truncate
=
false
)
explicit
simple_file_sink
(
const
filename_t
&
filename
,
bool
truncate
=
false
)
:
_force_flush
(
false
)
:
_force_flush
(
false
)
{
{
_file_helper
.
open
(
filename
,
truncate
);
_file_helper
.
open
(
filename
,
truncate
);
}
}
void
set_force_flush
(
bool
force_flush
)
void
set_force_flush
(
bool
force_flush
)
{
{
_force_flush
=
force_flush
;
_force_flush
=
force_flush
;
}
}
protected
:
protected
:
void
_sink_it
(
const
details
::
log_msg
&
msg
)
override
void
_sink_it
(
const
details
::
log_msg
&
msg
)
override
{
{
_file_helper
.
write
(
msg
);
_file_helper
.
write
(
msg
);
if
(
_force_flush
)
if
(
_force_flush
)
{
{
_file_helper
.
flush
();
_file_helper
.
flush
();
}
}
}
}
void
_flush
()
override
void
_flush
()
override
{
{
_file_helper
.
flush
();
_file_helper
.
flush
();
}
}
private
:
private
:
details
::
file_helper
_file_helper
;
details
::
file_helper
_file_helper
;
bool
_force_flush
;
bool
_force_flush
;
};
};
using
simple_file_sink_mt
=
simple_file_sink
<
std
::
mutex
>
;
using
simple_file_sink_mt
=
simple_file_sink
<
std
::
mutex
>
;
using
simple_file_sink_st
=
simple_file_sink
<
details
::
null_mutex
>
;
using
simple_file_sink_st
=
simple_file_sink
<
details
::
null_mutex
>
;
/*
/*
* Rotating file sink based on size
* Rotating file sink based on size
*/
*/
template
<
class
Mutex
>
template
<
class
Mutex
>
class
rotating_file_sink
SPDLOG_FINAL
:
public
base_sink
<
Mutex
>
class
rotating_file_sink
SPDLOG_FINAL
:
public
base_sink
<
Mutex
>
{
{
public
:
public
:
rotating_file_sink
(
filename_t
base_filename
,
std
::
size_t
max_size
,
std
::
size_t
max_files
)
rotating_file_sink
(
filename_t
base_filename
,
std
::
size_t
max_size
,
std
::
size_t
max_files
)
:
_base_filename
(
std
::
move
(
base_filename
))
:
_base_filename
(
std
::
move
(
base_filename
))
,
_max_size
(
max_size
)
,
_max_size
(
max_size
)
,
_max_files
(
max_files
)
,
_max_files
(
max_files
)
{
{
_file_helper
.
open
(
calc_filename
(
_base_filename
,
0
));
_file_helper
.
open
(
calc_filename
(
_base_filename
,
0
));
_current_size
=
_file_helper
.
size
();
// expensive. called only once
_current_size
=
_file_helper
.
size
();
// expensive. called only once
}
}
// calc filename according to index and file extension if exists.
// calc filename according to index and file extension if exists.
// e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt".
// e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt".
static
filename_t
calc_filename
(
const
filename_t
&
filename
,
std
::
size_t
index
)
static
filename_t
calc_filename
(
const
filename_t
&
filename
,
std
::
size_t
index
)
{
{
typename
std
::
conditional
<
std
::
is_same
<
filename_t
::
value_type
,
char
>::
value
,
fmt
::
MemoryWriter
,
fmt
::
WMemoryWriter
>::
type
w
;
typename
std
::
conditional
<
std
::
is_same
<
filename_t
::
value_type
,
char
>::
value
,
fmt
::
MemoryWriter
,
fmt
::
WMemoryWriter
>::
type
w
;
if
(
index
!=
0u
)
if
(
index
!=
0u
)
{
{
filename_t
basename
,
ext
;
filename_t
basename
,
ext
;
std
::
tie
(
basename
,
ext
)
=
details
::
file_helper
::
split_by_extenstion
(
filename
);
std
::
tie
(
basename
,
ext
)
=
details
::
file_helper
::
split_by_extenstion
(
filename
);
w
.
write
(
SPDLOG_FILENAME_T
(
"{}.{}{}"
),
basename
,
index
,
ext
);
w
.
write
(
SPDLOG_FILENAME_T
(
"{}.{}{}"
),
basename
,
index
,
ext
);
}
}
else
else
{
{
w
.
write
(
SPDLOG_FILENAME_T
(
"{}"
),
filename
);
w
.
write
(
SPDLOG_FILENAME_T
(
"{}"
),
filename
);
}
}
return
w
.
str
();
return
w
.
str
();
}
}
protected
:
protected
:
void
_sink_it
(
const
details
::
log_msg
&
msg
)
override
void
_sink_it
(
const
details
::
log_msg
&
msg
)
override
{
{
_current_size
+=
msg
.
formatted
.
size
();
_current_size
+=
msg
.
formatted
.
size
();
if
(
_current_size
>
_max_size
)
if
(
_current_size
>
_max_size
)
{
{
_rotate
();
_rotate
();
_current_size
=
msg
.
formatted
.
size
();
_current_size
=
msg
.
formatted
.
size
();
}
}
_file_helper
.
write
(
msg
);
_file_helper
.
write
(
msg
);
}
}
void
_flush
()
override
void
_flush
()
override
{
{
_file_helper
.
flush
();
_file_helper
.
flush
();
}
}
private
:
private
:
// Rotate files:
// Rotate files:
// log.txt -> log.1.txt
// log.txt -> log.1.txt
// log.1.txt -> log.2.txt
// log.1.txt -> log.2.txt
// log.2.txt -> log.3.txt
// log.2.txt -> log.3.txt
// log.3.txt -> delete
// log.3.txt -> delete
void
_rotate
()
void
_rotate
()
{
{
using
details
::
os
::
filename_to_str
;
using
details
::
os
::
filename_to_str
;
_file_helper
.
close
();
_file_helper
.
close
();
for
(
auto
i
=
_max_files
;
i
>
0
;
--
i
)
for
(
auto
i
=
_max_files
;
i
>
0
;
--
i
)
{
{
filename_t
src
=
calc_filename
(
_base_filename
,
i
-
1
);
filename_t
src
=
calc_filename
(
_base_filename
,
i
-
1
);
filename_t
target
=
calc_filename
(
_base_filename
,
i
);
filename_t
target
=
calc_filename
(
_base_filename
,
i
);
if
(
details
::
file_helper
::
file_exists
(
target
))
if
(
details
::
file_helper
::
file_exists
(
target
))
{
{
if
(
details
::
os
::
remove
(
target
)
!=
0
)
if
(
details
::
os
::
remove
(
target
)
!=
0
)
{
{
throw
spdlog_ex
(
"rotating_file_sink: failed removing "
+
filename_to_str
(
target
),
errno
);
throw
spdlog_ex
(
"rotating_file_sink: failed removing "
+
filename_to_str
(
target
),
errno
);
}
}
}
}
if
(
details
::
file_helper
::
file_exists
(
src
)
&&
details
::
os
::
rename
(
src
,
target
)
!=
0
)
if
(
details
::
file_helper
::
file_exists
(
src
)
&&
details
::
os
::
rename
(
src
,
target
)
!=
0
)
{
{
throw
spdlog_ex
(
"rotating_file_sink: failed renaming "
+
filename_to_str
(
src
)
+
" to "
+
filename_to_str
(
target
),
errno
);
throw
spdlog_ex
(
"rotating_file_sink: failed renaming "
+
filename_to_str
(
src
)
+
" to "
+
filename_to_str
(
target
),
errno
);
}
}
}
}
_file_helper
.
reopen
(
true
);
_file_helper
.
reopen
(
true
);
}
}
filename_t
_base_filename
;
filename_t
_base_filename
;
std
::
size_t
_max_size
;
std
::
size_t
_max_size
;
std
::
size_t
_max_files
;
std
::
size_t
_max_files
;
std
::
size_t
_current_size
;
std
::
size_t
_current_size
;
details
::
file_helper
_file_helper
;
details
::
file_helper
_file_helper
;
};
};
using
rotating_file_sink_mt
=
rotating_file_sink
<
std
::
mutex
>
;
using
rotating_file_sink_mt
=
rotating_file_sink
<
std
::
mutex
>
;
using
rotating_file_sink_st
=
rotating_file_sink
<
details
::
null_mutex
>
;
using
rotating_file_sink_st
=
rotating_file_sink
<
details
::
null_mutex
>
;
/*
/*
* Default generator of daily log file names.
* Default generator of daily log file names.
*/
*/
struct
default_daily_file_name_calculator
struct
default_daily_file_name_calculator
{
{
// Create filename for the form filename.YYYY-MM-DD_hh-mm.ext
// Create filename for the form filename.YYYY-MM-DD_hh-mm.ext
static
filename_t
calc_filename
(
const
filename_t
&
filename
)
static
filename_t
calc_filename
(
const
filename_t
&
filename
)
{
{
std
::
tm
tm
=
spdlog
::
details
::
os
::
localtime
();
std
::
tm
tm
=
spdlog
::
details
::
os
::
localtime
();
filename_t
basename
,
ext
;
filename_t
basename
,
ext
;
std
::
tie
(
basename
,
ext
)
=
details
::
file_helper
::
split_by_extenstion
(
filename
);
std
::
tie
(
basename
,
ext
)
=
details
::
file_helper
::
split_by_extenstion
(
filename
);
std
::
conditional
<
std
::
is_same
<
filename_t
::
value_type
,
char
>::
value
,
fmt
::
MemoryWriter
,
fmt
::
WMemoryWriter
>::
type
w
;
std
::
conditional
<
std
::
is_same
<
filename_t
::
value_type
,
char
>::
value
,
fmt
::
MemoryWriter
,
fmt
::
WMemoryWriter
>::
type
w
;
w
.
write
(
SPDLOG_FILENAME_T
(
"{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}{}"
),
basename
,
tm
.
tm_year
+
1900
,
tm
.
tm_mon
+
1
,
tm
.
tm_mday
,
w
.
write
(
SPDLOG_FILENAME_T
(
"{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}{}"
),
basename
,
tm
.
tm_year
+
1900
,
tm
.
tm_mon
+
1
,
tm
.
tm_mday
,
tm
.
tm_hour
,
tm
.
tm_min
,
ext
);
tm
.
tm_hour
,
tm
.
tm_min
,
ext
);
return
w
.
str
();
return
w
.
str
();
}
}
};
};
/*
/*
* Generator of daily log file names in format basename.YYYY-MM-DD.ext
* Generator of daily log file names in format basename.YYYY-MM-DD.ext
*/
*/
struct
dateonly_daily_file_name_calculator
struct
dateonly_daily_file_name_calculator
{
{
// Create filename for the form basename.YYYY-MM-DD
// Create filename for the form basename.YYYY-MM-DD
static
filename_t
calc_filename
(
const
filename_t
&
filename
)
static
filename_t
calc_filename
(
const
filename_t
&
filename
)
{
{
std
::
tm
tm
=
spdlog
::
details
::
os
::
localtime
();
std
::
tm
tm
=
spdlog
::
details
::
os
::
localtime
();
filename_t
basename
,
ext
;
filename_t
basename
,
ext
;
std
::
tie
(
basename
,
ext
)
=
details
::
file_helper
::
split_by_extenstion
(
filename
);
std
::
tie
(
basename
,
ext
)
=
details
::
file_helper
::
split_by_extenstion
(
filename
);
std
::
conditional
<
std
::
is_same
<
filename_t
::
value_type
,
char
>::
value
,
fmt
::
MemoryWriter
,
fmt
::
WMemoryWriter
>::
type
w
;
std
::
conditional
<
std
::
is_same
<
filename_t
::
value_type
,
char
>::
value
,
fmt
::
MemoryWriter
,
fmt
::
WMemoryWriter
>::
type
w
;
w
.
write
(
SPDLOG_FILENAME_T
(
"{}_{:04d}-{:02d}-{:02d}{}"
),
basename
,
tm
.
tm_year
+
1900
,
tm
.
tm_mon
+
1
,
tm
.
tm_mday
,
ext
);
w
.
write
(
SPDLOG_FILENAME_T
(
"{}_{:04d}-{:02d}-{:02d}{}"
),
basename
,
tm
.
tm_year
+
1900
,
tm
.
tm_mon
+
1
,
tm
.
tm_mday
,
ext
);
return
w
.
str
();
return
w
.
str
();
}
}
};
};
/*
/*
* Rotating file sink based on date. rotates at midnight
* Rotating file sink based on date. rotates at midnight
*/
*/
template
<
class
Mutex
,
class
FileNameCalc
=
default_daily_file_name_calculator
>
template
<
class
Mutex
,
class
FileNameCalc
=
default_daily_file_name_calculator
>
class
daily_file_sink
SPDLOG_FINAL
:
public
base_sink
<
Mutex
>
class
daily_file_sink
SPDLOG_FINAL
:
public
base_sink
<
Mutex
>
{
{
public
:
public
:
// create daily file sink which rotates on given time
// create daily file sink which rotates on given time
daily_file_sink
(
filename_t
base_filename
,
int
rotation_hour
,
int
rotation_minute
)
daily_file_sink
(
filename_t
base_filename
,
int
rotation_hour
,
int
rotation_minute
)
:
_base_filename
(
std
::
move
(
base_filename
))
:
_base_filename
(
std
::
move
(
base_filename
))
,
_rotation_h
(
rotation_hour
)
,
_rotation_h
(
rotation_hour
)
,
_rotation_m
(
rotation_minute
)
,
_rotation_m
(
rotation_minute
)
{
{
if
(
rotation_hour
<
0
||
rotation_hour
>
23
||
rotation_minute
<
0
||
rotation_minute
>
59
)
if
(
rotation_hour
<
0
||
rotation_hour
>
23
||
rotation_minute
<
0
||
rotation_minute
>
59
)
{
{
throw
spdlog_ex
(
"daily_file_sink: Invalid rotation time in ctor"
);
throw
spdlog_ex
(
"daily_file_sink: Invalid rotation time in ctor"
);
}
}
_rotation_tp
=
_next_rotation_tp
();
_rotation_tp
=
_next_rotation_tp
();
_file_helper
.
open
(
FileNameCalc
::
calc_filename
(
_base_filename
));
_file_helper
.
open
(
FileNameCalc
::
calc_filename
(
_base_filename
));
}
}
protected
:
protected
:
void
_sink_it
(
const
details
::
log_msg
&
msg
)
override
void
_sink_it
(
const
details
::
log_msg
&
msg
)
override
{
{
if
(
std
::
chrono
::
system_clock
::
now
()
>=
_rotation_tp
)
if
(
std
::
chrono
::
system_clock
::
now
()
>=
_rotation_tp
)
{
{
_file_helper
.
open
(
FileNameCalc
::
calc_filename
(
_base_filename
));
_file_helper
.
open
(
FileNameCalc
::
calc_filename
(
_base_filename
));
_rotation_tp
=
_next_rotation_tp
();
_rotation_tp
=
_next_rotation_tp
();
}
}
_file_helper
.
write
(
msg
);
_file_helper
.
write
(
msg
);
}
}
void
_flush
()
override
void
_flush
()
override
{
{
_file_helper
.
flush
();
_file_helper
.
flush
();
}
}
private
:
private
:
std
::
chrono
::
system_clock
::
time_point
_next_rotation_tp
()
std
::
chrono
::
system_clock
::
time_point
_next_rotation_tp
()
{
{
auto
now
=
std
::
chrono
::
system_clock
::
now
();
auto
now
=
std
::
chrono
::
system_clock
::
now
();
time_t
tnow
=
std
::
chrono
::
system_clock
::
to_time_t
(
now
);
time_t
tnow
=
std
::
chrono
::
system_clock
::
to_time_t
(
now
);
tm
date
=
spdlog
::
details
::
os
::
localtime
(
tnow
);
tm
date
=
spdlog
::
details
::
os
::
localtime
(
tnow
);
date
.
tm_hour
=
_rotation_h
;
date
.
tm_hour
=
_rotation_h
;
date
.
tm_min
=
_rotation_m
;
date
.
tm_min
=
_rotation_m
;
date
.
tm_sec
=
0
;
date
.
tm_sec
=
0
;
auto
rotation_time
=
std
::
chrono
::
system_clock
::
from_time_t
(
std
::
mktime
(
&
date
));
auto
rotation_time
=
std
::
chrono
::
system_clock
::
from_time_t
(
std
::
mktime
(
&
date
));
if
(
rotation_time
>
now
)
if
(
rotation_time
>
now
)
{
{
return
rotation_time
;
return
rotation_time
;
}
}
return
{
rotation_time
+
std
::
chrono
::
hours
(
24
)
};
return
{
rotation_time
+
std
::
chrono
::
hours
(
24
)
};
}
}
filename_t
_base_filename
;
filename_t
_base_filename
;
int
_rotation_h
;
int
_rotation_h
;
int
_rotation_m
;
int
_rotation_m
;
std
::
chrono
::
system_clock
::
time_point
_rotation_tp
;
std
::
chrono
::
system_clock
::
time_point
_rotation_tp
;
details
::
file_helper
_file_helper
;
details
::
file_helper
_file_helper
;
};
};
using
daily_file_sink_mt
=
daily_file_sink
<
std
::
mutex
>
;
using
daily_file_sink_mt
=
daily_file_sink
<
std
::
mutex
>
;
using
daily_file_sink_st
=
daily_file_sink
<
details
::
null_mutex
>
;
using
daily_file_sink_st
=
daily_file_sink
<
details
::
null_mutex
>
;
}
// namespace sinks
}
// namespace sinks
//
//
// factory functions to create and register file loggers
// factory functions to create and register file loggers
//
//
// Basic logger simply writes to given file without any limitations or rotations.
// Basic logger simply writes to given file without any limitations or rotations.
template
<
typename
Factory
=
default_factory
>
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
basic_logger_mt
(
const
std
::
string
&
logger_name
,
const
filename_t
&
filename
,
bool
truncate
=
false
)
inline
std
::
shared_ptr
<
logger
>
basic_logger_mt
(
const
std
::
string
&
logger_name
,
const
filename_t
&
filename
,
bool
truncate
=
false
)
{
{
return
Factory
::
template
create
<
sinks
::
simple_file_sink_mt
>
(
logger_name
,
filename
,
truncate
);
return
Factory
::
template
create
<
sinks
::
simple_file_sink_mt
>
(
logger_name
,
filename
,
truncate
);
}
}
template
<
typename
Factory
=
default_factory
>
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
basic_logger_st
(
const
std
::
string
&
logger_name
,
const
filename_t
&
filename
,
bool
truncate
=
false
)
inline
std
::
shared_ptr
<
logger
>
basic_logger_st
(
const
std
::
string
&
logger_name
,
const
filename_t
&
filename
,
bool
truncate
=
false
)
{
{
return
Factory
::
template
create
<
sinks
::
simple_file_sink_st
>
(
logger_name
,
filename
,
truncate
);
return
Factory
::
template
create
<
sinks
::
simple_file_sink_st
>
(
logger_name
,
filename
,
truncate
);
}
}
//
//
// Create and register multi/single threaded rotating file logger
// Create and register multi/single threaded rotating file logger
//
//
template
<
typename
Factory
=
default_factory
>
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
rotating_logger_mt
(
inline
std
::
shared_ptr
<
logger
>
rotating_logger_mt
(
const
std
::
string
&
logger_name
,
const
filename_t
&
filename
,
size_t
max_file_size
,
size_t
max_files
)
const
std
::
string
&
logger_name
,
const
filename_t
&
filename
,
size_t
max_file_size
,
size_t
max_files
)
{
{
return
Factory
::
template
create
<
sinks
::
rotating_file_sink_mt
>
(
logger_name
,
filename
,
max_file_size
,
max_files
);
return
Factory
::
template
create
<
sinks
::
rotating_file_sink_mt
>
(
logger_name
,
filename
,
max_file_size
,
max_files
);
}
}
template
<
typename
Factory
=
default_factory
>
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
rotating_logger_st
(
inline
std
::
shared_ptr
<
logger
>
rotating_logger_st
(
const
std
::
string
&
logger_name
,
const
filename_t
&
filename
,
size_t
max_file_size
,
size_t
max_files
)
const
std
::
string
&
logger_name
,
const
filename_t
&
filename
,
size_t
max_file_size
,
size_t
max_files
)
{
{
return
Factory
::
template
create
<
sinks
::
rotating_file_sink_st
>
(
logger_name
,
filename
,
max_file_size
,
max_files
);
return
Factory
::
template
create
<
sinks
::
rotating_file_sink_st
>
(
logger_name
,
filename
,
max_file_size
,
max_files
);
}
}
//
//
// Create file logger which creates new file on the given time (default in midnight):
// Create file logger which creates new file on the given time (default in midnight):
//
//
template
<
typename
Factory
=
default_factory
>
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
daily_logger_mt
(
const
std
::
string
&
logger_name
,
const
filename_t
&
filename
,
int
hour
=
0
,
int
minute
=
0
)
inline
std
::
shared_ptr
<
logger
>
daily_logger_mt
(
const
std
::
string
&
logger_name
,
const
filename_t
&
filename
,
int
hour
=
0
,
int
minute
=
0
)
{
{
return
Factory
::
template
create
<
sinks
::
daily_file_sink_mt
>
(
logger_name
,
filename
,
hour
,
minute
);
return
Factory
::
template
create
<
sinks
::
daily_file_sink_mt
>
(
logger_name
,
filename
,
hour
,
minute
);
}
}
template
<
typename
Factory
=
default_factory
>
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
daily_logger_st
(
const
std
::
string
&
logger_name
,
const
filename_t
&
filename
,
int
hour
=
0
,
int
minute
=
0
)
inline
std
::
shared_ptr
<
logger
>
daily_logger_st
(
const
std
::
string
&
logger_name
,
const
filename_t
&
filename
,
int
hour
=
0
,
int
minute
=
0
)
{
{
return
Factory
::
template
create
<
sinks
::
daily_file_sink_st
>
(
logger_name
,
filename
,
hour
,
minute
);
return
Factory
::
template
create
<
sinks
::
daily_file_sink_st
>
(
logger_name
,
filename
,
hour
,
minute
);
}
}
}
// namespace spdlog
}
// namespace spdlog
include/spdlog/sinks/stdout_color_sinks.h
View file @
c962c883
...
@@ -12,44 +12,43 @@
...
@@ -12,44 +12,43 @@
#include "ansicolor_sink.h"
#include "ansicolor_sink.h"
#endif
#endif
namespace
{
namespace
{
using
namespace
spdlog
::
sinks
;
using
namespace
spdlog
::
sinks
;
#ifdef _WIN32
#ifdef _WIN32
using
stdout_color_sink_mt
=
wincolor_stdout_sink_mt
;
using
stdout_color_sink_mt
=
wincolor_stdout_sink_mt
;
using
stdout_color_sink_st
=
wincolor_stdout_sink_st
;
using
stdout_color_sink_st
=
wincolor_stdout_sink_st
;
using
stderr_color_sink_mt
=
wincolor_stderr_sink_mt
;
using
stderr_color_sink_mt
=
wincolor_stderr_sink_mt
;
using
stderr_color_sink_st
=
wincolor_stderr_sink_st
;
using
stderr_color_sink_st
=
wincolor_stderr_sink_st
;
#else
#else
using
stdout_color_sink_mt
=
ansicolor_stdout_sink_mt
;
using
stdout_color_sink_mt
=
ansicolor_stdout_sink_mt
;
using
stdout_color_sink_st
=
ansicolor_stdout_sink_st
;
using
stdout_color_sink_st
=
ansicolor_stdout_sink_st
;
using
stderr_color_sink_mt
=
ansicolor_stderr_sink_mt
;
using
stderr_color_sink_mt
=
ansicolor_stderr_sink_mt
;
using
stderr_color_sink_st
=
ansicolor_stderr_sink_st
;
using
stderr_color_sink_st
=
ansicolor_stderr_sink_st
;
#endif
#endif
}
}
// namespace
namespace
spdlog
namespace
spdlog
{
{
template
<
typename
Factory
=
default_factory
>
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
stdout_color_mt
(
const
std
::
string
&
logger_name
)
inline
std
::
shared_ptr
<
logger
>
stdout_color_mt
(
const
std
::
string
&
logger_name
)
{
{
return
Factory
::
template
create
<
stdout_color_sink_mt
>
(
logger_name
);
return
Factory
::
template
create
<
stdout_color_sink_mt
>
(
logger_name
);
}
}
template
<
typename
Factory
=
default_factory
>
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
stdout_color_st
(
const
std
::
string
&
logger_name
)
inline
std
::
shared_ptr
<
logger
>
stdout_color_st
(
const
std
::
string
&
logger_name
)
{
{
return
Factory
::
template
create
<
stdout_color_sink_st
>
(
logger_name
);
return
Factory
::
template
create
<
stdout_color_sink_st
>
(
logger_name
);
}
}
template
<
typename
Factory
=
default_factory
>
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
stderr_color_mt
(
const
std
::
string
&
logger_name
)
inline
std
::
shared_ptr
<
logger
>
stderr_color_mt
(
const
std
::
string
&
logger_name
)
{
{
return
Factory
::
template
create
<
stderr_color_sink_mt
>
(
logger_name
);
return
Factory
::
template
create
<
stderr_color_sink_mt
>
(
logger_name
);
}
}
template
<
typename
Factory
=
default_factory
>
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
stderr_color_st
(
const
std
::
string
&
logger_name
)
inline
std
::
shared_ptr
<
logger
>
stderr_color_st
(
const
std
::
string
&
logger_name
)
{
{
return
Factory
::
template
createstderr_color_sink_mt
>
(
logger_name
);
return
Factory
::
template
createstderr_color_sink_mt
>
(
logger_name
);
}
}
}
}
// namespace spdlog
\ No newline at end of file
\ No newline at end of file
include/spdlog/sinks/stdout_sinks.h
View file @
c962c883
...
@@ -7,73 +7,78 @@
...
@@ -7,73 +7,78 @@
#include "../details/null_mutex.h"
#include "../details/null_mutex.h"
#include "../details/traits.h"
#include "../details/traits.h"
#include "../spdlog.h"
#include <cstdio>
#include <cstdio>
#include <memory>
#include <memory>
#include <mutex>
#include <mutex>
namespace
spdlog
{
namespace
spdlog
{
namespace
sinks
{
namespace
sinks
{
template
<
class
StdoutTrait
,
class
ConsoleMutexTrait
>
class
stdout_sink
:
public
sink
template
<
class
StdoutTrait
,
class
ConsoleMutexTrait
>
{
class
stdout_sink
:
public
sink
public
:
{
using
mutex_t
=
typename
ConsoleMutexTrait
::
mutex_t
;
public
:
stdout_sink
()
:
using
mutex_t
=
typename
ConsoleMutexTrait
::
mutex_t
;
_mutex
(
ConsoleMutexTrait
::
console_mutex
()),
stdout_sink
()
_file
(
StdoutTrait
::
stream
())
{}
:
_mutex
(
ConsoleMutexTrait
::
console_mutex
())
~
stdout_sink
()
=
default
;
,
_file
(
StdoutTrait
::
stream
())
{
stdout_sink
(
const
stdout_sink
&
other
)
=
delete
;
}
stdout_sink
&
operator
=
(
const
stdout_sink
&
other
)
=
delete
;
~
stdout_sink
()
=
default
;
void
log
(
const
details
::
log_msg
&
msg
)
override
stdout_sink
(
const
stdout_sink
&
other
)
=
delete
;
{
stdout_sink
&
operator
=
(
const
stdout_sink
&
other
)
=
delete
;
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
fwrite
(
msg
.
formatted
.
data
(),
sizeof
(
char
),
msg
.
formatted
.
size
(),
_file
);
void
log
(
const
details
::
log_msg
&
msg
)
override
fflush
(
StdoutTrait
::
stream
());
{
}
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
fwrite
(
msg
.
formatted
.
data
(),
sizeof
(
char
),
msg
.
formatted
.
size
(),
_file
);
void
flush
()
override
fflush
(
StdoutTrait
::
stream
());
{
}
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
fflush
(
StdoutTrait
::
stream
());
void
flush
()
override
}
{
private
:
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
typename
mutex_t
&
_mutex
;
fflush
(
StdoutTrait
::
stream
());
FILE
*
_file
;
}
};
private
:
using
stdout_sink_mt
=
stdout_sink
<
details
::
console_stdout_trait
,
details
::
console_mutex_trait
>
;
mutex_t
&
_mutex
;
using
stdout_sink_st
=
stdout_sink
<
details
::
console_stdout_trait
,
details
::
console_null_mutex_trait
>
;
FILE
*
_file
;
using
stderr_sink_mt
=
stdout_sink
<
details
::
console_stderr_trait
,
details
::
console_mutex_trait
>
;
};
using
stderr_sink_st
=
stdout_sink
<
details
::
console_stderr_trait
,
details
::
console_null_mutex_trait
>
;
using
stdout_sink_mt
=
stdout_sink
<
details
::
console_stdout_trait
,
details
::
console_mutex_trait
>
;
}
// namespace sinks
using
stdout_sink_st
=
stdout_sink
<
details
::
console_stdout_trait
,
details
::
console_null_mutex_trait
>
;
using
stderr_sink_mt
=
stdout_sink
<
details
::
console_stderr_trait
,
details
::
console_mutex_trait
>
;
// factory methods
using
stderr_sink_st
=
stdout_sink
<
details
::
console_stderr_trait
,
details
::
console_null_mutex_trait
>
;
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
stdout_logger_mt
(
const
std
::
string
&
logger_name
)
}
// namespace sinks
{
return
Factory
::
template
create
<
stdout_color_sink_mt
>
(
logger_name
);
// factory methods
}
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
stdout_logger_mt
(
const
std
::
string
&
logger_name
)
template
<
typename
Factory
=
default_factory
>
{
inline
std
::
shared_ptr
<
logger
>
stdout_logger_st
(
const
std
::
string
&
logger_name
)
return
Factory
::
template
create
<
stdout_color_sink_mt
>
(
logger_name
);
{
}
return
Factory
::
template
create
<
stdout_color_sink_mt
>
(
logger_name
);
}
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
stdout_logger_st
(
const
std
::
string
&
logger_name
)
template
<
typename
Factory
=
default_factory
>
{
inline
std
::
shared_ptr
<
logger
>
stderr_logger_mt
(
const
std
::
string
&
logger_name
)
return
Factory
::
template
create
<
stdout_color_sink_mt
>
(
logger_name
);
{
}
return
Factory
::
template
create
<
stderr_color_sink_mt
>
(
logger_name
);
}
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
stderr_logger_mt
(
const
std
::
string
&
logger_name
)
template
<
typename
Factory
=
default_factory
>
{
inline
std
::
shared_ptr
<
logger
>
stderr_logger_st
(
const
std
::
string
&
logger_name
)
return
Factory
::
template
create
<
stderr_color_sink_mt
>
(
logger_name
);
{
}
return
Factory
::
template
create
<
stderr_logger_sink_mt
>
(
logger_name
);
}
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
stderr_logger_st
(
const
std
::
string
&
logger_name
)
{
return
Factory
::
template
create
<
stderr_logger_sink_mt
>
(
logger_name
);
}
}
// namespace spdlog
}
// namespace spdlog
include/spdlog/sinks/syslog_sink.h
View file @
c962c883
...
@@ -7,8 +7,6 @@
...
@@ -7,8 +7,6 @@
#include "../common.h"
#include "../common.h"
#ifdef SPDLOG_ENABLE_SYSLOG
#include "../details/log_msg.h"
#include "../details/log_msg.h"
#include "sink.h"
#include "sink.h"
...
@@ -17,68 +15,66 @@
...
@@ -17,68 +15,66 @@
#include <syslog.h>
#include <syslog.h>
namespace
spdlog
{
namespace
spdlog
{
namespace
sinks
{
namespace
sinks
{
/**
/**
* Sink that write to syslog using the `syscall()` library call.
* Sink that write to syslog using the `syscall()` library call.
*
*
* Locking is not needed, as `syslog()` itself is thread-safe.
* Locking is not needed, as `syslog()` itself is thread-safe.
*/
*/
class
syslog_sink
:
public
sink
class
syslog_sink
:
public
sink
{
{
public
:
public
:
//
//
syslog_sink
(
const
std
::
string
&
ident
=
""
,
int
syslog_option
=
0
,
int
syslog_facility
=
LOG_USER
)
syslog_sink
(
const
std
::
string
&
ident
=
""
,
int
syslog_option
=
0
,
int
syslog_facility
=
LOG_USER
)
:
_ident
(
ident
)
:
_ident
(
ident
)
{
{
_priorities
[
static_cast
<
size_t
>
(
level
::
trace
)]
=
LOG_DEBUG
;
_priorities
[
static_cast
<
size_t
>
(
level
::
trace
)]
=
LOG_DEBUG
;
_priorities
[
static_cast
<
size_t
>
(
level
::
debug
)]
=
LOG_DEBUG
;
_priorities
[
static_cast
<
size_t
>
(
level
::
debug
)]
=
LOG_DEBUG
;
_priorities
[
static_cast
<
size_t
>
(
level
::
info
)]
=
LOG_INFO
;
_priorities
[
static_cast
<
size_t
>
(
level
::
info
)]
=
LOG_INFO
;
_priorities
[
static_cast
<
size_t
>
(
level
::
warn
)]
=
LOG_WARNING
;
_priorities
[
static_cast
<
size_t
>
(
level
::
warn
)]
=
LOG_WARNING
;
_priorities
[
static_cast
<
size_t
>
(
level
::
err
)]
=
LOG_ERR
;
_priorities
[
static_cast
<
size_t
>
(
level
::
err
)]
=
LOG_ERR
;
_priorities
[
static_cast
<
size_t
>
(
level
::
critical
)]
=
LOG_CRIT
;
_priorities
[
static_cast
<
size_t
>
(
level
::
critical
)]
=
LOG_CRIT
;
_priorities
[
static_cast
<
size_t
>
(
level
::
off
)]
=
LOG_INFO
;
_priorities
[
static_cast
<
size_t
>
(
level
::
off
)]
=
LOG_INFO
;
// set ident to be program name if empty
// set ident to be program name if empty
::
openlog
(
_ident
.
empty
()
?
nullptr
:
_ident
.
c_str
(),
syslog_option
,
syslog_facility
);
::
openlog
(
_ident
.
empty
()
?
nullptr
:
_ident
.
c_str
(),
syslog_option
,
syslog_facility
);
}
}
~
syslog_sink
()
override
~
syslog_sink
()
override
{
{
::
closelog
();
::
closelog
();
}
}
syslog_sink
(
const
syslog_sink
&
)
=
delete
;
syslog_sink
(
const
syslog_sink
&
)
=
delete
;
syslog_sink
&
operator
=
(
const
syslog_sink
&
)
=
delete
;
syslog_sink
&
operator
=
(
const
syslog_sink
&
)
=
delete
;
void
log
(
const
details
::
log_msg
&
msg
)
override
void
log
(
const
details
::
log_msg
&
msg
)
override
{
{
::
syslog
(
syslog_prio_from_level
(
msg
),
"%s"
,
msg
.
raw
.
str
().
c_str
());
::
syslog
(
syslog_prio_from_level
(
msg
),
"%s"
,
msg
.
raw
.
str
().
c_str
());
}
}
void
flush
()
override
{}
void
flush
()
override
{}
private
:
private
:
std
::
array
<
int
,
7
>
_priorities
;
std
::
array
<
int
,
7
>
_priorities
;
// must store the ident because the man says openlog might use the pointer as is and not a string copy
// must store the ident because the man says openlog might use the pointer as is and not a string copy
const
std
::
string
_ident
;
const
std
::
string
_ident
;
//
//
// Simply maps spdlog's log level to syslog priority level.
// Simply maps spdlog's log level to syslog priority level.
//
//
int
syslog_prio_from_level
(
const
details
::
log_msg
&
msg
)
const
int
syslog_prio_from_level
(
const
details
::
log_msg
&
msg
)
const
{
{
return
_priorities
[
static_cast
<
size_t
>
(
msg
.
level
)];
return
_priorities
[
static_cast
<
size_t
>
(
msg
.
level
)];
}
}
};
};
}
// namespace sinks
}
// namespace sinks
// Create and register a syslog logger
// Create and register a syslog logger
template
<
typename
Factory
=
default_factory
>
template
<
typename
Factory
=
default_factory
>
inline
std
::
shared_ptr
<
logger
>
syslog_logger
(
inline
std
::
shared_ptr
<
logger
>
syslog_logger
(
const
std
::
string
&
logger_name
,
const
std
::
string
&
ident
=
""
,
int
syslog_option
=
0
,
int
syslog_facil
ty
=
(
1
<<
3
))
const
std
::
string
&
logger_name
,
const
std
::
string
&
syslog_ident
=
""
,
int
syslog_option
=
0
,
int
syslog_facili
ty
=
(
1
<<
3
))
{
{
return
return
Factory
::
template
create
<
sinks
::
syslog_sink
>
(
logger_name
,
syslog_ident
,
syslog_option
,
syslog_facility
);
return
Factory
::
template
create
<
sinks
::
syslog_sink
>
(
logger_name
,
syslog_ident
,
syslog_option
,
syslog_facility
);
}
}
}
// namespace spdlog
}
// namespace spdlog
#endif
include/spdlog/sinks/wincolor_sink.h
View file @
c962c883
...
@@ -5,124 +5,120 @@
...
@@ -5,124 +5,120 @@
#pragma once
#pragma once
#include "sink.h"
#include "../common.h"
#include "../common.h"
#include "../details/null_mutex.h"
#include "../details/null_mutex.h"
#include "../details/traits.h"
#include "../details/traits.h"
#include "sink.h"
#include <mutex>
#include <memory>
#include <memory>
#include <mutex>
#include <string>
#include <string>
#include <unordered_map>
#include <unordered_map>
#include <wincon.h>
#include <wincon.h>
namespace
spdlog
{
namespace
spdlog
{
namespace
sinks
{
namespace
sinks
{
/*
/*
* Windows color console sink. Uses WriteConsoleA to write to the console with colors
* Windows color console sink. Uses WriteConsoleA to write to the console with colors
*/
*/
template
<
class
HandleTrait
,
class
ConsoleMutexTrait
>
template
<
class
HandleTrait
,
class
ConsoleMutexTrait
>
class
wincolor_sink
:
public
sink
class
wincolor_sink
:
public
sink
{
{
public
:
public
:
const
WORD
BOLD
=
FOREGROUND_INTENSITY
;
const
WORD
BOLD
=
FOREGROUND_INTENSITY
;
const
WORD
RED
=
FOREGROUND_RED
;
const
WORD
RED
=
FOREGROUND_RED
;
const
WORD
GREEN
=
FOREGROUND_GREEN
;
const
WORD
GREEN
=
FOREGROUND_GREEN
;
const
WORD
CYAN
=
FOREGROUND_GREEN
|
FOREGROUND_BLUE
;
const
WORD
CYAN
=
FOREGROUND_GREEN
|
FOREGROUND_BLUE
;
const
WORD
WHITE
=
FOREGROUND_RED
|
FOREGROUND_GREEN
|
FOREGROUND_BLUE
;
const
WORD
WHITE
=
FOREGROUND_RED
|
FOREGROUND_GREEN
|
FOREGROUND_BLUE
;
const
WORD
YELLOW
=
FOREGROUND_RED
|
FOREGROUND_GREEN
;
const
WORD
YELLOW
=
FOREGROUND_RED
|
FOREGROUND_GREEN
;
wincolor_sink
()
wincolor_sink
()
:
out_handle_
(
HandleTrait
::
handle
())
:
out_handle_
(
HandleTrait
::
handle
()),
,
_mutex
(
ConsoleMutexTrait
::
console_mutex
())
_mutex
(
ConsoleMutexTrait
::
console_mutex
())
{
{
colors_
[
level
::
trace
]
=
WHITE
;
colors_
[
level
::
trace
]
=
WHITE
;
colors_
[
level
::
debug
]
=
CYAN
;
colors_
[
level
::
debug
]
=
CYAN
;
colors_
[
level
::
info
]
=
GREEN
;
colors_
[
level
::
info
]
=
GREEN
;
colors_
[
level
::
warn
]
=
YELLOW
|
BOLD
;
colors_
[
level
::
warn
]
=
YELLOW
|
BOLD
;
colors_
[
level
::
err
]
=
RED
|
BOLD
;
// red bold
colors_
[
level
::
err
]
=
RED
|
BOLD
;
// red bold
colors_
[
level
::
critical
]
=
BACKGROUND_RED
|
WHITE
|
BOLD
;
// white bold on red background
colors_
[
level
::
critical
]
=
BACKGROUND_RED
|
WHITE
|
BOLD
;
// white bold on red background
colors_
[
level
::
off
]
=
0
;
colors_
[
level
::
off
]
=
0
;
}
}
~
wincolor_sink
()
override
{
~
wincolor_sink
()
override
this
->
flush
();
{
}
this
->
flush
();
}
wincolor_sink
(
const
wincolor_sink
&
other
)
=
delete
;
wincolor_sink
&
operator
=
(
const
wincolor_sink
&
other
)
=
delete
;
wincolor_sink
(
const
wincolor_sink
&
other
)
=
delete
;
wincolor_sink
&
operator
=
(
const
wincolor_sink
&
other
)
=
delete
;
// change the color for the given level
void
set_color
(
level
::
level_enum
level
,
WORD
color
)
// change the color for the given level
{
void
set_color
(
level
::
level_enum
level
,
WORD
color
)
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
{
colors_
[
level
]
=
color
;
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
}
colors_
[
level
]
=
color
;
}
void
log
(
const
details
::
log_msg
&
msg
)
SPDLOG_FINAL
override
{
void
log
(
const
details
::
log_msg
&
msg
)
SPDLOG_FINAL
override
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
{
std
::
lock_guard
<
mutex_t
>
lock
(
_mutex
);
if
(
msg
.
color_range_end
>
msg
.
color_range_start
)
{
if
(
msg
.
color_range_end
>
msg
.
color_range_start
)
// before color range
{
_print_range
(
msg
,
0
,
msg
.
color_range_start
);
// before color range
_print_range
(
msg
,
0
,
msg
.
color_range_start
);
// in color range
auto
orig_attribs
=
set_console_attribs
(
colors_
[
msg
.
level
]);
// in color range
_print_range
(
msg
,
msg
.
color_range_start
,
msg
.
color_range_end
);
auto
orig_attribs
=
set_console_attribs
(
colors_
[
msg
.
level
]);
::
SetConsoleTextAttribute
(
out_handle_
,
orig_attribs
);
// reset to orig colors
_print_range
(
msg
,
msg
.
color_range_start
,
msg
.
color_range_end
);
// after color range
::
SetConsoleTextAttribute
(
out_handle_
,
orig_attribs
);
// reset to orig colors
_print_range
(
msg
,
msg
.
color_range_end
,
msg
.
formatted
.
size
());
// after color range
}
_print_range
(
msg
,
msg
.
color_range_end
,
msg
.
formatted
.
size
());
else
// print without colors if color range is invalid
}
{
else
// print without colors if color range is invalid
_print_range
(
msg
,
0
,
msg
.
formatted
.
size
());
{
}
_print_range
(
msg
,
0
,
msg
.
formatted
.
size
());
}
}
}
void
flush
()
SPDLOG_FINAL
override
{
void
flush
()
SPDLOG_FINAL
override
// windows console always flushed?
{
}
// windows console always flushed?
}
private
:
using
mutex_t
=
typename
ConsoleMutexTrait
::
mutex_t
;
private
:
// set color and return the orig console attributes (for resetting later)
using
mutex_t
=
typename
ConsoleMutexTrait
::
mutex_t
;
WORD
set_console_attribs
(
WORD
attribs
)
// set color and return the orig console attributes (for resetting later)
{
WORD
set_console_attribs
(
WORD
attribs
)
CONSOLE_SCREEN_BUFFER_INFO
orig_buffer_info
;
{
::
GetConsoleScreenBufferInfo
(
out_handle_
,
&
orig_buffer_info
);
CONSOLE_SCREEN_BUFFER_INFO
orig_buffer_info
;
WORD
back_color
=
orig_buffer_info
.
wAttributes
;
::
GetConsoleScreenBufferInfo
(
out_handle_
,
&
orig_buffer_info
);
// retrieve the current background color
WORD
back_color
=
orig_buffer_info
.
wAttributes
;
back_color
&=
static_cast
<
WORD
>
(
~
(
FOREGROUND_RED
|
FOREGROUND_GREEN
|
FOREGROUND_BLUE
|
FOREGROUND_INTENSITY
));
// retrieve the current background color
// keep the background color unchanged
back_color
&=
static_cast
<
WORD
>
(
~
(
FOREGROUND_RED
|
FOREGROUND_GREEN
|
FOREGROUND_BLUE
|
FOREGROUND_INTENSITY
));
::
SetConsoleTextAttribute
(
out_handle_
,
attribs
|
back_color
);
// keep the background color unchanged
return
orig_buffer_info
.
wAttributes
;
// return orig attribs
::
SetConsoleTextAttribute
(
out_handle_
,
attribs
|
back_color
);
}
return
orig_buffer_info
.
wAttributes
;
// return orig attribs
}
// print a range of formatted message to console
void
_print_range
(
const
details
::
log_msg
&
msg
,
size_t
start
,
size_t
end
)
// print a range of formatted message to console
{
void
_print_range
(
const
details
::
log_msg
&
msg
,
size_t
start
,
size_t
end
)
auto
size
=
static_cast
<
DWORD
>
(
end
-
start
);
{
::
WriteConsoleA
(
out_handle_
,
msg
.
formatted
.
data
()
+
start
,
size
,
nullptr
,
nullptr
);
auto
size
=
static_cast
<
DWORD
>
(
end
-
start
);
}
::
WriteConsoleA
(
out_handle_
,
msg
.
formatted
.
data
()
+
start
,
size
,
nullptr
,
nullptr
);
}
HANDLE
out_handle_
;
mutex_t
&
_mutex
;
HANDLE
out_handle_
;
std
::
unordered_map
<
level
::
level_enum
,
WORD
,
level
::
level_hasher
>
colors_
;
mutex_t
&
_mutex
;
};
std
::
unordered_map
<
level
::
level_enum
,
WORD
,
level
::
level_hasher
>
colors_
;
};
using
wincolor_stdout_sink_mt
=
wincolor_sink
<
details
::
console_stdout_trait
,
details
::
console_mutex_trait
>
;
using
wincolor_stdout_sink_st
=
wincolor_sink
<
details
::
console_stdout_trait
,
details
::
console_null_mutex_trait
>
;
using
wincolor_stdout_sink_mt
=
wincolor_sink
<
details
::
console_stdout_trait
,
details
::
console_mutex_trait
>
;
using
wincolor_stderr_sink_mt
=
wincolor_sink
<
details
::
console_stderr_trait
,
details
::
console_mutex_trait
>
;
using
wincolor_stdout_sink_st
=
wincolor_sink
<
details
::
console_stdout_trait
,
details
::
console_null_mutex_trait
>
;
using
wincolor_stderr_sink_st
=
wincolor_sink
<
details
::
console_stderr_trait
,
details
::
console_null_mutex_trait
>
;
using
wincolor_stderr_sink_mt
=
wincolor_sink
<
details
::
console_stderr_trait
,
details
::
console_mutex_trait
>
;
}
// namespace sinks
using
wincolor_stderr_sink_st
=
wincolor_sink
<
details
::
console_stderr_trait
,
details
::
console_null_mutex_trait
>
;
}
// namespace sinks
}
// namespace spdlog
}
// namespace spdlog
include/spdlog/spdlog.h
View file @
c962c883
...
@@ -7,8 +7,8 @@
...
@@ -7,8 +7,8 @@
#pragma once
#pragma once
#include "details/registry.h"
#include "common.h"
#include "common.h"
#include "details/registry.h"
#include "logger.h"
#include "logger.h"
#include <chrono>
#include <chrono>
...
@@ -32,7 +32,6 @@ struct default_factory
...
@@ -32,7 +32,6 @@ struct default_factory
}
}
};
};
// Create and register a logger with a templated sink type
// Create and register a logger with a templated sink type
// The logger's level, formatter and flush level will be set according the global settings.
// The logger's level, formatter and flush level will be set according the global settings.
// Example:
// Example:
...
@@ -116,7 +115,6 @@ inline void drop_all()
...
@@ -116,7 +115,6 @@ inline void drop_all()
details
::
registry
::
instance
().
drop_all
();
details
::
registry
::
instance
().
drop_all
();
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
//
// Trace & Debug can be switched on/off at compile time for zero cost debug statements.
// Trace & Debug can be switched on/off at compile time for zero cost debug statements.
...
...
tests/includes.h
View file @
c962c883
...
@@ -12,9 +12,8 @@
...
@@ -12,9 +12,8 @@
#define SPDLOG_TRACE_ON
#define SPDLOG_TRACE_ON
#define SPDLOG_DEBUG_ON
#define SPDLOG_DEBUG_ON
#include "../include/spdlog/spdlog.h"
#include "../include/spdlog/async.h"
#include "../include/spdlog/async.h"
#include "../include/spdlog/sinks/null_sink.h"
#include "../include/spdlog/sinks/file_sinks.h"
#include "../include/spdlog/sinks/file_sinks.h"
#include "../include/spdlog/sinks/null_sink.h"
#include "../include/spdlog/sinks/ostream_sink.h"
#include "../include/spdlog/sinks/ostream_sink.h"
#include "../include/spdlog/spdlog.h"
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment