]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/base/CodeContext.h
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS code_contexts for details.
9 #ifndef SQUID_SRC_BASE_CODECONTEXT_H
10 #define SQUID_SRC_BASE_CODECONTEXT_H
12 #include "base/InstanceId.h"
13 #include "base/RefCount.h"
14 #include "base/Stopwatch.h"
20 * Most error-reporting code cannot know what transaction or task Squid was
21 * working on when the error occurred. For example, when Squid HTTP request
22 * parser discovers a malformed header field, the parser can report the field
23 * contents, but that information is often useless for the admin without
24 * processing context details like which client sent the request or what the
25 * requested URL was. Moreover, even when the error reporting code does have
26 * access to some context details, it cannot separate important facts from noise
27 * because such classification is usually deployment-specific (i.e. cannot be
28 * hard-coded) and requires human expertise. The situation is aggravated by a
29 * busy Squid instance constantly switching from one processing context to
32 * To solve these problems, Squid assigns a CodeContext object to a processing
33 * context. When Squid switches to another processing context, it switches the
34 * current CodeContext object as well. When Squid prints a level-0 or level-1
35 * message to cache.log, it asks the current CodeContext object (if any) to
36 * report context details, allowing the admin to correlate the cache.log message
37 * with an access.log record.
39 * Squid also reports processing context changes to cache.log when Squid
40 * level-5+ debugging is enabled.
42 * CodeContext is being retrofitted into existing code with lots of places that
43 * switch processing context. Identifying and adjusting all those places takes
44 * time. Until then, there will be incorrect and missing context attributions.
49 /// Interface for reporting what Squid code is working on.
50 /// Such reports are usually requested outside creator's call stack.
51 /// They are especially useful for attributing low-level errors to transactions.
52 class CodeContext
: public RefCountable
55 typedef RefCount
<CodeContext
> Pointer
;
57 /// \returns the known global context or, to indicate unknown context, nil
58 static const Pointer
&Current();
60 /// forgets the current context, setting it to nil/unknown
63 /// changes the current context; nil argument sets it to nil/unknown
64 static void Reset(const Pointer
);
66 ~CodeContext() override
{}
68 /// \returns a small, permanent ID of the current context
69 /// gists persist forever and are suitable for passing to other SMP workers
70 virtual ScopedId
codeContextGist() const = 0;
72 /// appends human-friendly context description line(s) to a cache.log record
73 virtual std::ostream
&detailCodeContext(std::ostream
&os
) const = 0;
75 /// time spent in this context (see also: %busy_time)
79 static void ForgetCurrent();
80 static void Entering(const Pointer
&codeCtx
);
81 static void Leaving();
84 /// by default, only small context gist is printed
86 std::ostream
&operator <<(std::ostream
&os
, const CodeContext
&ctx
)
88 return os
<< ctx
.codeContextGist();
91 /* convenience context-reporting wrappers that also reduce linking problems */
92 std::ostream
&CurrentCodeContextBrief(std::ostream
&os
);
93 std::ostream
&CurrentCodeContextDetail(std::ostream
&os
);
95 /// Convenience class that automatically restores the current/outer CodeContext
96 /// when leaving the scope of the new-context following/inner code. \see Run().
97 class CodeContextGuard
100 CodeContextGuard(const CodeContext::Pointer
&newContext
): savedCodeContext(CodeContext::Current()) { CodeContext::Reset(newContext
); }
101 ~CodeContextGuard() { CodeContext::Reset(savedCodeContext
); }
103 // no copying of any kind (for simplicity and to prevent accidental copies)
104 CodeContextGuard(CodeContextGuard
&&) = delete;
106 CodeContext::Pointer savedCodeContext
;
109 /// A helper that calls the given function in the given call context. If the
110 /// function throws, the call context is preserved, so that the exception is
111 /// associated with the context that triggered it.
112 template <typename Fun
>
114 CallAndRestore_(const CodeContext::Pointer
&context
, Fun
&&fun
)
116 const auto savedCodeContext(CodeContext::Current());
117 CodeContext::Reset(context
);
119 CodeContext::Reset(savedCodeContext
);
122 /// Service code running in its own service context should use this function.
123 /// \sa CallAndRestore_()
124 template <typename Fun
>
126 CallBack(const CodeContext::Pointer
&callbackContext
, Fun
&&callback
)
128 // TODO: Consider catching exceptions and letting CodeContext handle them.
129 CallAndRestore_(callbackContext
, callback
);
132 /// To supply error-reporting code with parsing context X (where the error
133 /// occurred), parsing code should use this function when initiating parsing
134 /// inside that context X.
135 /// \sa CallAndRestore_()
136 template <typename Fun
>
138 CallParser(const CodeContext::Pointer
&parsingContext
, Fun
&&parse
)
140 CallAndRestore_(parsingContext
, parse
);
143 /// Executes `service` in `serviceContext` but due to automatic caller context
144 /// restoration, service exceptions are associated with the caller that suffered
145 /// from (and/or caused) them (rather than with the service itself).
147 /// Service code running in caller's context should use this function to escape
148 /// into service context (e.g., for submitting caller-agnostic requests).
149 template <typename Fun
>
151 CallService(const CodeContext::Pointer
&serviceContext
, Fun
&&service
)
153 // TODO: Consider catching exceptions and letting CodeContext handle them.
154 CodeContextGuard
guard(serviceContext
);
158 /// Executes context `creator` in the service context. If an exception occurs,
159 /// the creator context is preserved, so that the exception is associated with
160 /// the creator that triggered them (rather than with the service).
162 /// Service code running in its own context should use this function to create
163 /// new code contexts. TODO: Use or, if this pattern is not repeated, remove.
164 template <typename Fun
>
166 CallContextCreator(Fun
&&creator
)
168 const auto savedCodeContext(CodeContext::Current());
170 CodeContext::Reset(savedCodeContext
);
175 #endif /* SQUID_SRC_BASE_CODECONTEXT_H */