Skip to content
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
2 changes: 2 additions & 0 deletions src/envoy/mixer/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ envoy_cc_library(
"http_filter.cc",
"mixer_control.cc",
"mixer_control.h",
"stats.cc",
"stats.h",
"tcp_filter.cc",
"utils.cc",
"utils.h",
Expand Down
22 changes: 15 additions & 7 deletions src/envoy/mixer/http_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@
#include "src/envoy/mixer/config.h"
#include "src/envoy/mixer/grpc_transport.h"
#include "src/envoy/mixer/mixer_control.h"
#include "src/envoy/mixer/stats.h"
#include "src/envoy/mixer/utils.h"

#include <map>
#include <mutex>
#include <thread>

using ::google::protobuf::util::Status;
using ::istio::mixer_client::Statistics;
using HttpCheckData = ::istio::mixer_control::http::CheckData;
using HttpHeaderUpdate = ::istio::mixer_control::http::HeaderUpdate;
using HttpReportData = ::istio::mixer_control::http::ReportData;
Expand All @@ -60,6 +62,9 @@ const LowerCaseString kIstioAttributeHeader("x-istio-attributes");
// Referer header
const LowerCaseString kRefererHeaderKey("referer");

// Envoy stats perfix for HTTP filter stats.
const std::string kHttpStatsPrefix("http_mixer_filter.");

// Set of headers excluded from request.headers attribute.
const std::set<std::string> RequestHeaderExclusives = {
kIstioAttributeHeader.get(),
Expand All @@ -86,20 +91,23 @@ class Config : public Logger::Loggable<Logger::Id::http> {
Upstream::ClusterManager& cm_;
HttpMixerConfig mixer_config_;
ThreadLocal::SlotPtr tls_;
MixerFilterStats stats_;

public:
Config(const Json::Object& config,
Server::Configuration::FactoryContext& context)
: cm_(context.clusterManager()),
tls_(context.threadLocal().allocateSlot()) {
tls_(context.threadLocal().allocateSlot()),
stats_{ALL_MIXER_FILTER_STATS(
POOL_COUNTER_PREFIX(context.scope(), kHttpStatsPrefix))} {
mixer_config_.Load(config);
Runtime::RandomGenerator& random = context.random();
tls_->set(
[this, &random](Event::Dispatcher& dispatcher)
-> ThreadLocal::ThreadLocalObjectSharedPtr {
return ThreadLocal::ThreadLocalObjectSharedPtr(
new HttpMixerControl(mixer_config_, cm_, dispatcher, random));
});
tls_->set([this, &random](Event::Dispatcher& dispatcher)
-> ThreadLocal::ThreadLocalObjectSharedPtr {
return ThreadLocal::ThreadLocalObjectSharedPtr(
new HttpMixerControl(mixer_config_, cm_, dispatcher,
random, stats_));
});
}

HttpMixerControl& mixer_control() {
Expand Down
32 changes: 28 additions & 4 deletions src/envoy/mixer/mixer_control.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

#include "src/envoy/mixer/mixer_control.h"

using ::istio::mixer_client::Statistics;

namespace Envoy {
namespace Http {
namespace Mixer {
Expand Down Expand Up @@ -66,8 +68,19 @@ void CreateEnvironment(Upstream::ClusterManager& cm,
HttpMixerControl::HttpMixerControl(const HttpMixerConfig& mixer_config,
Upstream::ClusterManager& cm,
Event::Dispatcher& dispatcher,
Runtime::RandomGenerator& random)
: config_(mixer_config), cm_(cm) {
Runtime::RandomGenerator& random,
MixerFilterStats& stats)
: config_(mixer_config),
cm_(cm),
stats_obj_(dispatcher, stats,
mixer_config.http_config.transport().stats_update_interval(),
[this](Statistics* stat) -> bool {
if (!controller_) {
return false;
}
controller_->GetStatistics(stat);
return true;
}) {
::istio::mixer_control::http::Controller::Options options(
mixer_config.http_config);

Expand All @@ -80,8 +93,19 @@ HttpMixerControl::HttpMixerControl(const HttpMixerConfig& mixer_config,
TcpMixerControl::TcpMixerControl(const TcpMixerConfig& mixer_config,
Upstream::ClusterManager& cm,
Event::Dispatcher& dispatcher,
Runtime::RandomGenerator& random)
: config_(mixer_config), dispatcher_(dispatcher) {
Runtime::RandomGenerator& random,
MixerFilterStats& stats)
: config_(mixer_config),
dispatcher_(dispatcher),
stats_obj_(dispatcher, stats,
mixer_config.tcp_config.transport().stats_update_interval(),
[this](Statistics* stat) -> bool {
if (!controller_) {
return false;
}
controller_->GetStatistics(stat);
return true;
}) {
::istio::mixer_control::tcp::Controller::Options options(
mixer_config.tcp_config);

Expand Down
9 changes: 7 additions & 2 deletions src/envoy/mixer/mixer_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "envoy/upstream/cluster_manager.h"
#include "src/envoy/mixer/config.h"
#include "src/envoy/mixer/grpc_transport.h"
#include "src/envoy/mixer/stats.h"

namespace Envoy {
namespace Http {
Expand All @@ -33,7 +34,7 @@ class HttpMixerControl final : public ThreadLocal::ThreadLocalObject {
// The constructor.
HttpMixerControl(const HttpMixerConfig& mixer_config,
Upstream::ClusterManager& cm, Event::Dispatcher& dispatcher,
Runtime::RandomGenerator& random);
Runtime::RandomGenerator& random, MixerFilterStats& stats);

::istio::mixer_control::http::Controller* controller() {
return controller_.get();
Expand All @@ -50,14 +51,16 @@ class HttpMixerControl final : public ThreadLocal::ThreadLocalObject {
Upstream::ClusterManager& cm_;
// The mixer control
std::unique_ptr<::istio::mixer_control::http::Controller> controller_;

MixerStatsObject stats_obj_;
};

class TcpMixerControl final : public ThreadLocal::ThreadLocalObject {
public:
// The constructor.
TcpMixerControl(const TcpMixerConfig& mixer_config,
Upstream::ClusterManager& cm, Event::Dispatcher& dispatcher,
Runtime::RandomGenerator& random);
Runtime::RandomGenerator& random, MixerFilterStats& stats);

::istio::mixer_control::tcp::Controller* controller() {
return controller_.get();
Expand All @@ -79,6 +82,8 @@ class TcpMixerControl final : public ThreadLocal::ThreadLocalObject {
std::chrono::milliseconds report_interval_ms_;

Event::Dispatcher& dispatcher_;

MixerStatsObject stats_obj_;
};

} // namespace Mixer
Expand Down
105 changes: 105 additions & 0 deletions src/envoy/mixer/stats.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/* Copyright 2017 Istio Authors. All Rights Reserved.
*
* Licensed 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.
*/

#include <chrono>

#include "src/envoy/mixer/stats.h"

namespace Envoy {
namespace Http {
namespace Mixer {
namespace {

// The time interval for envoy stats update.
const int kStatsUpdateIntervalInMs = 10000;

} // namespace

MixerStatsObject::MixerStatsObject(Event::Dispatcher& dispatcher,
MixerFilterStats& stats,
::google::protobuf::Duration update_interval,
GetStatsFunc func)
: stats_(stats), get_stats_func_(func) {
stats_update_interval_ =
update_interval.seconds() * 1000 + update_interval.nanos() / 1000000;
if (stats_update_interval_ <= 0) {
stats_update_interval_ = kStatsUpdateIntervalInMs;
}
memset(&old_stats_, 0, sizeof(old_stats_));

if (get_stats_func_) {
timer_ = dispatcher.createTimer([this]() { OnTimer(); });
timer_->enableTimer(std::chrono::milliseconds(stats_update_interval_));
}
}

void MixerStatsObject::OnTimer() {
::istio::mixer_client::Statistics new_stats;
bool get_stats = get_stats_func_(&new_stats);
if (get_stats) {
CheckAndUpdateStats(new_stats);
}
timer_->enableTimer(std::chrono::milliseconds(stats_update_interval_));
}

void MixerStatsObject::CheckAndUpdateStats(
const ::istio::mixer_client::Statistics& new_stats) {
if (new_stats.total_check_calls > old_stats_.total_check_calls) {
stats_.total_check_calls_.add(new_stats.total_check_calls -
old_stats_.total_check_calls);
}
if (new_stats.total_remote_check_calls >
old_stats_.total_remote_check_calls) {
stats_.total_remote_check_calls_.add(new_stats.total_remote_check_calls -
old_stats_.total_remote_check_calls);
}
if (new_stats.total_blocking_remote_check_calls >
old_stats_.total_blocking_remote_check_calls) {
stats_.total_blocking_remote_check_calls_.add(
new_stats.total_blocking_remote_check_calls -
old_stats_.total_blocking_remote_check_calls);
}
if (new_stats.total_quota_calls > old_stats_.total_quota_calls) {
stats_.total_quota_calls_.add(new_stats.total_quota_calls -
old_stats_.total_quota_calls);
}
if (new_stats.total_remote_quota_calls >
old_stats_.total_remote_quota_calls) {
stats_.total_remote_quota_calls_.add(new_stats.total_remote_quota_calls -
old_stats_.total_remote_quota_calls);
}
if (new_stats.total_blocking_remote_quota_calls >
old_stats_.total_blocking_remote_quota_calls) {
stats_.total_blocking_remote_quota_calls_.add(
new_stats.total_blocking_remote_quota_calls -
old_stats_.total_blocking_remote_quota_calls);
}
if (new_stats.total_report_calls > old_stats_.total_report_calls) {
stats_.total_report_calls_.add(new_stats.total_report_calls -
old_stats_.total_report_calls);
}
if (new_stats.total_remote_report_calls >
old_stats_.total_remote_report_calls) {
stats_.total_remote_report_calls_.add(new_stats.total_remote_report_calls -
old_stats_.total_remote_report_calls);
}

// Copy new_stats to old_stats_ for next stats update.
old_stats_ = new_stats;
}

} // namespace Mixer
} // namespace Http
} // namespace Envoy
87 changes: 87 additions & 0 deletions src/envoy/mixer/stats.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/* Copyright 2017 Istio Authors. All Rights Reserved.
*
* Licensed 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.
*/

#pragma once

#include "envoy/event/dispatcher.h"
#include "envoy/event/timer.h"
#include "envoy/stats/stats_macros.h"
#include "include/client.h"

namespace Envoy {
namespace Http {
namespace Mixer {

/**
* All mixer filter stats. @see stats_macros.h
*/
// clang-format off
#define ALL_MIXER_FILTER_STATS(COUNTER) \
COUNTER(total_check_calls) \
COUNTER(total_remote_check_calls) \
COUNTER(total_blocking_remote_check_calls) \
COUNTER(total_quota_calls) \
COUNTER(total_remote_quota_calls) \
COUNTER(total_blocking_remote_quota_calls) \
COUNTER(total_report_calls) \
COUNTER(total_remote_report_calls)
// clang-format on

/**
* Struct definition for all mixer filter stats. @see stats_macros.h
*/
struct MixerFilterStats {
ALL_MIXER_FILTER_STATS(GENERATE_COUNTER_STRUCT)
};

typedef std::function<bool(::istio::mixer_client::Statistics* s)> GetStatsFunc;

// MixerStatsObject maintains statistics for number of check, quota and report
// calls issued by a mixer filter.
class MixerStatsObject {
public:
MixerStatsObject(Event::Dispatcher& dispatcher, MixerFilterStats& stats,
::google::protobuf::Duration update_interval,
GetStatsFunc func);

private:
// This function is invoked when timer event fires.
void OnTimer();

// Compares old stats with new stats and updates envoy stats.
void CheckAndUpdateStats(const ::istio::mixer_client::Statistics& new_stats);

// A set of Envoy stats for the number of check, quota and report calls.
MixerFilterStats& stats_;
// Stores a function which gets statistics from mixer controller.
GetStatsFunc get_stats_func_;

// stats from last call to get_stats_func_. This is needed to calculate the
// variances of stats and update envoy stats.
::istio::mixer_client::Statistics old_stats_;

// These members are used for creating a timer which update Envoy stats
// periodically.
::Envoy::Event::TimerPtr timer_;

// Time interval at which Envoy stats get updated. If stats update interval
// from config is larger than 0, then store configured interval here.
// Otherwise, set interval to 10 seconds.
int stats_update_interval_;
};

} // namespace Mixer
} // namespace Http
} // namespace Envoy
Loading