1
#pragma once
2

            
3
#include <memory>
4

            
5
#include "envoy/server/lifecycle_notifier.h"
6
#include "envoy/stats/scope.h"
7
#include "envoy/stats/stats.h"
8
#include "envoy/upstream/cluster_manager.h"
9

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

            
13
namespace Envoy {
14
namespace Extensions {
15
namespace Common {
16
namespace Wasm {
17

            
18
// The custom stat namespace which prepends all the user-defined metrics.
19
// Note that the prefix is removed from the final output of /stats endpoints.
20
constexpr absl::string_view CustomStatNamespace = "wasmcustom";
21

            
22
#define CREATE_WASM_STATS(COUNTER, GAUGE)                                                          \
23
345
  COUNTER(remote_load_cache_hits)                                                                  \
24
345
  COUNTER(remote_load_cache_negative_hits)                                                         \
25
345
  COUNTER(remote_load_cache_misses)                                                                \
26
345
  COUNTER(remote_load_fetch_successes)                                                             \
27
345
  COUNTER(remote_load_fetch_failures)                                                              \
28
345
  GAUGE(remote_load_cache_entries, NeverImport)
29

            
30
struct CreateWasmStats {
31
  CREATE_WASM_STATS(GENERATE_COUNTER_STRUCT, GENERATE_GAUGE_STRUCT)
32
};
33

            
34
#define LIFECYCLE_STATS(COUNTER, GAUGE)                                                            \
35
388
  COUNTER(created)                                                                                 \
36
388
  GAUGE(active, NeverImport)
37

            
38
struct LifecycleStats {
39
  LIFECYCLE_STATS(GENERATE_COUNTER_STRUCT, GENERATE_GAUGE_STRUCT)
40
};
41

            
42
using ScopeWeakPtr = std::weak_ptr<Stats::Scope>;
43

            
44
enum class WasmEvent : int {
45
  Ok,
46
  RemoteLoadCacheHit,
47
  RemoteLoadCacheNegativeHit,
48
  RemoteLoadCacheMiss,
49
  RemoteLoadCacheFetchSuccess,
50
  RemoteLoadCacheFetchFailure,
51
  UnableToCreateVm,
52
  UnableToCloneVm,
53
  MissingFunction,
54
  UnableToInitializeCode,
55
  StartFailed,
56
  ConfigureFailed,
57
  RuntimeError,
58
  VmCreated,
59
  VmShutDown,
60
  VmReloadBackoff,
61
  VmReloadSuccess,
62
  VmReloadFailure,
63
};
64

            
65
class CreateStatsHandler : Logger::Loggable<Logger::Id::wasm> {
66
public:
67
91
  CreateStatsHandler() = default;
68
  ~CreateStatsHandler() = default;
69

            
70
  void initialize();
71

            
72
  void onEvent(WasmEvent event);
73
  void onRemoteCacheEntriesChanged(int remote_cache_entries);
74
  void createStats(const Stats::ScopeSharedPtr& scope) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
75
  void resetStats() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); // Delete stats pointers
76

            
77
  // NB: the Scope can become invalid if, for example, the owning FilterChain is deleted. When that
78
  // happens the stats must be recreated. This hook verifies the Scope of any existing stats and if
79
  // necessary recreates the stats with the newly provided scope.
80
  // This call takes out the mutex_ and calls createStats and possibly resetStats().
81
  Stats::ScopeSharedPtr lockAndCreateStats(const Stats::ScopeSharedPtr& scope);
82

            
83
  void resetStatsForTesting();
84

            
85
protected:
86
  absl::Mutex mutex_;
87
  ScopeWeakPtr scope_;
88
  std::unique_ptr<CreateWasmStats> create_wasm_stats_;
89
};
90

            
91
CreateStatsHandler& getCreateStatsHandler();
92

            
93
class LifecycleStatsHandler {
94
public:
95
  LifecycleStatsHandler(const Stats::ScopeSharedPtr& scope, std::string runtime)
96
388
      : lifecycle_stats_(LifecycleStats{
97
388
            LIFECYCLE_STATS(POOL_COUNTER_PREFIX(*scope, absl::StrCat("wasm.", runtime, ".")),
98
388
                            POOL_GAUGE_PREFIX(*scope, absl::StrCat("wasm.", runtime, ".")))}) {};
99
  ~LifecycleStatsHandler() = default;
100

            
101
  void onEvent(WasmEvent event);
102
  static int64_t getActiveVmCount();
103

            
104
protected:
105
  LifecycleStats lifecycle_stats_;
106
};
107

            
108
// TODO(wbpcode): refactor all these stats handlers into a single one.
109
#define WASM_STATS(COUNTER)                                                                        \
110
139
  COUNTER(vm_reload)                                                                               \
111
139
  COUNTER(vm_reload_backoff)                                                                       \
112
139
  COUNTER(vm_reload_success)                                                                       \
113
139
  COUNTER(vm_reload_failure)
114

            
115
struct WasmStats {
116
  WASM_STATS(GENERATE_COUNTER_STRUCT)
117
};
118

            
119
class StatsHandler {
120
public:
121
  StatsHandler(Stats::Scope& parent_scope, const std::string& prefix);
122
  void onEvent(WasmEvent event) const;
123
8
  WasmStats& wasmStats() const { return wasm_stats_; }
124

            
125
private:
126
  Stats::ScopeSharedPtr scope_;
127
  mutable WasmStats wasm_stats_;
128
};
129

            
130
using StatsHandlerSharedPtr = std::shared_ptr<StatsHandler>;
131

            
132
} // namespace Wasm
133
} // namespace Common
134
} // namespace Extensions
135
} // namespace Envoy