Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
spdlog
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
spdlog
Commits
06ffde63
Commit
06ffde63
authored
Nov 28, 2015
by
gabime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed flush of logs in async mode
parent
860015cc
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
92 additions
and
28 deletions
+92
-28
include/spdlog/async_logger.h
include/spdlog/async_logger.h
+1
-0
include/spdlog/details/async_log_helper.h
include/spdlog/details/async_log_helper.h
+81
-26
include/spdlog/details/async_logger_impl.h
include/spdlog/details/async_logger_impl.h
+9
-1
include/spdlog/logger.h
include/spdlog/logger.h
+1
-1
No files found.
include/spdlog/async_logger.h
View file @
06ffde63
...
...
@@ -76,6 +76,7 @@ public:
const
std
::
chrono
::
milliseconds
&
flush_interval_ms
=
std
::
chrono
::
milliseconds
::
zero
());
void
flush
()
override
;
protected:
void
_log_msg
(
details
::
log_msg
&
msg
)
override
;
void
_set_formatter
(
spdlog
::
formatter_ptr
msg_formatter
)
override
;
...
...
include/spdlog/details/async_log_helper.h
View file @
06ffde63
...
...
@@ -35,7 +35,6 @@
#include <chrono>
#include <thread>
#include <atomic>
#include <functional>
#include "../common.h"
...
...
@@ -43,7 +42,7 @@
#include "./mpmc_bounded_q.h"
#include "./log_msg.h"
#include "./format.h"
#include "os.h"
#include "
./
os.h"
namespace
spdlog
...
...
@@ -55,6 +54,12 @@ class async_log_helper
{
// Async msg to move to/from the queue
// Movable only. should never be copied
enum
class
async_msg_type
{
log
,
flush
,
terminate
};
struct
async_msg
{
std
::
string
logger_name
;
...
...
@@ -62,6 +67,7 @@ class async_log_helper
log_clock
::
time_point
time
;
size_t
thread_id
;
std
::
string
txt
;
async_msg_type
msg_type
;
async_msg
()
=
default
;
~
async_msg
()
=
default
;
...
...
@@ -70,9 +76,13 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
logger_name
(
std
::
move
(
other
.
logger_name
)),
level
(
std
::
move
(
other
.
level
)),
time
(
std
::
move
(
other
.
time
)),
txt
(
std
::
move
(
other
.
txt
))
txt
(
std
::
move
(
other
.
txt
)),
msg_type
(
std
::
move
(
other
.
msg_type
))
{}
async_msg
(
async_msg_type
msg_type
)
:
msg_type
(
msg_type
)
{};
async_msg
&
operator
=
(
async_msg
&&
other
)
SPDLOG_NOEXCEPT
{
logger_name
=
std
::
move
(
other
.
logger_name
);
...
...
@@ -80,6 +90,7 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
time
=
std
::
move
(
other
.
time
);
thread_id
=
other
.
thread_id
;
txt
=
std
::
move
(
other
.
txt
);
msg_type
=
other
.
msg_type
;
return
*
this
;
}
// never copy or assign. should only be moved..
...
...
@@ -92,10 +103,12 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
level
(
m
.
level
),
time
(
m
.
time
),
thread_id
(
m
.
thread_id
),
txt
(
m
.
raw
.
data
(),
m
.
raw
.
size
())
txt
(
m
.
raw
.
data
(),
m
.
raw
.
size
()),
msg_type
(
async_msg_type
::
log
)
{}
// copy into log_msg
void
fill_log_msg
(
log_msg
&
msg
)
{
...
...
@@ -130,6 +143,8 @@ public:
void
set_formatter
(
formatter_ptr
);
void
flush
();
private:
formatter_ptr
_formatter
;
...
...
@@ -138,6 +153,11 @@ private:
// queue of messages to log
q_type
_q
;
bool
_flush_requested
;
bool
_terminate_requested
;
// last exception thrown from the worker thread
std
::
shared_ptr
<
spdlog_ex
>
_last_workerthread_ex
;
...
...
@@ -153,14 +173,16 @@ private:
// worker thread
std
::
thread
_worker_thread
;
void
push_msg
(
async_msg
&
new_msg
);
// throw last worker thread exception or if worker thread is not active
void
throw_if_bad_worker
();
// worker thread main loop
void
worker_loop
();
// pop next message from the queue and process it
// return
true if a message was available (queue was not empty), will set the last_pop to the pop time
// pop next message from the queue and process it
. will set the last_pop to the pop time
// return
false if termination of the queue is required
bool
process_next_msg
(
log_clock
::
time_point
&
last_pop
,
log_clock
::
time_point
&
last_flush
);
void
handle_flush_interval
(
log_clock
::
time_point
&
now
,
log_clock
::
time_point
&
last_flush
);
...
...
@@ -168,8 +190,6 @@ private:
// sleep,yield or return immediatly using the time passed since last message as a hint
static
void
sleep_or_yield
(
const
spdlog
::
log_clock
::
time_point
&
now
,
const
log_clock
::
time_point
&
last_op_time
);
};
}
}
...
...
@@ -177,10 +197,18 @@ private:
///////////////////////////////////////////////////////////////////////////////
// async_sink class implementation
///////////////////////////////////////////////////////////////////////////////
inline
spdlog
::
details
::
async_log_helper
::
async_log_helper
(
formatter_ptr
formatter
,
const
std
::
vector
<
sink_ptr
>&
sinks
,
size_t
queue_size
,
const
async_overflow_policy
overflow_policy
,
const
std
::
function
<
void
()
>&
worker_warmup_cb
,
const
std
::
chrono
::
milliseconds
&
flush_interval_ms
)
:
inline
spdlog
::
details
::
async_log_helper
::
async_log_helper
(
formatter_ptr
formatter
,
const
std
::
vector
<
sink_ptr
>&
sinks
,
size_t
queue_size
,
const
async_overflow_policy
overflow_policy
,
const
std
::
function
<
void
()
>&
worker_warmup_cb
,
const
std
::
chrono
::
milliseconds
&
flush_interval_ms
)
:
_formatter
(
formatter
),
_sinks
(
sinks
),
_q
(
queue_size
),
_flush_requested
(
false
),
_terminate_requested
(
false
),
_overflow_policy
(
overflow_policy
),
_worker_warmup_cb
(
worker_warmup_cb
),
_flush_interval_ms
(
flush_interval_ms
),
...
...
@@ -191,13 +219,12 @@ inline spdlog::details::async_log_helper::async_log_helper(formatter_ptr formatt
// and wait for it to finish gracefully
inline
spdlog
::
details
::
async_log_helper
::~
async_log_helper
()
{
try
{
log
(
log_msg
(
level
::
off
));
push_msg
(
async_msg
(
async_msg_type
::
terminate
));
_worker_thread
.
join
();
}
catch
(...)
//
Dont crash if thread not joinable
catch
(...)
//
don't crash in destructor
{}
}
...
...
@@ -205,8 +232,16 @@ inline spdlog::details::async_log_helper::~async_log_helper()
//Try to push and block until succeeded
inline
void
spdlog
::
details
::
async_log_helper
::
log
(
const
details
::
log_msg
&
msg
)
{
throw_if_bad_worker
();
async_msg
new_msg
(
msg
);
push_msg
(
new_msg
);
}
//Try to push and block until succeeded
inline
void
spdlog
::
details
::
async_log_helper
::
push_msg
(
details
::
async_log_helper
::
async_msg
&
new_msg
)
{
throw_if_bad_worker
();
if
(
!
_q
.
enqueue
(
std
::
move
(
new_msg
))
&&
_overflow_policy
!=
async_overflow_policy
::
discard_log_msg
)
{
auto
last_op_time
=
details
::
os
::
now
();
...
...
@@ -215,12 +250,16 @@ inline void spdlog::details::async_log_helper::log(const details::log_msg& msg)
{
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
)));
}
}
inline
void
spdlog
::
details
::
async_log_helper
::
flush
()
{
push_msg
(
async_msg
(
async_msg_type
::
flush
));
}
inline
void
spdlog
::
details
::
async_log_helper
::
worker_loop
()
{
try
...
...
@@ -251,31 +290,47 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
if
(
_q
.
dequeue
(
incoming_async_msg
))
{
last_pop
=
details
::
os
::
now
();
if
(
incoming_async_msg
.
level
==
level
::
off
)
return
false
;
incoming_async_msg
.
fill_log_msg
(
incoming_log_msg
);
_formatter
->
format
(
incoming_log_msg
);
for
(
auto
&
s
:
_sinks
)
s
->
log
(
incoming_log_msg
);
switch
(
incoming_async_msg
.
msg_type
)
{
case
async_msg_type
:
:
flush
:
_flush_requested
=
true
;
break
;
case
async_msg_type
:
:
terminate
:
_flush_requested
=
true
;
_terminate_requested
=
true
;
break
;
default:
incoming_async_msg
.
fill_log_msg
(
incoming_log_msg
);
_formatter
->
format
(
incoming_log_msg
);
for
(
auto
&
s
:
_sinks
)
s
->
log
(
incoming_log_msg
);
}
return
true
;
}
else
//empty queue
// Handle empty queue..
// This is the only place where the queue can terminate or flush to avoid losing messages already in the queue
else
{
auto
now
=
details
::
os
::
now
();
handle_flush_interval
(
now
,
last_flush
);
sleep_or_yield
(
now
,
last_pop
);
return
!
_terminate_requested
;
}
return
true
;
}
inline
void
spdlog
::
details
::
async_log_helper
::
handle_flush_interval
(
log_clock
::
time_point
&
now
,
log_clock
::
time_point
&
last_flush
)
{
if
(
_flush_interval_ms
!=
std
::
chrono
::
milliseconds
::
zero
()
&&
now
-
last_flush
>=
_flush_interval_ms
)
auto
should_flush
=
_flush_requested
||
(
_flush_interval_ms
!=
std
::
chrono
::
milliseconds
::
zero
()
&&
now
-
last_flush
>=
_flush_interval_ms
);
if
(
should_flush
)
{
for
(
auto
&
s
:
_sinks
)
s
->
flush
();
now
=
last_flush
=
details
::
os
::
now
();
_flush_requested
=
false
;
}
}
inline
void
spdlog
::
details
::
async_log_helper
::
set_formatter
(
formatter_ptr
msg_formatter
)
...
...
include/spdlog/details/async_logger_impl.h
View file @
06ffde63
...
...
@@ -60,9 +60,17 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name,
const
async_overflow_policy
overflow_policy
,
const
std
::
function
<
void
()
>&
worker_warmup_cb
,
const
std
::
chrono
::
milliseconds
&
flush_interval_ms
)
:
async_logger
(
logger_name
,
{
single_sink
},
queue_size
,
overflow_policy
,
worker_warmup_cb
,
flush_interval_ms
)
{}
async_logger
(
logger_name
,
{
single_sink
},
queue_size
,
overflow_policy
,
worker_warmup_cb
,
flush_interval_ms
)
{}
inline
void
spdlog
::
async_logger
::
flush
()
{
_async_log_helper
->
flush
();
}
inline
void
spdlog
::
async_logger
::
_set_formatter
(
spdlog
::
formatter_ptr
msg_formatter
)
{
_formatter
=
msg_formatter
;
...
...
include/spdlog/logger.h
View file @
06ffde63
...
...
@@ -107,7 +107,7 @@ public:
void
set_pattern
(
const
std
::
string
&
);
void
set_formatter
(
formatter_ptr
);
void
flush
();
v
irtual
v
oid
flush
();
protected:
virtual
void
_log_msg
(
details
::
log_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