aboutsummaryrefslogtreecommitdiffstats
path: root/extras/vom/vom/logger.hpp
blob: 6d2e3dd82f68ef0caa5feba676f6efa8117b670b (plain)
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
 * Copyright (c) 2017 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __VOM_LOGGER_H__
#define __VOM_LOGGER_H__

#include <fstream>
#include <iostream>
#include <sstream>

#include "vom/enum_base.hpp"

namespace VOM {
struct log_level_t : enum_base<log_level_t>
{
  const static log_level_t CRITICAL;
  const static log_level_t ERROR;
  const static log_level_t WARNING;
  const static log_level_t INFO;
  const static log_level_t DEBUG;

private:
  /**
   * Private constructor taking the value and the string name
   */
  log_level_t(int v, const std::string& s);

  /*
   * not allowed to construct
   */
  log_level_t() = delete;
};

/**
 * Ideally we'd use the boost logger but that is not prevelent
 * in many distros. So something simple here instead.
 */
class log_t
{
public:
  /**
   *
   */
  class handler
  {
  public:
    /**
   * Default Constructor
   */
    handler() = default;

    /**
     * Default Destructor
     */
    virtual ~handler() = default;

    /**
     * Handle a log message
     */
    virtual void handle_message(const std::string& file,
                                const int line,
                                const std::string& function,
                                const log_level_t& level,
                                const std::string& message) = 0;
  };

  /**
   * Construct a logger
   */
  log_t(handler* h);
  log_t();

  /**
   * The configured level
   */
  const log_level_t& level() const;

  /**
   * set the logging level
   */
  void set(const log_level_t& level);

  /**
   * set a file to receive the logging data
   */
  void set(handler* h);

  /**
   * An entry in the log
   */
  class entry
  {
  public:
    entry(const char* file,
          const char* function,
          int line,
          const log_level_t& level);
    ~entry();

    std::stringstream& stream();

  private:
    const std::string m_file;
    const std::string m_function;
    const log_level_t m_level;
    const int m_line;

    std::stringstream m_stream;
  };
  /**
   * Register a log handler to receive the log output
   */
  void register_handler(handler& h);

private:
  void write(const std::string& file,
             const int line,
             const std::string& function,
             const log_level_t& level,
             const std::string& message);

  /**
   * the configured logging level
   */
  log_level_t m_level;

  /**
   * Pointer to a registered handler. Null if no handler registerd
   */
  handler* m_handler;
};

class file_handler : public log_t::handler
{
public:
  file_handler(const std::string& ofile);
  ~file_handler();

  virtual void handle_message(const std::string& file,
                              const int line,
                              const std::string& function,
                              const log_level_t& level,
                              const std::string& message);

private:
  /**
   * Opened file for debugging
   */
  std::ofstream m_file_stream;
};

class cout_handler : public log_t::handler
{
public:
  cout_handler() = default;
  ~cout_handler() = default;
  virtual void handle_message(const std::string& file,
                              const int line,
                              const std::string& function,
                              const log_level_t& level,
                              const std::string& message);
};

/**
 * Return a log object into which VPP objects can write
 */
log_t& logger();

#define VOM_LOG(lvl)                                                           \
  if (lvl >= logger().level())                                                 \
  log_t::entry(__FILE__, __FUNCTION__, __LINE__, lvl).stream()
};

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "mozilla")
 * End:
 */

#endif