Repository: envoyproxy/envoy
File: source/extensions/filters/http/stateful_session/stateful_session.h (C/C++)

Code before:
  bool strict_{false};
  std::string stat_prefix_override_{};
};
using StatefulSessionConfigSharedPtr = std::shared_ptr<StatefulSessionConfig>;

class PerRouteStatefulSession : public Router::RouteSpecificFilterConfig {
public:
  PerRouteStatefulSession(const PerRouteProtoConfig& config,
                          Server::Configuration::GenericFactoryContext& context);

  bool disabled() const { return disabled_; }
  StatefulSessionConfig* statefulSessionConfig() const { return config_.get(); }

private:
  bool disabled_{};
  StatefulSessionConfigSharedPtr config_;
};
using PerRouteStatefulSessionConfigSharedPtr = std::shared_ptr<PerRouteStatefulSession>;

class StatefulSession : public Http::PassThroughFilter,
                        public Logger::Loggable<Logger::Id::filter> {
public:
  StatefulSession(StatefulSessionConfigSharedPtr config, Stats::Scope& scope,
                  const std::string& hcm_prefix)
      : config_(std::move(config)), scope_(scope), hcm_prefix_(hcm_prefix),
        stats_(generateStats(hcm_prefix_, config_->statPrefixOverride(), scope_)) {}

  // Http::StreamDecoderFilter
  Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap& headers, bool) override;

  // Http::StreamEncoderFilter
  Http::FilterHeadersStatus encodeHeaders(Http::ResponseHeaderMap& headers, bool) override;

  // Http::StreamFilterBase
  Http::LocalErrorStatus onLocalReply(const Http::StreamFilterBase::LocalReplyData&) override {
    // For strict mode, if an override was attempted and a local reply was sent (e.g., 503),
    // consider this a failed-closed selection.
    if (override_attempted_ && config_->isStrict() && !accounted_) {
      markFailedClosed();
      accounted_ = true;
    }
    return Http::LocalErrorStatus::Continue;
  }

  Http::SessionStatePtr& sessionStateForTest() { return session_state_; }

private:
  StatefulSessionFilterStats generateStats(const std::string& prefix,
                                           const std::string& filter_stats_prefix,
                                           Stats::Scope& scope) {
    const std::string final_prefix = absl::StrCat(prefix, "stateful_session.", filter_stats_prefix);

Review comment (performance):
I think the stats should be part of the `StatefulSessionConfig` rather then part of the filter instance to avoid we construct it from the scope again and again. It's inefficient.

Code after:
  Http::SessionStateFactorySharedPtr factory_;
  bool strict_{false};
  std::shared_ptr<StatefulSessionFilterStats> stats_;
};
using StatefulSessionConfigSharedPtr = std::shared_ptr<StatefulSessionConfig>;

class PerRouteStatefulSession : public Router::RouteSpecificFilterConfig {
public:
  PerRouteStatefulSession(const PerRouteProtoConfig& config,
                          Server::Configuration::GenericFactoryContext& context);

  bool disabled() const { return disabled_; }
  StatefulSessionConfig* statefulSessionConfig() const { return config_.get(); }

private:
  bool disabled_{};
  StatefulSessionConfigSharedPtr config_;
};
using PerRouteStatefulSessionConfigSharedPtr = std::shared_ptr<PerRouteStatefulSession>;

class StatefulSession : public Http::PassThroughFilter,
                        public Logger::Loggable<Logger::Id::filter> {
public:
  StatefulSession(StatefulSessionConfigSharedPtr config) : config_(std::move(config)) {}

  // Http::StreamDecoderFilter
  Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap& headers, bool) override;

  // Http::StreamEncoderFilter
  Http::FilterHeadersStatus encodeHeaders(Http::ResponseHeaderMap& headers, bool) override;

  Http::SessionStatePtr& sessionStateForTest() { return session_state_; }

private:
  void markRouted() {
    if (auto stats = effective_config_->stats(); stats.has_value()) {
      stats->routed_.inc();
    }
  }
  void markFailedClosed() {
    if (auto stats = effective_config_->stats(); stats.has_value()) {
      stats->failed_closed_.inc();
    }
  }
  void markFailedOpen() {
    if (auto stats = effective_config_->stats(); stats.has_value()) {
      stats->failed_open_.inc();
    }
  }

  Http::SessionStatePtr session_state_;