1
#pragma once
2

            
3
#include <string>
4

            
5
#include "envoy/common/optref.h"
6
#include "envoy/common/pure.h"
7
#include "envoy/stats/scope.h"
8
#include "envoy/stats/stats.h"
9

            
10
#include "source/common/common/assert.h"
11
#include "source/common/stats/symbol_table.h"
12

            
13
namespace Envoy {
14
namespace Server {
15

            
16
class ProactiveResourceMonitor {
17
public:
18
14
  ProactiveResourceMonitor() = default;
19
14
  virtual ~ProactiveResourceMonitor() = default;
20
  /**
21
   * Tries to allocate resource for given resource monitor in thread safe manner.
22
   * Returns true if there is enough resource quota available and allocation has succeeded, false
23
   * otherwise.
24
   * @param increment to add to current resource usage value and compare against configured max
25
   * threshold.
26
   */
27
  virtual bool tryAllocateResource(int64_t increment) PURE;
28
  /**
29
   * Tries to deallocate resource for given resource monitor in thread safe manner.
30
   * Returns true if there is enough resource quota available and deallocation has succeeded, false
31
   * otherwise.
32
   * @param decrement to subtract from current resource usage value.
33
   */
34
  virtual bool tryDeallocateResource(int64_t decrement) PURE;
35
  /**
36
   * Returns current resource usage (most recent read) tracked by monitor.
37
   */
38
  virtual int64_t currentResourceUsage() const PURE;
39
  /**
40
   * Returns max resource usage configured in monitor.
41
   */
42
  virtual int64_t maxResourceUsage() const PURE;
43
};
44

            
45
using ProactiveResourceMonitorPtr = std::unique_ptr<ProactiveResourceMonitor>;
46
using ProactiveResourceMonitorOptRef = OptRef<ProactiveResourceMonitor>;
47

            
48
class ProactiveResource {
49
public:
50
  ProactiveResource(const std::string& name, ProactiveResourceMonitorPtr monitor,
51
                    Stats::Scope& stats_scope)
52
7
      : name_(name), monitor_(std::move(monitor)),
53
7
        failed_updates_counter_(makeCounter(stats_scope, name, "failed_updates")),
54
7
        pressure_gauge_(makeGauge(stats_scope, name, "pressure")) {}
55

            
56
16
  bool tryAllocateResource(int64_t increment) {
57
16
    if (monitor_->tryAllocateResource(increment)) {
58
13
      return true;
59
13
    } else {
60
3
      failed_updates_counter_.inc();
61
3
      return false;
62
3
    }
63
16
  }
64

            
65
19
  bool tryDeallocateResource(int64_t decrement) {
66
19
    if (monitor_->tryDeallocateResource(decrement)) {
67
13
      return true;
68
13
    } else {
69
6
      failed_updates_counter_.inc();
70
6
      return false;
71
6
    }
72
19
  }
73

            
74
4
  double updateResourcePressure() {
75
4
    const double pressure = static_cast<double>(monitor_->currentResourceUsage()) /
76
4
                            static_cast<double>(monitor_->maxResourceUsage());
77
4
    pressure_gauge_.set(pressure * 100);
78
4
    return pressure;
79
4
  }
80

            
81
3
  ProactiveResourceMonitorOptRef getProactiveResourceMonitorForTest() {
82
3
    return makeOptRefFromPtr<ProactiveResourceMonitor>(monitor_.get());
83
3
  };
84

            
85
private:
86
  const std::string name_;
87
  ProactiveResourceMonitorPtr monitor_;
88
  Stats::Counter& failed_updates_counter_;
89
  Stats::Gauge& pressure_gauge_;
90

            
91
  Stats::StatNameManagedStorage makeName(Stats::Scope& scope, absl::string_view a,
92
14
                                         absl::string_view b) {
93
14
    return {absl::StrCat("overload.", a, ".", b), scope.symbolTable()};
94
14
  }
95

            
96
7
  Stats::Counter& makeCounter(Stats::Scope& scope, absl::string_view a, absl::string_view b) {
97
7
    auto stat_name = makeName(scope, a, b);
98
7
    return scope.counterFromStatName(stat_name.statName());
99
7
  }
100

            
101
7
  Stats::Gauge& makeGauge(Stats::Scope& scope, absl::string_view a, absl::string_view b) {
102
7
    auto stat_name = makeName(scope, a, b);
103
7
    return scope.gaugeFromStatName(stat_name.statName(), Stats::Gauge::ImportMode::NeverImport);
104
7
  }
105
};
106

            
107
} // namespace Server
108
} // namespace Envoy