blob: 02b2ce1619c87296ee8c90f6363e77d070dd598d [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __SLAVE_MONITOR_HPP__
#define __SLAVE_MONITOR_HPP__
#include <map>
#include <string>
#include <boost/circular_buffer.hpp>
#include <mesos/mesos.hpp>
#include <process/future.hpp>
#include <process/limiter.hpp>
#include <process/statistics.hpp>
#include <stout/cache.hpp>
#include <stout/duration.hpp>
#include <stout/hashmap.hpp>
#include <stout/nothing.hpp>
#include <stout/option.hpp>
#include <stout/try.hpp>
#include "common/type_utils.hpp"
namespace mesos {
namespace internal {
namespace slave {
// Forward declarations.
class Containerizer;
class ResourceMonitorProcess;
const extern Duration MONITORING_TIME_SERIES_WINDOW;
const extern size_t MONITORING_TIME_SERIES_CAPACITY;
// Number of time series to maintain for completed executors.
const extern size_t MONITORING_ARCHIVED_TIME_SERIES;
// Provides resource monitoring for containers. Resource usage time
// series are stored using the Statistics module. Usage information
// is also exported via a JSON endpoint.
// TODO(bmahler): Forward usage information to the master.
// TODO(bmahler): Consider pulling out the resource collection into
// a Collector abstraction. The monitor can then become a true
// monitoring abstraction, allowing isolators to subscribe
// to resource usage events. (e.g. get a future for the executor
// hitting 75% memory consumption, the future would become ready
// when this occurs, and the isolator can discard the future
// when no longer interested).
class ResourceMonitor
{
public:
explicit ResourceMonitor(Containerizer* containerizer);
~ResourceMonitor();
// Starts monitoring resources for the given container.
// Returns a failure if the container is already being watched.
process::Future<Nothing> start(
const ContainerID& containerId,
const ExecutorInfo& executorInfo,
const Duration& interval);
// Stops monitoring resources for the given container.
// Returns a failure if the container is unknown to the monitor.
process::Future<Nothing> stop(
const ContainerID& containerId);
private:
ResourceMonitorProcess* process;
};
class ResourceMonitorProcess : public process::Process<ResourceMonitorProcess>
{
public:
explicit ResourceMonitorProcess(Containerizer* _containerizer)
: ProcessBase("monitor"),
containerizer(_containerizer),
limiter(2, Seconds(1)), // 2 permits per second.
archive(MONITORING_ARCHIVED_TIME_SERIES) {}
virtual ~ResourceMonitorProcess() {}
process::Future<Nothing> start(
const ContainerID& containerId,
const ExecutorInfo& executorInfo,
const Duration& interval);
process::Future<Nothing> stop(
const ContainerID& containerId);
protected:
virtual void initialize()
{
route("/statistics.json",
STATISTICS_HELP,
&ResourceMonitorProcess::statistics);
// TODO(bmahler): Add a archive.json endpoint that exposes
// historical information, once we have path parameters for
// routes.
}
private:
void collect(
const ContainerID& containerId,
const Duration& interval);
void _collect(
const process::Future<ResourceStatistics>& statistics,
const ContainerID& containerId,
const Duration& interval);
// This is a convenience struct for bundling usage information.
struct Usage
{
ContainerID containerId;
ExecutorInfo executorInfo;
process::Future<ResourceStatistics> statistics;
};
// Helper for returning the usage for a particular executor.
Usage usage(
const ContainerID& containerId,
const ExecutorInfo& executorInfo);
// HTTP Endpoints.
// Returns the monitoring statistics. Requests have no parameters.
process::Future<process::http::Response> statistics(
const process::http::Request& request);
process::Future<process::http::Response> _statistics(
const process::http::Request& request);
process::Future<process::http::Response> __statistics(
const std::list<Usage>& usages,
const process::http::Request& request);
static const std::string STATISTICS_HELP;
Containerizer* containerizer;
// Used to rate limit the statistics.json endpoint.
process::RateLimiter limiter;
// Monitoring information for an executor.
struct MonitoringInfo {
// boost::circular_buffer needs a default constructor.
MonitoringInfo() {}
MonitoringInfo(const ExecutorInfo& _executorInfo,
const Duration& window,
size_t capacity)
: executorInfo(_executorInfo), statistics(window, capacity) {}
ExecutorInfo executorInfo; // Non-const for assignability.
process::TimeSeries<ResourceStatistics> statistics;
};
// The monitoring info is stored for each monitored container.
hashmap<ContainerID, MonitoringInfo> monitored;
// Fixed-size history of monitoring information.
boost::circular_buffer<MonitoringInfo> archive;
};
} // namespace slave {
} // namespace internal {
} // namespace mesos {
#endif // __SLAVE_MONITOR_HPP__