summaryrefslogtreecommitdiffstats
path: root/src/common/logging/backend.h
blob: 11edbf1b6a763ef723cea06e556f9bcb7afd6de7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

#include <chrono>
#include <memory>
#include <string>
#include <string_view>
#include "common/file_util.h"
#include "common/logging/filter.h"
#include "common/logging/log.h"

namespace Log {

class Filter;

/**
 * A log entry. Log entries are store in a structured format to permit more varied output
 * formatting on different frontends, as well as facilitating filtering and aggregation.
 */
struct Entry {
    std::chrono::microseconds timestamp;
    Class log_class;
    Level log_level;
    std::string filename;
    unsigned int line_num;
    std::string function;
    std::string message;

    Entry() = default;
    Entry(Entry&& o) = default;

    Entry& operator=(Entry&& o) = default;
    Entry& operator=(const Entry& o) = default;
};

/**
 * Interface for logging backends. As loggers can be created and removed at runtime, this can be
 * used by a frontend for adding a custom logging backend as needed
 */
class Backend {
public:
    virtual ~Backend() = default;
    virtual void SetFilter(const Filter& new_filter) {
        filter = new_filter;
    }
    virtual const char* GetName() const = 0;
    virtual void Write(const Entry& entry) = 0;

private:
    Filter filter;
};

/**
 * Backend that writes to stderr without any color commands
 */
class ConsoleBackend : public Backend {
public:
    static const char* Name() {
        return "console";
    }
    const char* GetName() const override {
        return Name();
    }
    void Write(const Entry& entry) override;
};

/**
 * Backend that writes to stderr and with color
 */
class ColorConsoleBackend : public Backend {
public:
    static const char* Name() {
        return "color_console";
    }

    const char* GetName() const override {
        return Name();
    }
    void Write(const Entry& entry) override;
};

/**
 * Backend that writes to a file passed into the constructor
 */
class FileBackend : public Backend {
public:
    explicit FileBackend(const std::string& filename);

    static const char* Name() {
        return "file";
    }

    const char* GetName() const override {
        return Name();
    }

    void Write(const Entry& entry) override;

private:
    FileUtil::IOFile file;
    std::size_t bytes_written;
};

void AddBackend(std::unique_ptr<Backend> backend);

void RemoveBackend(std::string_view backend_name);

Backend* GetBackend(std::string_view backend_name);

/**
 * Returns the name of the passed log class as a C-string. Subclasses are separated by periods
 * instead of underscores as in the enumeration.
 */
const char* GetLogClassName(Class log_class);

/**
 * Returns the name of the passed log level as a C-string.
 */
const char* GetLevelName(Level log_level);

/// Creates a log entry by formatting the given source location, and message.
Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
                  const char* function, std::string message);

/**
 * The global filter will prevent any messages from even being processed if they are filtered. Each
 * backend can have a filter, but if the level is lower than the global filter, the backend will
 * never get the message
 */
void SetGlobalFilter(const Filter& filter);
} // namespace Log