| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- //
- // file_logger.cxx
- // logging
- //
- // Created by Sam Jaffe on 4/1/19.
- //
- #include <fstream>
- #include "expect/expect.hpp"
- #include "resource_factory/prototype_factory.hpp"
- #include "logger/detail/appender.h"
- #include "logger/detail/layout.h"
- #include "logger/log_manager.h"
- #include "logger/properties.h"
- using namespace logging;
- struct buffer : std::filebuf {
- buffer(properties const & props);
- buffer * setbuf(char* data, std::streamsize n);
- };
- class file_appender : public simple_appender {
- public:
- static std::shared_ptr<appender> create(properties const & props);
-
- explicit file_appender(properties const & props);
-
- std::ostream & stream() override { return out_; }
- void write(logpacket const & packet, layout & withLayout) override;
- private:
- bool flush_immediately_;
- buffer rdbuf_;
- std::ostream out_;
- std::unique_ptr<char[]> buffer_;
- };
- using namespace logging::property;
- properties const DEFAULT_FILE_APPENDER{_obj({
- {"immediateFlush", _v(true)},
- {"threshold", _v("ERROR")},
- {"filename", {}}, // Will throw if accessed
- {"fileAppend", _v(true)},
- {"bufferedIO", _v(false)},
- {"bufferSize", _v(8192)}
- })};
- std::shared_ptr<appender> file_appender::create(properties const & props) {
- properties const actual = DEFAULT_FILE_APPENDER.mergedWith(props);
- return std::make_shared<file_appender>(actual);
- }
- static std::ios_base::openmode mode(bool append) {
- return append ? std::ios_base::app : std::ios_base::out;
- }
- buffer::buffer(properties const & props) : std::filebuf() {
- if (open(props["filename"], mode(props["fileAppend"])) == nullptr) {
- throw std::runtime_error("Cannot open file");
- }
- }
- buffer * buffer::setbuf(char* data, std::streamsize n) {
- std::filebuf::setbuf(data, n);
- return this;
- }
- file_appender::file_appender(properties const & props)
- : simple_appender(props),
- flush_immediately_(props["immediateFlush"]),
- rdbuf_(props), out_(&rdbuf_) {
- if (props["bufferedIO"]) {
- int const size = props["bufferSize"];
- buffer_.reset(new char[size]);
- rdbuf_.setbuf(buffer_.get(), size);
- }
- }
- void file_appender::write(logpacket const & packet, layout & withLayout) {
- withLayout.format(out_, packet);
- if (flush_immediately_) { flush(); }
- }
- namespace {
- bool _ = appenders::instance().bind("File", file_appender::create);
- }
|