userver: userver/error_injection/hook.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
hook.hpp
1#pragma once
2
3#include <userver/engine/deadline.hpp>
4#include <userver/engine/sleep.hpp>
5#include <userver/error_injection/settings.hpp>
6#include <userver/logging/log.hpp>
7#include <userver/tracing/span.hpp>
8
9USERVER_NAMESPACE_BEGIN
10
11/// Artificial errors injection framework
12namespace error_injection {
13
14/// Single operation error injection process. Create on the stack,
15/// call PreHook(), do operation, call PostHook().
16class Hook final {
17 public:
18 explicit Hook(const Settings& settings, engine::Deadline deadline);
19
20 /// Must be called just before actual operation. May sleep for some time,
21 /// throw an exception, or do nothing.
22 /// @throws TimeoutException in case of artificial timeout
23 /// @throws ErrorException in case of artificial error
24 template <typename TimeoutException, typename ErrorException>
25 void PreHook() {
26 if (verdict_ == Verdict::Skip) {
27 // fast path
28 return;
29 }
30
31 switch (verdict_) {
32 case Verdict::Error:
33 LOG_ERROR() << "Error injection hook triggered verdict: error";
34 throw ErrorException{"error injection"};
35
37 LOG_ERROR() << "Error injection hook triggered verdict: timeout";
38 {
39 auto scope_time = tracing::Span::CurrentSpan().CreateScopeTime(
40 "error_injection_timeout");
41 engine::InterruptibleSleepUntil(deadline_);
42 }
43 throw TimeoutException{"error injection"};
44
47 case Verdict::Skip:
48 // pass
49 ;
50 }
51 }
52
53 /// Must be called just after operation. May sleep for some time,
54 /// or do nothing.
55 void PostHook() {
56 if (verdict_ == Verdict::Skip) {
57 // fast path
58 return;
59 }
60
61 engine::Deadline deadline = CalcPostHookDeadline();
62 if (deadline.IsReached()) return;
63
64 LOG_ERROR()
65 << "Error injection hook triggered verdict: max-delay / random-delay";
66 auto scope_time =
67 tracing::Span::CurrentSpan().CreateScopeTime("error_injection_delay");
68 engine::InterruptibleSleepUntil(deadline);
69 }
70
71 private:
72 engine::Deadline CalcPostHookDeadline();
73
74 static Verdict ReturnVerdict(const Settings& settings);
75
76 const Verdict verdict_;
77 const engine::Deadline deadline_;
78};
79
80} // namespace error_injection
81
82USERVER_NAMESPACE_END