Lightweight 0.20261105.1
Loading...
Searching...
No Matches
SqlLogger.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include "Api.hpp"
6#include "SqlDataBinder.hpp"
7#include "SqlError.hpp"
8
9#include <functional>
10#include <source_location>
11#include <string_view>
12
13namespace Lightweight
14{
15
16class SqlConnection;
17
18struct SqlVariant;
19
20/// @ingroup CoreApi
21/// Represents a logger for SQL operations.
23{
24 public:
25 /// Mandates the support for logging bind operations.
26 enum class SupportBindLogging : uint8_t
27 {
28 No,
29 Yes
30 };
31
32 LIGHTWEIGHT_API SqlLogger();
33 /// Default copy constructor.
34 LIGHTWEIGHT_API SqlLogger(SqlLogger const& /*other*/) = default;
35 /// Default move constructor.
36 LIGHTWEIGHT_API SqlLogger(SqlLogger&& /*other*/) = default;
37 /// Default copy assignment operator.
38 LIGHTWEIGHT_API SqlLogger& operator=(SqlLogger const& /*other*/) = default;
39 /// Default move assignment operator.
40 LIGHTWEIGHT_API SqlLogger& operator=(SqlLogger&& /*other*/) = default;
41 LIGHTWEIGHT_API virtual ~SqlLogger() = default;
42
43 /// Type definition for a function that writes messages.
44 using MessageWriter = std::function<void(std::string /*message*/)>;
45
46 /// Constructs a new logger.
47 ///
48 /// @param supportBindLogging Indicates if the logger should support bind logging.
49 /// @param writer Optional message writer function for log output.
50 LIGHTWEIGHT_API explicit SqlLogger(SupportBindLogging supportBindLogging, MessageWriter writer = {});
51
52 /// Sets the logging sink for the logger.
53 ///
54 /// @param writer A function that takes a message string and writes it to the desired output.
55 LIGHTWEIGHT_API void SetLoggingSink(MessageWriter writer = {});
56
57 /// Invoked on a warning.
58 virtual void OnWarning(std::string_view const& message) = 0;
59
60 /// Invoked on ODBC SQL error occurred.
61 virtual void OnError(SqlError errorCode, std::source_location sourceLocation = std::source_location::current()) = 0;
62
63 /// Invoked an ODBC SQL error occurred, with extended error information.
64 virtual void OnError(SqlErrorInfo const& errorInfo,
65 std::source_location sourceLocation = std::source_location::current()) = 0;
66
67 /// Invoked when a scoped code region needs to be timed and logged. The region starts with this call.
68 virtual void OnScopedTimerStart(std::string const& tag) = 0;
69
70 /// Invoked when a scoped code region needs to be timed and logged. The region ends with this call.
71 virtual void OnScopedTimerStop(std::string const& tag) = 0;
72
73 /// Invoked when a connection is opened.
74 virtual void OnConnectionOpened(SqlConnection const& connection) = 0;
75
76 /// Invoked when a connection is closed.
77 virtual void OnConnectionClosed(SqlConnection const& connection) = 0;
78
79 /// Invoked when a connection is idle.
80 virtual void OnConnectionIdle(SqlConnection const& connection) = 0;
81
82 /// Invoked when a connection is reused.
83 virtual void OnConnectionReuse(SqlConnection const& connection) = 0;
84
85 /// Invoked when a direct query is executed.
86 virtual void OnExecuteDirect(std::string_view const& query) = 0;
87
88 /// Invoked when a query is prepared.
89 virtual void OnPrepare(std::string_view const& query) = 0;
90
91 /// Invoked when an input parameter is bound.
92 template <typename T>
93 void OnBindInputParameter(std::string_view const& name, T&& value)
94 {
95 if (_supportsBindLogging)
96 {
97 using value_type = std::remove_cvref_t<T>;
98 if constexpr (SqlDataBinderSupportsInspect<value_type>)
99 {
100 OnBind(name, std::string(SqlDataBinder<value_type>::Inspect(std::forward<T>(value))));
101 }
102 }
103 }
104
105 /// Invoked when an input parameter is bound, by name.
106 virtual void OnBind(std::string_view const& name, std::string value) = 0;
107
108 /// Invoked when a prepared query is executed.
109 virtual void OnExecute(std::string_view const& query) = 0;
110
111 /// Invoked when a batch of queries is executed
112 virtual void OnExecuteBatch() = 0;
113
114 /// Invoked when a row is fetched.
115 virtual void OnFetchRow() = 0;
116
117 /// @brief Invoked once per block-prefetch round-trip (one @c SQLFetchScroll that materialized a
118 /// whole row block on the transparent prefetch path), with the number of rows the block yielded.
119 ///
120 /// Non-pure with an empty default so existing loggers need no change; override to observe how many
121 /// network round-trips a query actually cost (N rows at depth D collapse to @c ceil(N/D) blocks).
122 /// The argument is the number of rows materialized by this block fetch (0 at end of result set).
123 virtual void OnFetchBlock(std::size_t /*rowsInBlock*/) {}
124
125 /// Invoked when fetching is done.
126 virtual void OnFetchEnd() = 0;
127
128 /// @brief Invoked when an operation on a statement failed, naming that statement's own query.
129 ///
130 /// Non-pure so existing loggers need no change: the default forwards to @ref OnError. Unlike a query
131 /// remembered from @ref OnPrepare or @ref OnExecute, which may belong to any statement of the process,
132 /// @p query is the one the failure belongs to.
133 ///
134 /// @param errorInfo The diagnostics of the failure.
135 /// @param query The statement's prepared query; empty if it has none, as after a direct execution.
136 /// @param sourceLocation Where the failure was reported from.
137 virtual void OnStatementError(SqlErrorInfo const& errorInfo,
138 [[maybe_unused]] std::string_view query,
139 std::source_location sourceLocation)
140 {
141 OnError(errorInfo, sourceLocation);
142 }
143
144 /// @brief Invoked when a prepared query is executed as one native row-wise batch.
145 ///
146 /// Non-pure so existing loggers need no change: the default forwards to @ref OnExecuteBatch.
147 ///
148 /// @param query The query being executed.
149 virtual void OnExecuteNativeBatch([[maybe_unused]] std::string_view query)
150 {
152 }
153
154 class Null;
155
156 /// Retrieves a null logger that does nothing.
157 LIGHTWEIGHT_API static Null& NullLogger() noexcept;
158
159 /// Retrieves a logger that logs to standard output.
160 LIGHTWEIGHT_API static SqlLogger& StandardLogger();
161
162 /// Retrieves a logger that logs to the trace logger.
163 LIGHTWEIGHT_API static SqlLogger& TraceLogger();
164
165 /// Retrieves the currently configured logger.
166 LIGHTWEIGHT_API static SqlLogger& GetLogger();
167
168 /// Sets the current logger.
169 ///
170 /// The ownership of the logger is not transferred and remains with the caller. Statements and
171 /// connections report to the current logger when they are destroyed, which for those owned by
172 /// statics (such as the migration manager's) happens during static destruction. A logger installed
173 /// here must therefore outlive them, or be replaced (e.g. by @ref NullLogger) before it is destroyed.
174 /// The built-in loggers are never destroyed.
175 LIGHTWEIGHT_API static void SetLogger(SqlLogger& logger);
176
177 protected:
178 /// The function used to write log messages.
179 MessageWriter _messageWriter; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
180
181 private:
182 bool _supportsBindLogging = false;
183};
184
185class SqlLogger::Null: public SqlLogger
186{
187 public:
188 void OnWarning(std::string_view const& /*message*/) override {}
189 void OnError(SqlError /*errorCode*/, std::source_location /*sourceLocation*/) override {}
190 void OnError(SqlErrorInfo const& /*errorInfo*/, std::source_location /*sourceLocation*/) override {}
191 void OnScopedTimerStart(std::string const& /*tag*/) override {}
192 void OnScopedTimerStop(std::string const& /*tag*/) override {}
193 void OnConnectionOpened(SqlConnection const& /*connection*/) override {}
194 void OnConnectionClosed(SqlConnection const& /*connection*/) override {}
195 void OnConnectionIdle(SqlConnection const& /*connection*/) override {}
196 void OnConnectionReuse(SqlConnection const& /*connection*/) override {}
197 void OnExecuteDirect(std::string_view const& /*query*/) override {}
198 void OnPrepare(std::string_view const& /*qurey*/) override {}
199 void OnBind(std::string_view const& /*name*/, std::string /*value*/) override {}
200 void OnExecute(std::string_view const& /*query*/) override {}
201 void OnExecuteBatch() override {}
202 void OnFetchRow() override {}
203 void OnFetchEnd() override {}
204};
205
206/// A scoped timer for logging.
207///
208/// This class is used to measure the time spent in a code region and log it.
209/// This is typically useful for performance analysis, to identify bottlenecks.
210///
211/// @see SqlLogger
213{
214 public:
215 /// Default copy constructor.
218 /// Default copy assignment operator.
220 SqlScopedTimeLogger& operator=(SqlScopedTimeLogger&&) = delete;
221 /// Constructs a scoped time logger with the given tag.
222 explicit SqlScopedTimeLogger(std::string tag):
223 _tag { std::move(tag) }
224 {
225 SqlLogger::GetLogger().OnScopedTimerStart(_tag);
226 }
227
229 {
230 SqlLogger::GetLogger().OnScopedTimerStop(_tag);
231 }
232
233 private:
234 std::string _tag;
235};
236
237} // namespace Lightweight
Represents a connection to a SQL database.
MessageWriter _messageWriter
The function used to write log messages.
virtual void OnExecuteDirect(std::string_view const &query)=0
Invoked when a direct query is executed.
virtual void OnExecute(std::string_view const &query)=0
Invoked when a prepared query is executed.
virtual void OnError(SqlError errorCode, std::source_location sourceLocation=std::source_location::current())=0
Invoked on ODBC SQL error occurred.
static LIGHTWEIGHT_API Null & NullLogger() noexcept
Retrieves a null logger that does nothing.
static LIGHTWEIGHT_API SqlLogger & GetLogger()
Retrieves the currently configured logger.
LIGHTWEIGHT_API SqlLogger(SqlLogger const &)=default
Default copy constructor.
virtual void OnFetchEnd()=0
Invoked when fetching is done.
LIGHTWEIGHT_API SqlLogger & operator=(SqlLogger &&)=default
Default move assignment operator.
static LIGHTWEIGHT_API SqlLogger & TraceLogger()
Retrieves a logger that logs to the trace logger.
static LIGHTWEIGHT_API void SetLogger(SqlLogger &logger)
virtual void OnError(SqlErrorInfo const &errorInfo, std::source_location sourceLocation=std::source_location::current())=0
Invoked an ODBC SQL error occurred, with extended error information.
LIGHTWEIGHT_API void SetLoggingSink(MessageWriter writer={})
virtual void OnBind(std::string_view const &name, std::string value)=0
Invoked when an input parameter is bound, by name.
virtual void OnConnectionReuse(SqlConnection const &connection)=0
Invoked when a connection is reused.
virtual void OnStatementError(SqlErrorInfo const &errorInfo, std::string_view query, std::source_location sourceLocation)
Invoked when an operation on a statement failed, naming that statement's own query.
static LIGHTWEIGHT_API SqlLogger & StandardLogger()
Retrieves a logger that logs to standard output.
virtual void OnPrepare(std::string_view const &query)=0
Invoked when a query is prepared.
virtual void OnExecuteBatch()=0
Invoked when a batch of queries is executed.
void OnBindInputParameter(std::string_view const &name, T &&value)
Invoked when an input parameter is bound.
Definition SqlLogger.hpp:93
LIGHTWEIGHT_API SqlLogger(SqlLogger &&)=default
Default move constructor.
std::function< void(std::string)> MessageWriter
Type definition for a function that writes messages.
Definition SqlLogger.hpp:44
virtual void OnConnectionClosed(SqlConnection const &connection)=0
Invoked when a connection is closed.
virtual void OnFetchBlock(std::size_t)
Invoked once per block-prefetch round-trip (one SQLFetchScroll that materialized a whole row block on...
SupportBindLogging
Mandates the support for logging bind operations.
Definition SqlLogger.hpp:27
virtual void OnScopedTimerStart(std::string const &tag)=0
Invoked when a scoped code region needs to be timed and logged. The region starts with this call.
virtual void OnConnectionIdle(SqlConnection const &connection)=0
Invoked when a connection is idle.
virtual void OnScopedTimerStop(std::string const &tag)=0
Invoked when a scoped code region needs to be timed and logged. The region ends with this call.
virtual void OnWarning(std::string_view const &message)=0
Invoked on a warning.
LIGHTWEIGHT_API SqlLogger & operator=(SqlLogger const &)=default
Default copy assignment operator.
virtual void OnFetchRow()=0
Invoked when a row is fetched.
virtual void OnConnectionOpened(SqlConnection const &connection)=0
Invoked when a connection is opened.
virtual void OnExecuteNativeBatch(std::string_view query)
Invoked when a prepared query is executed as one native row-wise batch.
LIGHTWEIGHT_API SqlLogger(SupportBindLogging supportBindLogging, MessageWriter writer={})
SqlScopedTimeLogger & operator=(SqlScopedTimeLogger const &)=default
Default copy assignment operator.
SqlScopedTimeLogger(std::string tag)
Constructs a scoped time logger with the given tag.
SqlScopedTimeLogger(SqlScopedTimeLogger const &)=default
Default copy constructor.
Represents an ODBC SQL error.
Definition SqlError.hpp:32