-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wip: logger: Write logs in separate thread
- Loading branch information
Showing
4 changed files
with
199 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#ifndef _LOGGER_COMMON_H | ||
#define _LOGGER_COMMON_H | ||
|
||
#include "tll/logger.h" | ||
#include "tll/logger/impl.h" | ||
#include "tll/util/refptr.h" | ||
#include "tll/util/time.h" | ||
|
||
#include <mutex> | ||
|
||
namespace tll::logger { | ||
|
||
struct tll_logger_obj_t : tll::util::refbase_t<tll_logger_obj_t, 0> | ||
{ | ||
const char * name = ""; | ||
void * obj = nullptr; | ||
tll_logger_impl_t * impl = nullptr; | ||
|
||
~tll_logger_obj_t() | ||
{ | ||
if (obj && impl && impl->log_free) | ||
impl->log_free(impl, name, obj); | ||
} | ||
|
||
auto log(tll::time_point ts, tll_logger_level_t level, std::string_view body) | ||
{ | ||
return (*impl->log)(ts.time_since_epoch().count(), name, level, body.data(), body.size(), obj); | ||
} | ||
}; | ||
|
||
struct Logger : public tll_logger_t, public tll::util::refbase_t<Logger> | ||
{ | ||
void destroy(); | ||
|
||
std::mutex lock; | ||
std::string name; | ||
tll::util::refptr_t<tll_logger_obj_t> impl; | ||
}; | ||
|
||
} // namespace tll::logger | ||
|
||
#endif//_LOGGER_COMMON_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
#ifndef _LOGGER_THREAD_H | ||
#define _LOGGER_THREAD_H | ||
|
||
#include "tll/cppring.h" | ||
#include "tll/logger.h" | ||
#include "tll/util/time.h" | ||
|
||
#include <poll.h> | ||
#include <sys/eventfd.h> | ||
#include <unistd.h> | ||
|
||
#include <cstdlib> | ||
#include <mutex> | ||
#include <thread> | ||
|
||
#include "logger/common.h" | ||
|
||
namespace tll::logger { | ||
|
||
struct Header | ||
{ | ||
uint16_t level = TLL_LOGGER_DEBUG; | ||
tll::logger::Logger * logger = nullptr; | ||
tll::time_point timestamp; | ||
}; | ||
|
||
struct Thread | ||
{ | ||
std::mutex _lock; | ||
std::shared_ptr<tll::Ring> _ring; | ||
int _fd = -1; | ||
bool _stop = false; | ||
std::thread _thread; | ||
|
||
~Thread() | ||
{ | ||
stop(); | ||
|
||
if (_thread.joinable()) | ||
_thread.join(); | ||
_thread = {}; | ||
|
||
if (_fd != -1) | ||
close(_fd); | ||
_fd = -1; | ||
} | ||
|
||
int init(size_t size) | ||
{ | ||
_fd = eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK | EFD_CLOEXEC); | ||
if (_fd == -1) | ||
return EINVAL; | ||
_ring.reset(tll::Ring::allocate(size).release()); | ||
if (!_ring) | ||
return EINVAL; | ||
|
||
_thread = std::thread([](Thread * self) { self->run(); }, this); | ||
return 0; | ||
} | ||
|
||
void stop() | ||
{ | ||
_stop = true; | ||
eventfd_write(_fd, 1); | ||
} | ||
|
||
void run() | ||
{ | ||
std::shared_ptr<Ring> ring = _ring; | ||
pollfd pfd = { .fd = _fd, .events = POLLIN }; | ||
while (!_stop || !ring->empty()) { | ||
auto r = poll(&pfd, 1, 1000); | ||
if (r == 1) | ||
step(); | ||
else if (r < 0) | ||
return; | ||
else if (_stop) | ||
return; | ||
} | ||
} | ||
|
||
void step() | ||
{ | ||
const void * data; | ||
size_t size; | ||
if (_ring->read(&data, &size)) | ||
return; | ||
|
||
eventfd_t v; | ||
eventfd_read(_fd, &v); | ||
|
||
if (size < sizeof(Header)) | ||
return; | ||
|
||
auto header = (const Header *) data; | ||
|
||
std::string_view body((const char *) (header + 1), size - sizeof(Header)); | ||
|
||
{ | ||
std::unique_lock<std::mutex> lck(header->logger->lock); | ||
header->logger->impl->log(header->timestamp, (tll_logger_level_t) header->level, body); | ||
} | ||
header->logger->unref(); | ||
_ring->shift(); | ||
} | ||
|
||
int push(Logger * log, tll::time_point ts, tll_logger_level_t level, std::string_view body) | ||
{ | ||
std::unique_lock<std::mutex> lock(_lock); | ||
void * data; | ||
if (_ring->write_begin(&data, sizeof(Header) + body.size())) { | ||
_lock.unlock(); | ||
return log->impl->log(ts, level, body); | ||
} | ||
auto header = (Header *) data; | ||
header->logger = log->ref(); | ||
header->timestamp = ts; | ||
header->level = level; | ||
memcpy(header + 1, body.data(), body.size()); | ||
_ring->write_end(data, sizeof(Header) + body.size()); | ||
eventfd_write(_fd, 1); | ||
return 0; | ||
} | ||
}; | ||
|
||
} // namespace tll::logger | ||
|
||
#endif//_LOGGER_THREAD_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters