summaryrefslogtreecommitdiffstats
path: root/contrib/libs/apache/arrow_next/cpp/src/arrow/util/logger.h
blob: d051d37c0347fd14482050014ca2741970465265 (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
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
#pragma clang system_header
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

#pragma once

#include <chrono>
#include <iosfwd>
#include <memory>
#include <string_view>

#include "contrib/libs/apache/arrow_next/cpp/src/arrow/result.h"
#include "contrib/libs/apache/arrow_next/cpp/src/arrow/status.h"
#include "contrib/libs/apache/arrow_next/cpp/src/arrow/util/logging.h"
#include "contrib/libs/apache/arrow_next/cpp/src/arrow/util/macros.h"
#include "contrib/libs/apache/arrow_next/cpp/src/arrow/util/visibility.h"

namespace arrow20 {
namespace util {

struct SourceLocation {
  const char* file = "";
  int line = 0;
};

struct LogDetails {
  ArrowLogLevel severity = ArrowLogLevel::ARROW_INFO;
  std::chrono::system_clock::time_point timestamp = std::chrono::system_clock::now();
  SourceLocation source_location{};
  std::string_view message = "";
};

/// \brief A base interface for custom loggers.
///
/// Loggers can be added to the LoggerRegistry for global access or directly provided to
/// certain logging utilities.
class Logger {
 public:
  virtual ~Logger() = default;

  virtual void Log(const LogDetails& details) = 0;

  virtual bool Flush(std::chrono::microseconds timeout) { return true; }
  bool Flush() { return this->Flush(std::chrono::microseconds::max()); }

  virtual bool is_enabled() const { return true; }

  virtual ArrowLogLevel severity_threshold() const { return ArrowLogLevel::ARROW_TRACE; }
};

/// \brief Creates a simple logger that redirects output to std::cerr
ARROW_EXPORT std::shared_ptr<Logger> MakeOStreamLogger(ArrowLogLevel severity_threshold);
/// \brief Creates a simple logger that redirects output to the provided ostream
ARROW_EXPORT std::shared_ptr<Logger> MakeOStreamLogger(ArrowLogLevel severity_threshold,
                                                       std::ostream& sink);

class ARROW_EXPORT LoggerRegistry {
 public:
  /// \brief Add a logger to the registry with the associated name
  ///
  /// Returns Invalid if a logger with the provided name already exists. Users should call
  /// `UnregisterLogger` first if they wish to overwrite it.
  static Status RegisterLogger(std::string_view name, std::shared_ptr<Logger> logger);

  /// \brief Remove a logger from the registry
  static void UnregisterLogger(std::string_view name);

  /// \brief Return the logger associated with the provided name
  ///
  /// If `name` is empty, the default logger is returned. If `name` doesn't match any of
  /// the registered loggers then a non-null noop logger is returned
  static std::shared_ptr<Logger> GetLogger(std::string_view name = "");

  /// \brief Return the default logger
  static std::shared_ptr<Logger> GetDefaultLogger();
  /// \brief Set the default logger
  static void SetDefaultLogger(std::shared_ptr<Logger> logger);
};

/// \brief Represents a single log record to be emitted by an underlying logger
class ARROW_EXPORT LogMessage {
 public:
  /// \brief Construct a LogMessage with the provided underlying logger
  LogMessage(ArrowLogLevel severity, std::shared_ptr<Logger> logger,
             SourceLocation source_location = {});
  /// \brief Construct a LogMessage with the provided logger name, which will be used to
  /// find an underlying logger in the registry
  LogMessage(ArrowLogLevel severity, std::string_view logger_name,
             SourceLocation source_location = {});

  std::ostream& Stream();

  // Convenience method - mainly for use in ARROW_LOG_* macros. This prevents unnecessary
  // argument evaluation when log statements are stripped in certain builds
  template <typename... Args>
  LogMessage& Append(Args&&... args) {
    if constexpr (sizeof...(Args) > 0) {
      if (CheckIsEnabled()) {
        (Stream() << ... << args);
      }
    }
    return *this;
  }

 private:
  bool CheckIsEnabled();

  class Impl;
  std::shared_ptr<Impl> impl_;
};

}  // namespace util
}  // namespace arrow20

// For the following macros, log statements with a lower severity than
// `ARROW_MINIMUM_LOG_LEVEL` will be stripped from the build
#ifndef ARROW_MINIMUM_LOG_LEVEL
#  define ARROW_MINIMUM_LOG_LEVEL -1000
#endif

#define ARROW_LOGGER_INTERNAL(LOGGER, LEVEL)                                      \
  (::arrow20::util::LogMessage(::arrow20::util::ArrowLogLevel::ARROW_##LEVEL, LOGGER, \
                             ::arrow20::util::SourceLocation{__FILE__, __LINE__}))

static_assert(static_cast<int>(::arrow20::util::ArrowLogLevel::ARROW_TRACE) == -2);
#if ARROW_MINIMUM_LOG_LEVEL <= -2
#  define ARROW_LOGGER_TRACE(LOGGER, ...) \
    (ARROW_LOGGER_INTERNAL(LOGGER, TRACE).Append(__VA_ARGS__))
#else
#  define ARROW_LOGGER_TRACE(...) ARROW_UNUSED(0)
#endif

static_assert(static_cast<int>(::arrow20::util::ArrowLogLevel::ARROW_DEBUG) == -1);
#if ARROW_MINIMUM_LOG_LEVEL <= -1
#  define ARROW_LOGGER_DEBUG(LOGGER, ...) \
    (ARROW_LOGGER_INTERNAL(LOGGER, DEBUG).Append(__VA_ARGS__))
#else
#  define ARROW_LOGGER_DEBUG(...) ARROW_UNUSED(0)
#endif

static_assert(static_cast<int>(::arrow20::util::ArrowLogLevel::ARROW_INFO) == 0);
#if ARROW_MINIMUM_LOG_LEVEL <= 0
#  define ARROW_LOGGER_INFO(LOGGER, ...) \
    (ARROW_LOGGER_INTERNAL(LOGGER, INFO).Append(__VA_ARGS__))
#else
#  define ARROW_LOGGER_INFO(...) ARROW_UNUSED(0)
#endif

static_assert(static_cast<int>(::arrow20::util::ArrowLogLevel::ARROW_WARNING) == 1);
#if ARROW_MINIMUM_LOG_LEVEL <= 1
#  define ARROW_LOGGER_WARNING(LOGGER, ...) \
    (ARROW_LOGGER_INTERNAL(LOGGER, WARNING).Append(__VA_ARGS__))
#else
#  define ARROW_LOGGER_WARNING(...) ARROW_UNUSED(0)
#endif

static_assert(static_cast<int>(::arrow20::util::ArrowLogLevel::ARROW_ERROR) == 2);
#if ARROW_MINIMUM_LOG_LEVEL <= 2
#  define ARROW_LOGGER_ERROR(LOGGER, ...) \
    (ARROW_LOGGER_INTERNAL(LOGGER, ERROR).Append(__VA_ARGS__))
#else
#  define ARROW_LOGGER_ERROR(...) ARROW_UNUSED(0)
#endif

static_assert(static_cast<int>(::arrow20::util::ArrowLogLevel::ARROW_FATAL) == 3);
#if ARROW_MINIMUM_LOG_LEVEL <= 3
#  define ARROW_LOGGER_FATAL(LOGGER, ...) \
    (ARROW_LOGGER_INTERNAL(LOGGER, FATAL).Append(__VA_ARGS__))
#else
#  define ARROW_LOGGER_FATAL(...) ARROW_UNUSED(0)
#endif

#define ARROW_LOGGER_CALL(LOGGER, LEVEL, ...) ARROW_LOGGER_##LEVEL(LOGGER, __VA_ARGS__)