userver: userver/error_injection/hook.hpp Source File
Loading...
Searching...
No Matches
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 {
17public:
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("error_injection_timeout");
40 engine::InterruptibleSleepUntil(deadline_);
41 }
42 throw TimeoutException{"error injection"};
43
46 case Verdict::Skip:
47 // pass
48 ;
49 }
50 }
51
52 /// Must be called just after operation. May sleep for some time,
53 /// or do nothing.
54 void PostHook() {
55 if (verdict_ == Verdict::Skip) {
56 // fast path
57 return;
58 }
59
60 engine::Deadline deadline = CalcPostHookDeadline();
61 if (deadline.IsReached()) return;
62
63 LOG_ERROR() << "Error injection hook triggered verdict: max-delay / random-delay";
64 auto scope_time = tracing::Span::CurrentSpan().CreateScopeTime("error_injection_delay");
65 engine::InterruptibleSleepUntil(deadline);
66 }
67
68private:
69 engine::Deadline CalcPostHookDeadline();
70
71 static Verdict ReturnVerdict(const Settings& settings);
72
73 const Verdict verdict_;
74 const engine::Deadline deadline_;
75};
76
77} // namespace error_injection
78
79USERVER_NAMESPACE_END