1//
2// Copyright(c) 2015 Gabi Melman.
3// Distributed under the MIT License (http://opensource.org/licenses/MIT)
4//
5
6/* -*- MODE: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
7/*
8 *     Copyright 2017 Couchbase, Inc
9 *
10 *   Licensed under the Apache License, Version 2.0 (the "License");
11 *   you may not use this file except in compliance with the License.
12 *   You may obtain a copy of the License at
13 *
14 *       http://www.apache.org/licenses/LICENSE-2.0
15 *
16 *   Unless required by applicable law or agreed to in writing, software
17 *   distributed under the License is distributed on an "AS IS" BASIS,
18 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 *   See the License for the specific language governing permissions and
20 *   limitations under the License.
21 */
22
23#pragma once
24
25#include <spdlog/sinks/base_sink.h>
26
27namespace spdlog {
28namespace details {
29class file_helper;
30} // namespace details
31} // namespace spdlog
32
33/**
34 * Customised version of spdlog's rotating_file_sink with the following
35 * modifications:
36 *
37 * 1 Adds open and closing tags in the file so that a concatenated version
38 *   of all of the log files may be split back into its fragments again
39 *
40 * 2 Instead of renaming all of the files every time we're rotating to
41 *   the next file we start a new log file with a higher number
42 *
43 * TODO: If updating spdlog from v1.1.0, check if this class also needs
44 *       updating.
45 */
46template <class Mutex>
47class custom_rotating_file_sink : public spdlog::sinks::base_sink<Mutex> {
48public:
49    custom_rotating_file_sink(const spdlog::filename_t& base_filename,
50                              std::size_t max_size,
51                              const std::string& log_pattern);
52
53    ~custom_rotating_file_sink() override;
54
55protected:
56    void sink_it_(const spdlog::details::log_msg& msg) override;
57    void flush_() override;
58
59private:
60    void addHook(const std::string& hook);
61    // Calculate the full filename to use the next time
62    spdlog::filename_t calc_filename();
63
64    const spdlog::filename_t _base_filename;
65    const std::size_t _max_size;
66    std::size_t _current_size;
67    std::unique_ptr<spdlog::details::file_helper> _file_helper;
68    std::unique_ptr<spdlog::pattern_formatter> formatter;
69    unsigned long _next_file_id;
70
71    const std::string openingLogfile{"---------- Opening logfile: "};
72    const std::string closingLogfile{"---------- Closing logfile"};
73};
74
75using custom_rotating_file_sink_mt = custom_rotating_file_sink<std::mutex>;
76using custom_rotating_file_sink_st =
77        custom_rotating_file_sink<spdlog::details::null_mutex>;
78