StripeKit 0.1.1
Stripe integration toolkit for C++
Loading...
Searching...
No Matches
Logging.h
1/** Logging.h
2 *
3 * System for StripeKit logging..
4 *
5 * @author Hans de Ruiter
6 *
7 * @license See LICENSE.md for details.
8 */
9
10#pragma once
11
12#include <optional>
13#include <string>
14#include <string_view>
15
16namespace stripekit {
17
18/**
19 * @addtogroup logging
20 * @{
21 */
22
23/**
24 * Severity of a log entry.
25 */
26enum class LogLevel {
27 Trace, /**< Very detailed tracing. Noisy. */
28 Debug, /**< Diagnostic detail useful while developing. */
29 Info, /**< Normal, noteworthy activity. */
30 Warn, /**< Something unexpected that did not stop the operation. */
31 Error, /**< An operation failed. */
32 Off /**< Nothing at all. Use as a threshold to silence logging. */
33};
34
35/**
36 * Extra identifiers attached to a log entry.
37 *
38 * These are the fields worth searching on when tracing a payment through
39 * Stripe's dashboard and the application's own logs. A logger that supports
40 * structured output should emit them as separate fields.
41 *
42 * Fields that do not apply are left empty.
43 */
44struct LogContext {
45 /** Stripe request id for an outbound call, of the form "req_...". */
46 std::string request_id;
47
48 /** Stripe event id for webhook work, of the form "evt_...". */
49 std::string event_id;
50
51 /** Stripe event type, for example "invoice.paid". */
52 std::string webhook_type;
53
54 /** Which attempt this is, for operations that are retried. */
55 std::optional<int> retry_attempt;
56
57 /** Name of the adapter that produced the entry. */
58 std::string adapter_name;
59};
60
61/**
62 * Receives StripeKit's log entries.
63 *
64 * Implement this to route StripeKit's diagnostics into the application's own
65 * log. Adapters usually provide one already, such as
66 * stripekit::drogon::LogBridge.
67 *
68 * Entries may be written from any thread, so implementations must be
69 * thread-safe. They must not throw, and must never write the API key or the
70 * webhook signing secret; redact_sensitive_text() helps with the latter.
71 *
72 * @sa @ref writing_an_adapter
73 */
74class Logger {
75public:
76 /**
77 * Destroys the logger instance.
78 */
79 virtual ~Logger() = default;
80
81 /**
82 * Reports whether entries at this level are wanted.
83 *
84 * StripeKit checks this before building a message, so answering honestly
85 * avoids formatting work for entries that would be thrown away.
86 *
87 * @param level Severity being considered.
88 * @return True when an entry at that level would be written.
89 */
90 virtual bool should_log(LogLevel level) const = 0;
91
92 /**
93 * Writes one entry.
94 *
95 * @param level Severity of the entry.
96 * @param message The text to record.
97 * @param context Identifiers to attach. Fields that do not apply are empty.
98 */
99 virtual void
100 log(LogLevel level, std::string_view message, const LogContext& context = LogContext{}) = 0;
101};
102
103/**
104 * A logger that discards everything.
105 *
106 * Use it where a Logger is required but no output is wanted.
107 */
108class NullLogger final : public Logger {
109public:
110 /**
111 * Reports whether entries at this level are wanted.
112 *
113 * @param level Ignored.
114 * @return Always false.
115 */
116 bool should_log(LogLevel level) const override;
117
118 /**
119 * Discards the entry.
120 *
121 * @param level Ignored.
122 * @param message Ignored.
123 * @param context Ignored.
124 */
125 void log(LogLevel level, std::string_view message, const LogContext& context) override;
126};
127
128/**
129 * A logger that writes to the process's standard error stream.
130 *
131 * Convenient for command-line tools and getting started. Applications with
132 * their own logging should implement Logger, or use their adapter's bridge.
133 */
134class ConsoleLogger final : public Logger {
135public:
136 /**
137 * Creates a console logger.
138 *
139 * @param threshold Lowest severity to write. Entries below it are dropped.
140 */
141 explicit ConsoleLogger(LogLevel threshold = LogLevel::Info);
142
143 /**
144 * Reports whether entries at this level are wanted.
145 *
146 * @param level Severity being considered.
147 * @return True when it is at or above the configured threshold.
148 */
149 bool should_log(LogLevel level) const override;
150
151 /**
152 * Writes one formatted line.
153 *
154 * @param level Severity of the entry.
155 * @param message The text to record.
156 * @param context Identifiers to include in the line.
157 */
158 void log(LogLevel level, std::string_view message, const LogContext& context) override;
159
160private:
161 LogLevel threshold_level;
162};
163
164/**
165 * Reports whether a field is one whose value should never be logged.
166 *
167 * Recognises the names Stripe uses for keys, secrets, and card details.
168 *
169 * @param field_name Name of the field being considered.
170 * @return True when the value should be replaced before logging.
171 */
172bool is_sensitive_field_name(std::string_view field_name);
173
174/**
175 * Replaces a secret value with a placeholder.
176 *
177 * @param value The value to hide.
178 * @return A placeholder that shows something was present without revealing it.
179 */
180std::string redact_sensitive_value(std::string_view value);
181
182/**
183 * Strips secret-looking tokens out of free-form text.
184 *
185 * Catches API keys and signing secrets by their recognisable prefixes, which
186 * makes it useful for sanitising an error message or a response body before
187 * writing it to a log.
188 *
189 * @param text The text to sanitise.
190 * @return The text with recognised secrets replaced by placeholders.
191 */
192std::string redact_sensitive_text(std::string_view text);
193
194/** @} */
195
196} // namespace stripekit
bool should_log(LogLevel level) const override
Reports whether entries at this level are wanted.
void log(LogLevel level, std::string_view message, const LogContext &context) override
Writes one formatted line.
ConsoleLogger(LogLevel threshold=LogLevel::Info)
Creates a console logger.
Receives StripeKit's log entries.
Definition Logging.h:74
virtual void log(LogLevel level, std::string_view message, const LogContext &context=LogContext{})=0
Writes one entry.
virtual ~Logger()=default
Destroys the logger instance.
virtual bool should_log(LogLevel level) const =0
Reports whether entries at this level are wanted.
A logger that discards everything.
Definition Logging.h:108
bool should_log(LogLevel level) const override
Reports whether entries at this level are wanted.
void log(LogLevel level, std::string_view message, const LogContext &context) override
Discards the entry.
std::string redact_sensitive_value(std::string_view value)
Replaces a secret value with a placeholder.
bool is_sensitive_field_name(std::string_view field_name)
Reports whether a field is one whose value should never be logged.
LogLevel
Severity of a log entry.
Definition Logging.h:26
std::string redact_sensitive_text(std::string_view text)
Strips secret-looking tokens out of free-form text.
@ Info
Normal, noteworthy activity.
Definition Logging.h:29
@ Warn
Something unexpected that did not stop the operation.
Definition Logging.h:30
@ Error
An operation failed.
Definition Logging.h:31
@ Debug
Diagnostic detail useful while developing.
Definition Logging.h:28
@ Off
Nothing at all.
Definition Logging.h:32
@ Trace
Very detailed tracing.
Definition Logging.h:27
Async.h.
Definition Async.h:20
Extra identifiers attached to a log entry.
Definition Logging.h:44
std::string request_id
Stripe request id for an outbound call, of the form "req_...".
Definition Logging.h:46
std::string adapter_name
Name of the adapter that produced the entry.
Definition Logging.h:58
std::optional< int > retry_attempt
Which attempt this is, for operations that are retried.
Definition Logging.h:55
std::string event_id
Stripe event id for webhook work, of the form "evt_...".
Definition Logging.h:49
std::string webhook_type
Stripe event type, for example "invoice.paid".
Definition Logging.h:52