Skip to content
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

Merged
merged 6 commits into from
Jul 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions api/envoy/config/resource_monitor/fixed_heap/v2alpha/BUILD
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
Copy link
Member

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?).

Copy link
Contributor Author

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.

Copy link
Member

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.

// is defined as (current heap size)/max_heap_size_bytes.
uint64 max_heap_size_bytes = 1;
}
17 changes: 17 additions & 0 deletions include/envoy/server/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Copy link
Member

Choose a reason for hiding this comment

The 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",
],
)
52 changes: 52 additions & 0 deletions include/envoy/server/resource_monitor.h
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;
Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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
53 changes: 53 additions & 0 deletions include/envoy/server/resource_monitor_config.h
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;
Copy link
Member

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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
7 changes: 7 additions & 0 deletions source/common/memory/stats.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ uint64_t Stats::totalCurrentlyReserved() {
return value;
}

uint64_t Stats::totalPageHeapUnmapped() {
size_t value = 0;
MallocExtension::instance()->GetNumericProperty("tcmalloc.pageheap_unmapped_bytes", &value);
return value;
}

} // namespace Memory
} // namespace Envoy

Expand All @@ -31,6 +37,7 @@ namespace Memory {

uint64_t Stats::totalCurrentlyAllocated() { return 0; }
uint64_t Stats::totalCurrentlyReserved() { return 0; }
uint64_t Stats::totalPageHeapUnmapped() { return 0; }

} // namespace Memory
} // namespace Envoy
Expand Down
5 changes: 5 additions & 0 deletions source/common/memory/stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ class Stats {
* allocated.
*/
static uint64_t totalCurrentlyReserved();

/**
* @return uint64_t the number of bytes in free, unmapped pages in the page heap.
*/
static uint64_t totalPageHeapUnmapped();
};

} // namespace Memory
Expand Down
6 changes: 6 additions & 0 deletions source/extensions/extensions_build_config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ EXTENSIONS = {
"envoy.filters.network.tcp_proxy": "//source/extensions/filters/network/tcp_proxy:config",
"envoy.filters.network.thrift_proxy": "//source/extensions/filters/network/thrift_proxy:config",

#
# Resource monitors
#

"envoy.resource_monitors.fixed_heap": "//source/extensions/resource_monitors/fixed_heap:config",

#
# Stat sinks
#
Expand Down
17 changes: 17 additions & 0 deletions source/extensions/resource_monitors/BUILD
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",
],
)
18 changes: 18 additions & 0 deletions source/extensions/resource_monitors/common/BUILD
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",
],
)
38 changes: 38 additions & 0 deletions source/extensions/resource_monitors/common/factory_base.h
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
34 changes: 34 additions & 0 deletions source/extensions/resource_monitors/fixed_heap/BUILD
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",
],
)
30 changes: 30 additions & 0 deletions source/extensions/resource_monitors/fixed_heap/config.cc
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
30 changes: 30 additions & 0 deletions source/extensions/resource_monitors/fixed_heap/config.h
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
Loading