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
0c276bea
Commit
0c276bea
authored
Mar 27, 2017
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
astyle
parent
5a8cecdf
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
192 additions
and
100 deletions
+192
-100
async_logger.h
include/spdlog/async_logger.h
+0
-0
async_log_helper.h
include/spdlog/details/async_log_helper.h
+39
-24
async_logger_impl.h
include/spdlog/details/async_logger_impl.h
+0
-0
format.h
include/spdlog/fmt/bundled/format.h
+0
-0
ostream.h
include/spdlog/fmt/bundled/ostream.h
+24
-13
posix.h
include/spdlog/fmt/bundled/posix.h
+111
-54
time.h
include/spdlog/fmt/bundled/time.h
+10
-5
logger.h
include/spdlog/logger.h
+0
-0
errors.cpp
tests/errors.cpp
+8
-4
No files found.
include/spdlog/async_logger.h
View file @
0c276bea
include/spdlog/details/async_log_helper.h
View file @
0c276bea
...
...
@@ -32,11 +32,11 @@
namespace
spdlog
{
namespace
details
{
namespace
details
{
class
async_log_helper
{
class
async_log_helper
{
// Async msg to move to/from the queue
// Movable only. should never be copied
enum
class
async_msg_type
...
...
@@ -58,7 +58,7 @@ namespace spdlog
~
async_msg
()
=
default
;
async_msg
(
async_msg
&&
other
)
SPDLOG_NOEXCEPT
:
async_msg
(
async_msg
&&
other
)
SPDLOG_NOEXCEPT
:
logger_name
(
std
::
move
(
other
.
logger_name
)),
level
(
std
::
move
(
other
.
level
)),
time
(
std
::
move
(
other
.
time
)),
...
...
@@ -109,7 +109,7 @@ namespace spdlog
}
};
public
:
public
:
using
item_type
=
async_msg
;
using
q_type
=
details
::
mpmc_bounded_queue
<
item_type
>
;
...
...
@@ -137,7 +137,7 @@ namespace spdlog
void
set_error_handler
(
spdlog
::
log_err_handler
err_handler
);
private
:
private
:
formatter_ptr
_formatter
;
std
::
vector
<
std
::
shared_ptr
<
sinks
::
sink
>>
_sinks
;
...
...
@@ -183,8 +183,8 @@ namespace spdlog
// wait until the queue is empty
void
wait_empty_q
();
};
}
};
}
}
///////////////////////////////////////////////////////////////////////////////
...
...
@@ -216,7 +216,8 @@ inline spdlog::details::async_log_helper::async_log_helper(
// and wait for it to finish gracefully
inline
spdlog
::
details
::
async_log_helper
::~
async_log_helper
()
{
try
{
try
{
push_msg
(
async_msg
(
async_msg_type
::
terminate
));
_worker_thread
.
join
();
}
...
...
@@ -234,13 +235,16 @@ inline void spdlog::details::async_log_helper::log(const details::log_msg& msg)
inline
void
spdlog
::
details
::
async_log_helper
::
push_msg
(
details
::
async_log_helper
::
async_msg
&&
new_msg
)
{
if
(
!
_q
.
enqueue
(
std
::
move
(
new_msg
))
&&
_overflow_policy
!=
async_overflow_policy
::
discard_log_msg
)
{
if
(
!
_q
.
enqueue
(
std
::
move
(
new_msg
))
&&
_overflow_policy
!=
async_overflow_policy
::
discard_log_msg
)
{
auto
last_op_time
=
details
::
os
::
now
();
auto
now
=
last_op_time
;
do
{
do
{
now
=
details
::
os
::
now
();
sleep_or_yield
(
now
,
last_op_time
);
}
while
(
!
_q
.
enqueue
(
std
::
move
(
new_msg
)));
}
while
(
!
_q
.
enqueue
(
std
::
move
(
new_msg
)));
}
}
...
...
@@ -258,14 +262,18 @@ inline void spdlog::details::async_log_helper::worker_loop()
auto
last_pop
=
details
::
os
::
now
();
auto
last_flush
=
last_pop
;
auto
active
=
true
;
while
(
active
)
{
try
{
while
(
active
)
{
try
{
active
=
process_next_msg
(
last_pop
,
last_flush
);
}
catch
(
const
std
::
exception
&
ex
)
{
catch
(
const
std
::
exception
&
ex
)
{
_err_handler
(
ex
.
what
());
}
catch
(...)
{
catch
(...)
{
_err_handler
(
"Unknown exception"
);
}
}
...
...
@@ -280,9 +288,11 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
{
async_msg
incoming_async_msg
;
if
(
_q
.
dequeue
(
incoming_async_msg
))
{
if
(
_q
.
dequeue
(
incoming_async_msg
))
{
last_pop
=
details
::
os
::
now
();
switch
(
incoming_async_msg
.
msg_type
)
{
switch
(
incoming_async_msg
.
msg_type
)
{
case
async_msg_type
:
:
flush
:
_flush_requested
=
true
;
break
;
...
...
@@ -296,8 +306,10 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
log_msg
incoming_log_msg
;
incoming_async_msg
.
fill_log_msg
(
incoming_log_msg
);
_formatter
->
format
(
incoming_log_msg
);
for
(
auto
&
s
:
_sinks
)
{
if
(
s
->
should_log
(
incoming_log_msg
.
level
))
{
for
(
auto
&
s
:
_sinks
)
{
if
(
s
->
should_log
(
incoming_log_msg
.
level
))
{
s
->
log
(
incoming_log_msg
);
}
}
...
...
@@ -307,7 +319,8 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
// Handle empty queue..
// This is the only place where the queue can terminate or flush to avoid losing messages already in the queue
else
{
else
{
auto
now
=
details
::
os
::
now
();
handle_flush_interval
(
now
,
last_flush
);
sleep_or_yield
(
now
,
last_pop
);
...
...
@@ -319,7 +332,8 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
inline
void
spdlog
::
details
::
async_log_helper
::
handle_flush_interval
(
log_clock
::
time_point
&
now
,
log_clock
::
time_point
&
last_flush
)
{
auto
should_flush
=
_flush_requested
||
(
_flush_interval_ms
!=
std
::
chrono
::
milliseconds
::
zero
()
&&
now
-
last_flush
>=
_flush_interval_ms
);
if
(
should_flush
)
{
if
(
should_flush
)
{
for
(
auto
&
s
:
_sinks
)
s
->
flush
();
now
=
last_flush
=
details
::
os
::
now
();
...
...
@@ -362,7 +376,8 @@ inline void spdlog::details::async_log_helper::sleep_or_yield(const spdlog::log_
inline
void
spdlog
::
details
::
async_log_helper
::
wait_empty_q
()
{
auto
last_op
=
details
::
os
::
now
();
while
(
_q
.
approx_size
()
>
0
)
{
while
(
_q
.
approx_size
()
>
0
)
{
sleep_or_yield
(
details
::
os
::
now
(),
last_op
);
}
}
...
...
include/spdlog/details/async_logger_impl.h
View file @
0c276bea
include/spdlog/fmt/bundled/format.h
View file @
0c276bea
This source diff could not be displayed because it is too large. You can
view the blob
instead.
include/spdlog/fmt/bundled/ostream.h
View file @
0c276bea
...
...
@@ -13,26 +13,32 @@
#include "format.h"
#include <ostream>
namespace
fmt
{
namespace
fmt
{
namespace
internal
{
namespace
internal
{
template
<
class
Char
>
class
FormatBuf
:
public
std
::
basic_streambuf
<
Char
>
{
private
:
class
FormatBuf
:
public
std
::
basic_streambuf
<
Char
>
{
private
:
typedef
typename
std
::
basic_streambuf
<
Char
>::
int_type
int_type
;
typedef
typename
std
::
basic_streambuf
<
Char
>::
traits_type
traits_type
;
Buffer
<
Char
>
&
buffer_
;
Char
*
start_
;
public
:
FormatBuf
(
Buffer
<
Char
>
&
buffer
)
:
buffer_
(
buffer
),
start_
(
&
buffer
[
0
])
{
public
:
FormatBuf
(
Buffer
<
Char
>
&
buffer
)
:
buffer_
(
buffer
),
start_
(
&
buffer
[
0
])
{
this
->
setp
(
start_
,
start_
+
buffer_
.
capacity
());
}
int_type
overflow
(
int_type
ch
=
traits_type
::
eof
())
{
if
(
!
traits_type
::
eq_int_type
(
ch
,
traits_type
::
eof
()))
{
int_type
overflow
(
int_type
ch
=
traits_type
::
eof
())
{
if
(
!
traits_type
::
eq_int_type
(
ch
,
traits_type
::
eof
()))
{
size_t
buf_size
=
size
();
buffer_
.
resize
(
buf_size
);
buffer_
.
reserve
(
buf_size
*
2
);
...
...
@@ -44,14 +50,16 @@ class FormatBuf : public std::basic_streambuf<Char> {
return
ch
;
}
size_t
size
()
const
{
size_t
size
()
const
{
return
to_unsigned
(
this
->
pptr
()
-
start_
);
}
};
Yes
&
convert
(
std
::
ostream
&
);
struct
DummyStream
:
std
::
ostream
{
struct
DummyStream
:
std
::
ostream
{
DummyStream
();
// Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream.
void
operator
<<
(
Null
<>
);
...
...
@@ -60,9 +68,11 @@ struct DummyStream : std::ostream {
No
&
operator
<<
(
std
::
ostream
&
,
int
);
template
<
typename
T
>
struct
ConvertToIntImpl
<
T
,
true
>
{
struct
ConvertToIntImpl
<
T
,
true
>
{
// Convert to int only if T doesn't have an overloaded operator<<.
enum
{
enum
{
value
=
sizeof
(
convert
(
get
<
DummyStream
>
()
<<
get
<
T
>
()))
==
sizeof
(
No
)
};
};
...
...
@@ -71,7 +81,8 @@ struct ConvertToIntImpl<T, true> {
// Formats a value.
template
<
typename
Char
,
typename
ArgFormatter
,
typename
T
>
void
format
(
BasicFormatter
<
Char
,
ArgFormatter
>
&
f
,
const
Char
*&
format_str
,
const
T
&
value
)
{
const
Char
*&
format_str
,
const
T
&
value
)
{
internal
::
MemoryBuffer
<
Char
,
internal
::
INLINE_BUFFER_SIZE
>
buffer
;
internal
::
FormatBuf
<
Char
>
format_buf
(
buffer
);
...
...
include/spdlog/fmt/bundled/posix.h
View file @
0c276bea
...
...
@@ -83,31 +83,39 @@
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
namespace
fmt
{
namespace
fmt
{
// An error code.
class
ErrorCode
{
private
:
class
ErrorCode
{
private
:
int
value_
;
public
:
explicit
ErrorCode
(
int
value
=
0
)
FMT_NOEXCEPT
:
value_
(
value
)
{}
public
:
explicit
ErrorCode
(
int
value
=
0
)
FMT_NOEXCEPT
:
value_
(
value
)
{}
int
get
()
const
FMT_NOEXCEPT
{
return
value_
;
}
int
get
()
const
FMT_NOEXCEPT
{
return
value_
;
}
};
// A buffered file.
class
BufferedFile
{
private
:
class
BufferedFile
{
private
:
FILE
*
file_
;
friend
class
File
;
explicit
BufferedFile
(
FILE
*
f
)
:
file_
(
f
)
{}
public
:
public
:
// Constructs a BufferedFile object which doesn't represent any file.
BufferedFile
()
FMT_NOEXCEPT
:
file_
(
0
)
{}
BufferedFile
()
FMT_NOEXCEPT
:
file_
(
0
)
{}
// Destroys the object closing the file it represents if any.
~
BufferedFile
()
FMT_NOEXCEPT
;
...
...
@@ -116,31 +124,37 @@ class BufferedFile {
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private
:
private
:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct
Proxy
{
struct
Proxy
{
FILE
*
file
;
};
public
:
// A "move constructor" for moving from a temporary.
BufferedFile
(
Proxy
p
)
FMT_NOEXCEPT
:
file_
(
p
.
file
)
{}
BufferedFile
(
Proxy
p
)
FMT_NOEXCEPT
:
file_
(
p
.
file
)
{}
// A "move constructor" for moving from an lvalue.
BufferedFile
(
BufferedFile
&
f
)
FMT_NOEXCEPT
:
file_
(
f
.
file_
)
{
BufferedFile
(
BufferedFile
&
f
)
FMT_NOEXCEPT
:
file_
(
f
.
file_
)
{
f
.
file_
=
0
;
}
// A "move assignment operator" for moving from a temporary.
BufferedFile
&
operator
=
(
Proxy
p
)
{
BufferedFile
&
operator
=
(
Proxy
p
)
{
close
();
file_
=
p
.
file
;
return
*
this
;
}
// A "move assignment operator" for moving from an lvalue.
BufferedFile
&
operator
=
(
BufferedFile
&
other
)
{
BufferedFile
&
operator
=
(
BufferedFile
&
other
)
{
close
();
file_
=
other
.
file_
;
other
.
file_
=
0
;
...
...
@@ -149,22 +163,26 @@ public:
// Returns a proxy object for moving from a temporary:
// BufferedFile file = BufferedFile(...);
operator
Proxy
()
FMT_NOEXCEPT
{
operator
Proxy
()
FMT_NOEXCEPT
{
Proxy
p
=
{
file_
};
file_
=
0
;
return
p
;
}
#else
private
:
private
:
FMT_DISALLOW_COPY_AND_ASSIGN
(
BufferedFile
);
public
:
BufferedFile
(
BufferedFile
&&
other
)
FMT_NOEXCEPT
:
file_
(
other
.
file_
)
{
public
:
BufferedFile
(
BufferedFile
&&
other
)
FMT_NOEXCEPT
:
file_
(
other
.
file_
)
{
other
.
file_
=
0
;
}
BufferedFile
&
operator
=
(
BufferedFile
&&
other
)
{
BufferedFile
&
operator
=
(
BufferedFile
&&
other
)
{
close
();
file_
=
other
.
file_
;
other
.
file_
=
0
;
...
...
@@ -179,13 +197,17 @@ public:
void
close
();
// Returns the pointer to a FILE object representing this file.
FILE
*
get
()
const
FMT_NOEXCEPT
{
return
file_
;
}
FILE
*
get
()
const
FMT_NOEXCEPT
{
return
file_
;
}
// We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro.
int
(
fileno
)()
const
;
void
print
(
CStringRef
format_str
,
const
ArgList
&
args
)
{
void
print
(
CStringRef
format_str
,
const
ArgList
&
args
)
{
fmt
::
print
(
file_
,
format_str
,
args
);
}
FMT_VARIADIC
(
void
,
print
,
CStringRef
)
...
...
@@ -197,23 +219,26 @@ public:
// closing the file multiple times will cause a crash on Windows rather
// than an exception. You can get standard behavior by overriding the
// invalid parameter handler with _set_invalid_parameter_handler.
class
File
{
private
:
class
File
{
private
:
int
fd_
;
// File descriptor.
// Constructs a File object with a given descriptor.
explicit
File
(
int
fd
)
:
fd_
(
fd
)
{}
public
:
public
:
// Possible values for the oflag argument to the constructor.
enum
{
enum
{
RDONLY
=
FMT_POSIX
(
O_RDONLY
),
// Open for reading only.
WRONLY
=
FMT_POSIX
(
O_WRONLY
),
// Open for writing only.
RDWR
=
FMT_POSIX
(
O_RDWR
)
// Open for reading and writing.
};
// Constructs a File object which doesn't represent any file.
File
()
FMT_NOEXCEPT
:
fd_
(
-
1
)
{}
File
()
FMT_NOEXCEPT
:
fd_
(
-
1
)
{}
// Opens a file and constructs a File object representing this file.
File
(
CStringRef
path
,
int
oflag
);
...
...
@@ -222,31 +247,37 @@ class File {
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private
:
private
:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct
Proxy
{
struct
Proxy
{
int
fd
;
};
public
:
public
:
// A "move constructor" for moving from a temporary.
File
(
Proxy
p
)
FMT_NOEXCEPT
:
fd_
(
p
.
fd
)
{}
File
(
Proxy
p
)
FMT_NOEXCEPT
:
fd_
(
p
.
fd
)
{}
// A "move constructor" for moving from an lvalue.
File
(
File
&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
File
(
File
&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
other
.
fd_
=
-
1
;
}
// A "move assignment operator" for moving from a temporary.
File
&
operator
=
(
Proxy
p
)
{
File
&
operator
=
(
Proxy
p
)
{
close
();
fd_
=
p
.
fd
;
return
*
this
;
}
// A "move assignment operator" for moving from an lvalue.
File
&
operator
=
(
File
&
other
)
{
File
&
operator
=
(
File
&
other
)
{
close
();
fd_
=
other
.
fd_
;
other
.
fd_
=
-
1
;
...
...
@@ -255,22 +286,26 @@ class File {
// Returns a proxy object for moving from a temporary:
// File file = File(...);
operator
Proxy
()
FMT_NOEXCEPT
{
operator
Proxy
()
FMT_NOEXCEPT
{
Proxy
p
=
{
fd_
};
fd_
=
-
1
;
return
p
;
}
#else
private
:
private
:
FMT_DISALLOW_COPY_AND_ASSIGN
(
File
);
public
:
File
(
File
&&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
public
:
File
(
File
&&
other
)
FMT_NOEXCEPT
:
fd_
(
other
.
fd_
)
{
other
.
fd_
=
-
1
;
}
File
&
operator
=
(
File
&&
other
)
{
File
&
operator
=
(
File
&&
other
)
{
close
();
fd_
=
other
.
fd_
;
other
.
fd_
=
-
1
;
...
...
@@ -282,7 +317,10 @@ class File {
~
File
()
FMT_NOEXCEPT
;
// Returns the file descriptor.
int
descriptor
()
const
FMT_NOEXCEPT
{
return
fd_
;
}
int
descriptor
()
const
FMT_NOEXCEPT
{
return
fd_
;
}
// Closes the file.
void
close
();
...
...
@@ -328,22 +366,26 @@ long getpagesize();
#ifdef FMT_LOCALE
// A "C" numeric locale.
class
Locale
{
private
:
class
Locale
{
private
:
# ifdef _MSC_VER
typedef
_locale_t
locale_t
;
enum
{
LC_NUMERIC_MASK
=
LC_NUMERIC
};
static
locale_t
newlocale
(
int
category_mask
,
const
char
*
locale
,
locale_t
)
{
static
locale_t
newlocale
(
int
category_mask
,
const
char
*
locale
,
locale_t
)
{
return
_create_locale
(
category_mask
,
locale
);
}
static
void
freelocale
(
locale_t
locale
)
{
static
void
freelocale
(
locale_t
locale
)
{
_free_locale
(
locale
);
}
static
double
strtod_l
(
const
char
*
nptr
,
char
**
endptr
,
_locale_t
locale
)
{
static
double
strtod_l
(
const
char
*
nptr
,
char
**
endptr
,
_locale_t
locale
)
{
return
_strtod_l
(
nptr
,
endptr
,
locale
);
}
# endif
...
...
@@ -352,20 +394,28 @@ class Locale {
FMT_DISALLOW_COPY_AND_ASSIGN
(
Locale
);
public
:
public
:
typedef
locale_t
Type
;
Locale
()
:
locale_
(
newlocale
(
LC_NUMERIC_MASK
,
"C"
,
NULL
))
{
Locale
()
:
locale_
(
newlocale
(
LC_NUMERIC_MASK
,
"C"
,
NULL
))
{
if
(
!
locale_
)
FMT_THROW
(
fmt
::
SystemError
(
errno
,
"cannot create locale"
));
}
~
Locale
()
{
freelocale
(
locale_
);
}
~
Locale
()
{
freelocale
(
locale_
);
}
Type
get
()
const
{
return
locale_
;
}
Type
get
()
const
{
return
locale_
;
}
// Converts string to floating-point number and advances str past the end
// of the parsed input.
double
strtod
(
const
char
*&
str
)
const
{
double
strtod
(
const
char
*&
str
)
const
{
char
*
end
=
0
;
double
result
=
strtod_l
(
str
,
&
end
,
locale_
);
str
=
end
;
...
...
@@ -376,10 +426,17 @@ class Locale {
}
// namespace fmt
#if !FMT_USE_RVALUE_REFERENCES
namespace
std
{
namespace
std
{
// For compatibility with C++98.
inline
fmt
::
BufferedFile
&
move
(
fmt
::
BufferedFile
&
f
)
{
return
f
;
}
inline
fmt
::
File
&
move
(
fmt
::
File
&
f
)
{
return
f
;
}
inline
fmt
::
BufferedFile
&
move
(
fmt
::
BufferedFile
&
f
)
{
return
f
;
}
inline
fmt
::
File
&
move
(
fmt
::
File
&
f
)
{
return
f
;
}
}
#endif
...
...
include/spdlog/fmt/bundled/time.h
View file @
0c276bea
...
...
@@ -13,10 +13,12 @@
#include "format.h"
#include <ctime>
namespace
fmt
{
namespace
fmt
{
template
<
typename
ArgFormatter
>
void
format
(
BasicFormatter
<
char
,
ArgFormatter
>
&
f
,
const
char
*&
format_str
,
const
std
::
tm
&
tm
)
{
const
char
*&
format_str
,
const
std
::
tm
&
tm
)
{
if
(
*
format_str
==
':'
)
++
format_str
;
const
char
*
end
=
format_str
;
...
...
@@ -29,14 +31,17 @@ void format(BasicFormatter<char, ArgFormatter> &f,
format
[
format
.
size
()
-
1
]
=
'\0'
;
Buffer
<
char
>
&
buffer
=
f
.
writer
().
buffer
();
std
::
size_t
start
=
buffer
.
size
();
for
(;;)
{
for
(;;)
{
std
::
size_t
size
=
buffer
.
capacity
()
-
start
;
std
::
size_t
count
=
std
::
strftime
(
&
buffer
[
start
],
size
,
&
format
[
0
],
&
tm
);
if
(
count
!=
0
)
{
if
(
count
!=
0
)
{
buffer
.
resize
(
start
+
count
);
break
;
}
if
(
size
>=
format
.
size
()
*
256
)
{
if
(
size
>=
format
.
size
()
*
256
)
{
// If the buffer is 256 times larger than the format string, assume
// that `strftime` gives an empty result. There doesn't seem to be a
// better way to distinguish the two cases:
...
...
include/spdlog/logger.h
View file @
0c276bea
tests/errors.cpp
View file @
0c276bea
...
...
@@ -45,7 +45,8 @@ TEST_CASE("custom_error_handler", "[errors]]")
std
::
string
filename
=
"logs/simple_log.txt"
;
auto
logger
=
spdlog
::
create
<
spdlog
::
sinks
::
simple_file_sink_mt
>
(
"logger"
,
filename
,
true
);
logger
->
flush_on
(
spdlog
::
level
::
info
);
logger
->
set_error_handler
([
=
](
const
std
::
string
&
msg
)
{
logger
->
set_error_handler
([
=
](
const
std
::
string
&
msg
)
{
throw
custom_ex
();
});
logger
->
info
(
"Good message #1"
);
...
...
@@ -58,7 +59,8 @@ TEST_CASE("default_error_handler2", "[errors]]")
{
auto
logger
=
spdlog
::
create
<
failing_sink
>
(
"failed_logger"
);
logger
->
set_error_handler
([
=
](
const
std
::
string
&
msg
)
{
logger
->
set_error_handler
([
=
](
const
std
::
string
&
msg
)
{
throw
custom_ex
();
});
REQUIRE_THROWS_AS
(
logger
->
info
(
"Some message"
),
custom_ex
);
...
...
@@ -72,7 +74,8 @@ TEST_CASE("async_error_handler", "[errors]]")
std
::
string
filename
=
"logs/simple_async_log.txt"
;
{
auto
logger
=
spdlog
::
create
<
spdlog
::
sinks
::
simple_file_sink_mt
>
(
"logger"
,
filename
,
true
);
logger
->
set_error_handler
([
=
](
const
std
::
string
&
msg
)
{
logger
->
set_error_handler
([
=
](
const
std
::
string
&
msg
)
{
std
::
ofstream
ofs
(
"logs/custom_err.txt"
);
if
(
!
ofs
)
throw
std
::
runtime_error
(
"Failed open logs/custom_err.txt"
);
ofs
<<
err_msg
;
...
...
@@ -95,7 +98,8 @@ TEST_CASE("async_error_handler2", "[errors]]")
spdlog
::
set_async_mode
(
128
);
{
auto
logger
=
spdlog
::
create
<
failing_sink
>
(
"failed_logger"
);
logger
->
set_error_handler
([
=
](
const
std
::
string
&
msg
)
{
logger
->
set_error_handler
([
=
](
const
std
::
string
&
msg
)
{
std
::
ofstream
ofs
(
"logs/custom_err2.txt"
);
if
(
!
ofs
)
throw
std
::
runtime_error
(
"Failed open logs/custom_err2.txt"
);
ofs
<<
err_msg
;
...
...
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