-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add resource monitor framework #3848
Changes from all commits
96cdb76
f773b5f
e5e55d2
88e18af
bb6c083
167f077
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
load("//bazel:api_build_system.bzl", "api_proto_library_internal") | ||
|
||
licenses(["notice"]) # Apache 2 | ||
|
||
api_proto_library_internal( | ||
name = "fixed_heap", | ||
srcs = ["fixed_heap.proto"], | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
syntax = "proto3"; | ||
|
||
package envoy.config.resource_monitor.fixed_heap.v2alpha; | ||
option go_package = "v2alpha"; | ||
|
||
message FixedHeapConfig { | ||
// Limit of the Envoy process heap size. This is used to calculate heap memory pressure which | ||
// is defined as (current heap size)/max_heap_size_bytes. | ||
uint64 max_heap_size_bytes = 1; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -180,3 +180,20 @@ envoy_cc_library( | |
"//source/common/protobuf", | ||
], | ||
) | ||
|
||
envoy_cc_library( | ||
name = "resource_monitor_interface", | ||
hdrs = ["resource_monitor.h"], | ||
deps = [ | ||
"//source/common/protobuf", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this dependency isn't needed (based on header analysis). |
||
], | ||
) | ||
|
||
envoy_cc_library( | ||
name = "resource_monitor_config_interface", | ||
hdrs = ["resource_monitor_config.h"], | ||
deps = [ | ||
":resource_monitor_interface", | ||
"//include/envoy/event:dispatcher_interface", | ||
], | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#pragma once | ||
|
||
#include <memory> | ||
|
||
#include "envoy/common/exception.h" | ||
#include "envoy/common/pure.h" | ||
|
||
namespace Envoy { | ||
namespace Server { | ||
|
||
// Struct for reporting usage for a particular resource. | ||
struct ResourceUsage { | ||
// Fraction of (resource usage)/(resource limit). | ||
double resource_pressure_; | ||
}; | ||
|
||
class ResourceMonitor { | ||
public: | ||
virtual ~ResourceMonitor() {} | ||
|
||
/** | ||
* Notifies caller of updated resource usage. | ||
*/ | ||
class Callbacks { | ||
public: | ||
virtual ~Callbacks() {} | ||
|
||
/** | ||
* Called when the request for updated resource usage succeeds. | ||
* @param usage the updated resource usage | ||
*/ | ||
virtual void onSuccess(const ResourceUsage& usage) PURE; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FWIW, given the size of ResourceUsage I would probably pass by value everywhere, unless you see it getting larger in the future? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We may want to add the actual usage and limit values - useful at least for reporting as stats. So it may grow a little, but probably not much. In any event, I'd expect resource usages won't be polled so frequently that passing by reference or value will make any noticeable difference. |
||
|
||
/** | ||
* Called when the request for updated resource usage fails. | ||
* @param error the exception caught when trying to get updated resource usage | ||
*/ | ||
virtual void onFailure(const EnvoyException& error) PURE; | ||
}; | ||
|
||
/** | ||
* Recalculate resource usage. | ||
* This must be non-blocking so if RPCs need to be made they should be | ||
* done asynchronously and invoke the callback when finished. | ||
*/ | ||
virtual void updateResourceUsage(Callbacks& callbacks) PURE; | ||
}; | ||
|
||
typedef std::unique_ptr<ResourceMonitor> ResourceMonitorPtr; | ||
|
||
} // namespace Server | ||
} // namespace Envoy |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#pragma once | ||
|
||
#include "envoy/common/pure.h" | ||
#include "envoy/event/dispatcher.h" | ||
#include "envoy/server/resource_monitor.h" | ||
|
||
#include "common/protobuf/protobuf.h" | ||
|
||
namespace Envoy { | ||
namespace Server { | ||
namespace Configuration { | ||
|
||
class ResourceMonitorFactoryContext { | ||
public: | ||
virtual ~ResourceMonitorFactoryContext() {} | ||
|
||
/** | ||
* @return Event::Dispatcher& the main thread's dispatcher. This dispatcher should be used | ||
* for all singleton processing. | ||
*/ | ||
virtual Event::Dispatcher& dispatcher() PURE; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would just inline this and skip the context unless you anticipate this growing significantly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
}; | ||
|
||
/** | ||
* Implemented by each resource monitor and registered via Registry::registerFactory() | ||
* or the convenience class RegistryFactory. | ||
*/ | ||
class ResourceMonitorFactory { | ||
public: | ||
virtual ~ResourceMonitorFactory() {} | ||
|
||
/** | ||
* Create a particular resource monitor implementation. | ||
* @param config const ProtoBuf::Message& supplies the config for the resource monitor | ||
* implementation. | ||
* @param context ResourceMonitorFactoryContext& supplies the resource monitor's context. | ||
* @return ResourceMonitorPtr the resource monitor instance. Should not be nullptr. | ||
* @throw EnvoyException if the implementation is unable to produce an instance with | ||
* the provided parameters. | ||
*/ | ||
virtual ResourceMonitorPtr createResourceMonitor(const Protobuf::Message& config, | ||
ResourceMonitorFactoryContext& context) PURE; | ||
|
||
/** | ||
* @return std::string the identifying name for a particular implementation of a resource | ||
* monitor produced by the factory. | ||
*/ | ||
virtual std::string name() PURE; | ||
}; | ||
|
||
} // namespace Configuration | ||
} // namespace Server | ||
} // namespace Envoy |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
licenses(["notice"]) # Apache 2 | ||
|
||
load( | ||
"//bazel:envoy_build_system.bzl", | ||
"envoy_cc_library", | ||
"envoy_package", | ||
) | ||
|
||
envoy_package() | ||
|
||
envoy_cc_library( | ||
name = "well_known_names", | ||
hdrs = ["well_known_names.h"], | ||
deps = [ | ||
"//source/common/singleton:const_singleton", | ||
], | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
licenses(["notice"]) # Apache 2 | ||
|
||
load( | ||
"//bazel:envoy_build_system.bzl", | ||
"envoy_cc_library", | ||
"envoy_package", | ||
) | ||
|
||
envoy_package() | ||
|
||
envoy_cc_library( | ||
name = "factory_base_lib", | ||
hdrs = ["factory_base.h"], | ||
deps = [ | ||
"//include/envoy/server:resource_monitor_config_interface", | ||
"//source/common/protobuf:utility_lib", | ||
], | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#pragma once | ||
|
||
#include "envoy/server/resource_monitor_config.h" | ||
|
||
#include "common/protobuf/utility.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace ResourceMonitors { | ||
namespace Common { | ||
|
||
template <class ConfigProto> | ||
class FactoryBase : public Server::Configuration::ResourceMonitorFactory { | ||
public: | ||
Server::ResourceMonitorPtr | ||
createResourceMonitor(const Protobuf::Message& config, | ||
Server::Configuration::ResourceMonitorFactoryContext& context) override { | ||
return createResourceMonitorFromProtoTyped( | ||
MessageUtil::downcastAndValidate<const ConfigProto&>(config), context); | ||
} | ||
|
||
std::string name() override { return name_; } | ||
|
||
protected: | ||
FactoryBase(const std::string& name) : name_(name) {} | ||
|
||
private: | ||
virtual Server::ResourceMonitorPtr createResourceMonitorFromProtoTyped( | ||
const ConfigProto& config, | ||
Server::Configuration::ResourceMonitorFactoryContext& context) PURE; | ||
|
||
const std::string name_; | ||
}; | ||
|
||
} // namespace Common | ||
} // namespace ResourceMonitors | ||
} // namespace Extensions | ||
} // namespace Envoy |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
licenses(["notice"]) # Apache 2 | ||
|
||
load( | ||
"//bazel:envoy_build_system.bzl", | ||
"envoy_cc_library", | ||
"envoy_package", | ||
) | ||
|
||
envoy_package() | ||
|
||
envoy_cc_library( | ||
name = "fixed_heap_monitor", | ||
srcs = ["fixed_heap_monitor.cc"], | ||
hdrs = ["fixed_heap_monitor.h"], | ||
deps = [ | ||
"//include/envoy/server:resource_monitor_config_interface", | ||
"//source/common/common:assert_lib", | ||
"//source/common/memory:stats_lib", | ||
"@envoy_api//envoy/config/resource_monitor/fixed_heap/v2alpha:fixed_heap_cc", | ||
], | ||
) | ||
|
||
envoy_cc_library( | ||
name = "config", | ||
srcs = ["config.cc"], | ||
hdrs = ["config.h"], | ||
deps = [ | ||
":fixed_heap_monitor", | ||
"//include/envoy/registry", | ||
"//source/common/common:assert_lib", | ||
"//source/extensions/resource_monitors:well_known_names", | ||
"//source/extensions/resource_monitors/common:factory_base_lib", | ||
], | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#include "extensions/resource_monitors/fixed_heap/config.h" | ||
|
||
#include "envoy/registry/registry.h" | ||
|
||
#include "common/protobuf/utility.h" | ||
|
||
#include "extensions/resource_monitors/fixed_heap/fixed_heap_monitor.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace ResourceMonitors { | ||
namespace FixedHeapMonitor { | ||
|
||
Server::ResourceMonitorPtr FixedHeapMonitorFactory::createResourceMonitorFromProtoTyped( | ||
const envoy::config::resource_monitor::fixed_heap::v2alpha::FixedHeapConfig& config, | ||
Server::Configuration::ResourceMonitorFactoryContext& /*unused_context*/) { | ||
return std::make_unique<FixedHeapMonitor>(config); | ||
} | ||
|
||
/** | ||
* Static registration for the fixed heap resource monitor factory. @see RegistryFactory. | ||
*/ | ||
static Registry::RegisterFactory<FixedHeapMonitorFactory, | ||
Server::Configuration::ResourceMonitorFactory> | ||
registered_; | ||
|
||
} // namespace FixedHeapMonitor | ||
} // namespace ResourceMonitors | ||
} // namespace Extensions | ||
} // namespace Envoy |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#pragma once | ||
|
||
#include "envoy/config/resource_monitor/fixed_heap/v2alpha/fixed_heap.pb.validate.h" | ||
#include "envoy/server/resource_monitor_config.h" | ||
|
||
#include "extensions/resource_monitors/common/factory_base.h" | ||
#include "extensions/resource_monitors/well_known_names.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace ResourceMonitors { | ||
namespace FixedHeapMonitor { | ||
|
||
class FixedHeapMonitorFactory | ||
: public Common::FactoryBase< | ||
envoy::config::resource_monitor::fixed_heap::v2alpha::FixedHeapConfig> { | ||
public: | ||
FixedHeapMonitorFactory() | ||
: FactoryBase(ResourceMonitorNames::get().FIXED_HEAP_RESOURCE_MONITOR) {} | ||
|
||
private: | ||
Server::ResourceMonitorPtr createResourceMonitorFromProtoTyped( | ||
const envoy::config::resource_monitor::fixed_heap::v2alpha::FixedHeapConfig& config, | ||
Server::Configuration::ResourceMonitorFactoryContext& context) override; | ||
}; | ||
|
||
} // namespace FixedHeapMonitor | ||
} // namespace ResourceMonitors | ||
} // namespace Extensions | ||
} // namespace Envoy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if there is a more push-button way to approach this, by having Envoy infer maximum memory available in the container? We have had some recent discussions with OpenCensus on how to do memory utilization determination and the main takeaway is its hard to do cross platform in a consistent way. OTOH, freeing users from having to make this determination seems a net win if there's some reasonable approaches (e.g. can tcmalloc tell us anything?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, I couldn't find a way to dynamically get the heap limit from tcmalloc. I expect most users will want to define their own memory monitor which knows how to query the envoy container for this info and perhaps use it in combination with this or on its own.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW I agree with @eziskind on this that it will be easier to have the operator provide the limit. How that limit is obtained/enforced is going to be system specific.