// Generated by the gRPC C++ plugin.
// If you make any local change, they will be lost.
// source: dmi/hw_metrics_mgmt_service.proto
#ifndef GRPC_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto__INCLUDED
#define GRPC_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto__INCLUDED

#include "dmi/hw_metrics_mgmt_service.pb.h"

#include <grpc++/impl/codegen/async_stream.h>
#include <grpc++/impl/codegen/async_unary_call.h>
#include <grpc++/impl/codegen/method_handler_impl.h>
#include <grpc++/impl/codegen/proto_utils.h>
#include <grpc++/impl/codegen/rpc_method.h>
#include <grpc++/impl/codegen/service_type.h>
#include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/stub_options.h>
#include <grpc++/impl/codegen/sync_stream.h>

namespace grpc {
class CompletionQueue;
class Channel;
class RpcService;
class ServerCompletionQueue;
class ServerContext;
}  // namespace grpc

namespace dmi {

class NativeMetricsManagementService final {
 public:
  class StubInterface {
   public:
    virtual ~StubInterface() {}
    // List the supported metrics for the passed device.
    // This would be the first call that you make to know about the metrics that a particular device supports and
    // then use the UpdateMetricsConfiguration API to monitor only the required metrics.
    virtual ::grpc::Status ListMetrics(::grpc::ClientContext* context, const ::dmi::HardwareID& request, ::dmi::ListMetricsResponse* response) = 0;
    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::dmi::ListMetricsResponse>> AsyncListMetrics(::grpc::ClientContext* context, const ::dmi::HardwareID& request, ::grpc::CompletionQueue* cq) {
      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::dmi::ListMetricsResponse>>(AsyncListMetricsRaw(context, request, cq));
    }
    // Updates the configuration of the list of metrics in the request
    // Acts upon single metric configuration, collection of a single metric can be started/stopped
    // by changing its configuration.
    // 
    // This configuration is persisted across restart of the device or the device manager
    virtual ::grpc::Status UpdateMetricsConfiguration(::grpc::ClientContext* context, const ::dmi::MetricsConfigurationRequest& request, ::dmi::MetricsConfigurationResponse* response) = 0;
    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::dmi::MetricsConfigurationResponse>> AsyncUpdateMetricsConfiguration(::grpc::ClientContext* context, const ::dmi::MetricsConfigurationRequest& request, ::grpc::CompletionQueue* cq) {
      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::dmi::MetricsConfigurationResponse>>(AsyncUpdateMetricsConfigurationRaw(context, request, cq));
    }
    // Get the instantenous value of a metric
    virtual ::grpc::Status GetMetric(::grpc::ClientContext* context, const ::dmi::GetMetricRequest& request, ::dmi::GetMetricResponse* response) = 0;
    std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::dmi::GetMetricResponse>> AsyncGetMetric(::grpc::ClientContext* context, const ::dmi::GetMetricRequest& request, ::grpc::CompletionQueue* cq) {
      return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::dmi::GetMetricResponse>>(AsyncGetMetricRaw(context, request, cq));
    }
    // Initiate the server streaming of the metrics
    std::unique_ptr< ::grpc::ClientReaderInterface< ::dmi::Metric>> StreamMetrics(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) {
      return std::unique_ptr< ::grpc::ClientReaderInterface< ::dmi::Metric>>(StreamMetricsRaw(context, request));
    }
    std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::dmi::Metric>> AsyncStreamMetrics(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) {
      return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::dmi::Metric>>(AsyncStreamMetricsRaw(context, request, cq, tag));
    }
  private:
    virtual ::grpc::ClientAsyncResponseReaderInterface< ::dmi::ListMetricsResponse>* AsyncListMetricsRaw(::grpc::ClientContext* context, const ::dmi::HardwareID& request, ::grpc::CompletionQueue* cq) = 0;
    virtual ::grpc::ClientAsyncResponseReaderInterface< ::dmi::MetricsConfigurationResponse>* AsyncUpdateMetricsConfigurationRaw(::grpc::ClientContext* context, const ::dmi::MetricsConfigurationRequest& request, ::grpc::CompletionQueue* cq) = 0;
    virtual ::grpc::ClientAsyncResponseReaderInterface< ::dmi::GetMetricResponse>* AsyncGetMetricRaw(::grpc::ClientContext* context, const ::dmi::GetMetricRequest& request, ::grpc::CompletionQueue* cq) = 0;
    virtual ::grpc::ClientReaderInterface< ::dmi::Metric>* StreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) = 0;
    virtual ::grpc::ClientAsyncReaderInterface< ::dmi::Metric>* AsyncStreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) = 0;
  };
  class Stub final : public StubInterface {
   public:
    Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);
    ::grpc::Status ListMetrics(::grpc::ClientContext* context, const ::dmi::HardwareID& request, ::dmi::ListMetricsResponse* response) override;
    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::dmi::ListMetricsResponse>> AsyncListMetrics(::grpc::ClientContext* context, const ::dmi::HardwareID& request, ::grpc::CompletionQueue* cq) {
      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::dmi::ListMetricsResponse>>(AsyncListMetricsRaw(context, request, cq));
    }
    ::grpc::Status UpdateMetricsConfiguration(::grpc::ClientContext* context, const ::dmi::MetricsConfigurationRequest& request, ::dmi::MetricsConfigurationResponse* response) override;
    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::dmi::MetricsConfigurationResponse>> AsyncUpdateMetricsConfiguration(::grpc::ClientContext* context, const ::dmi::MetricsConfigurationRequest& request, ::grpc::CompletionQueue* cq) {
      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::dmi::MetricsConfigurationResponse>>(AsyncUpdateMetricsConfigurationRaw(context, request, cq));
    }
    ::grpc::Status GetMetric(::grpc::ClientContext* context, const ::dmi::GetMetricRequest& request, ::dmi::GetMetricResponse* response) override;
    std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::dmi::GetMetricResponse>> AsyncGetMetric(::grpc::ClientContext* context, const ::dmi::GetMetricRequest& request, ::grpc::CompletionQueue* cq) {
      return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::dmi::GetMetricResponse>>(AsyncGetMetricRaw(context, request, cq));
    }
    std::unique_ptr< ::grpc::ClientReader< ::dmi::Metric>> StreamMetrics(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) {
      return std::unique_ptr< ::grpc::ClientReader< ::dmi::Metric>>(StreamMetricsRaw(context, request));
    }
    std::unique_ptr< ::grpc::ClientAsyncReader< ::dmi::Metric>> AsyncStreamMetrics(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) {
      return std::unique_ptr< ::grpc::ClientAsyncReader< ::dmi::Metric>>(AsyncStreamMetricsRaw(context, request, cq, tag));
    }

   private:
    std::shared_ptr< ::grpc::ChannelInterface> channel_;
    ::grpc::ClientAsyncResponseReader< ::dmi::ListMetricsResponse>* AsyncListMetricsRaw(::grpc::ClientContext* context, const ::dmi::HardwareID& request, ::grpc::CompletionQueue* cq) override;
    ::grpc::ClientAsyncResponseReader< ::dmi::MetricsConfigurationResponse>* AsyncUpdateMetricsConfigurationRaw(::grpc::ClientContext* context, const ::dmi::MetricsConfigurationRequest& request, ::grpc::CompletionQueue* cq) override;
    ::grpc::ClientAsyncResponseReader< ::dmi::GetMetricResponse>* AsyncGetMetricRaw(::grpc::ClientContext* context, const ::dmi::GetMetricRequest& request, ::grpc::CompletionQueue* cq) override;
    ::grpc::ClientReader< ::dmi::Metric>* StreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) override;
    ::grpc::ClientAsyncReader< ::dmi::Metric>* AsyncStreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) override;
    const ::grpc::RpcMethod rpcmethod_ListMetrics_;
    const ::grpc::RpcMethod rpcmethod_UpdateMetricsConfiguration_;
    const ::grpc::RpcMethod rpcmethod_GetMetric_;
    const ::grpc::RpcMethod rpcmethod_StreamMetrics_;
  };
  static std::unique_ptr<Stub> NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());

  class Service : public ::grpc::Service {
   public:
    Service();
    virtual ~Service();
    // List the supported metrics for the passed device.
    // This would be the first call that you make to know about the metrics that a particular device supports and
    // then use the UpdateMetricsConfiguration API to monitor only the required metrics.
    virtual ::grpc::Status ListMetrics(::grpc::ServerContext* context, const ::dmi::HardwareID* request, ::dmi::ListMetricsResponse* response);
    // Updates the configuration of the list of metrics in the request
    // Acts upon single metric configuration, collection of a single metric can be started/stopped
    // by changing its configuration.
    // 
    // This configuration is persisted across restart of the device or the device manager
    virtual ::grpc::Status UpdateMetricsConfiguration(::grpc::ServerContext* context, const ::dmi::MetricsConfigurationRequest* request, ::dmi::MetricsConfigurationResponse* response);
    // Get the instantenous value of a metric
    virtual ::grpc::Status GetMetric(::grpc::ServerContext* context, const ::dmi::GetMetricRequest* request, ::dmi::GetMetricResponse* response);
    // Initiate the server streaming of the metrics
    virtual ::grpc::Status StreamMetrics(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::grpc::ServerWriter< ::dmi::Metric>* writer);
  };
  template <class BaseClass>
  class WithAsyncMethod_ListMetrics : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithAsyncMethod_ListMetrics() {
      ::grpc::Service::MarkMethodAsync(0);
    }
    ~WithAsyncMethod_ListMetrics() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status ListMetrics(::grpc::ServerContext* context, const ::dmi::HardwareID* request, ::dmi::ListMetricsResponse* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    void RequestListMetrics(::grpc::ServerContext* context, ::dmi::HardwareID* request, ::grpc::ServerAsyncResponseWriter< ::dmi::ListMetricsResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
      ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag);
    }
  };
  template <class BaseClass>
  class WithAsyncMethod_UpdateMetricsConfiguration : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithAsyncMethod_UpdateMetricsConfiguration() {
      ::grpc::Service::MarkMethodAsync(1);
    }
    ~WithAsyncMethod_UpdateMetricsConfiguration() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status UpdateMetricsConfiguration(::grpc::ServerContext* context, const ::dmi::MetricsConfigurationRequest* request, ::dmi::MetricsConfigurationResponse* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    void RequestUpdateMetricsConfiguration(::grpc::ServerContext* context, ::dmi::MetricsConfigurationRequest* request, ::grpc::ServerAsyncResponseWriter< ::dmi::MetricsConfigurationResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
      ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag);
    }
  };
  template <class BaseClass>
  class WithAsyncMethod_GetMetric : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithAsyncMethod_GetMetric() {
      ::grpc::Service::MarkMethodAsync(2);
    }
    ~WithAsyncMethod_GetMetric() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status GetMetric(::grpc::ServerContext* context, const ::dmi::GetMetricRequest* request, ::dmi::GetMetricResponse* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    void RequestGetMetric(::grpc::ServerContext* context, ::dmi::GetMetricRequest* request, ::grpc::ServerAsyncResponseWriter< ::dmi::GetMetricResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
      ::grpc::Service::RequestAsyncUnary(2, context, request, response, new_call_cq, notification_cq, tag);
    }
  };
  template <class BaseClass>
  class WithAsyncMethod_StreamMetrics : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithAsyncMethod_StreamMetrics() {
      ::grpc::Service::MarkMethodAsync(3);
    }
    ~WithAsyncMethod_StreamMetrics() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status StreamMetrics(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::grpc::ServerWriter< ::dmi::Metric>* writer) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    void RequestStreamMetrics(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncWriter< ::dmi::Metric>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
      ::grpc::Service::RequestAsyncServerStreaming(3, context, request, writer, new_call_cq, notification_cq, tag);
    }
  };
  typedef WithAsyncMethod_ListMetrics<WithAsyncMethod_UpdateMetricsConfiguration<WithAsyncMethod_GetMetric<WithAsyncMethod_StreamMetrics<Service > > > > AsyncService;
  template <class BaseClass>
  class WithGenericMethod_ListMetrics : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithGenericMethod_ListMetrics() {
      ::grpc::Service::MarkMethodGeneric(0);
    }
    ~WithGenericMethod_ListMetrics() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status ListMetrics(::grpc::ServerContext* context, const ::dmi::HardwareID* request, ::dmi::ListMetricsResponse* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
  };
  template <class BaseClass>
  class WithGenericMethod_UpdateMetricsConfiguration : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithGenericMethod_UpdateMetricsConfiguration() {
      ::grpc::Service::MarkMethodGeneric(1);
    }
    ~WithGenericMethod_UpdateMetricsConfiguration() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status UpdateMetricsConfiguration(::grpc::ServerContext* context, const ::dmi::MetricsConfigurationRequest* request, ::dmi::MetricsConfigurationResponse* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
  };
  template <class BaseClass>
  class WithGenericMethod_GetMetric : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithGenericMethod_GetMetric() {
      ::grpc::Service::MarkMethodGeneric(2);
    }
    ~WithGenericMethod_GetMetric() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status GetMetric(::grpc::ServerContext* context, const ::dmi::GetMetricRequest* request, ::dmi::GetMetricResponse* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
  };
  template <class BaseClass>
  class WithGenericMethod_StreamMetrics : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithGenericMethod_StreamMetrics() {
      ::grpc::Service::MarkMethodGeneric(3);
    }
    ~WithGenericMethod_StreamMetrics() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable synchronous version of this method
    ::grpc::Status StreamMetrics(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::grpc::ServerWriter< ::dmi::Metric>* writer) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
  };
  template <class BaseClass>
  class WithStreamedUnaryMethod_ListMetrics : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithStreamedUnaryMethod_ListMetrics() {
      ::grpc::Service::MarkMethodStreamed(0,
        new ::grpc::StreamedUnaryHandler< ::dmi::HardwareID, ::dmi::ListMetricsResponse>(std::bind(&WithStreamedUnaryMethod_ListMetrics<BaseClass>::StreamedListMetrics, this, std::placeholders::_1, std::placeholders::_2)));
    }
    ~WithStreamedUnaryMethod_ListMetrics() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable regular version of this method
    ::grpc::Status ListMetrics(::grpc::ServerContext* context, const ::dmi::HardwareID* request, ::dmi::ListMetricsResponse* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    // replace default version of method with streamed unary
    virtual ::grpc::Status StreamedListMetrics(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::dmi::HardwareID,::dmi::ListMetricsResponse>* server_unary_streamer) = 0;
  };
  template <class BaseClass>
  class WithStreamedUnaryMethod_UpdateMetricsConfiguration : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithStreamedUnaryMethod_UpdateMetricsConfiguration() {
      ::grpc::Service::MarkMethodStreamed(1,
        new ::grpc::StreamedUnaryHandler< ::dmi::MetricsConfigurationRequest, ::dmi::MetricsConfigurationResponse>(std::bind(&WithStreamedUnaryMethod_UpdateMetricsConfiguration<BaseClass>::StreamedUpdateMetricsConfiguration, this, std::placeholders::_1, std::placeholders::_2)));
    }
    ~WithStreamedUnaryMethod_UpdateMetricsConfiguration() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable regular version of this method
    ::grpc::Status UpdateMetricsConfiguration(::grpc::ServerContext* context, const ::dmi::MetricsConfigurationRequest* request, ::dmi::MetricsConfigurationResponse* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    // replace default version of method with streamed unary
    virtual ::grpc::Status StreamedUpdateMetricsConfiguration(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::dmi::MetricsConfigurationRequest,::dmi::MetricsConfigurationResponse>* server_unary_streamer) = 0;
  };
  template <class BaseClass>
  class WithStreamedUnaryMethod_GetMetric : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithStreamedUnaryMethod_GetMetric() {
      ::grpc::Service::MarkMethodStreamed(2,
        new ::grpc::StreamedUnaryHandler< ::dmi::GetMetricRequest, ::dmi::GetMetricResponse>(std::bind(&WithStreamedUnaryMethod_GetMetric<BaseClass>::StreamedGetMetric, this, std::placeholders::_1, std::placeholders::_2)));
    }
    ~WithStreamedUnaryMethod_GetMetric() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable regular version of this method
    ::grpc::Status GetMetric(::grpc::ServerContext* context, const ::dmi::GetMetricRequest* request, ::dmi::GetMetricResponse* response) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    // replace default version of method with streamed unary
    virtual ::grpc::Status StreamedGetMetric(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::dmi::GetMetricRequest,::dmi::GetMetricResponse>* server_unary_streamer) = 0;
  };
  typedef WithStreamedUnaryMethod_ListMetrics<WithStreamedUnaryMethod_UpdateMetricsConfiguration<WithStreamedUnaryMethod_GetMetric<Service > > > StreamedUnaryService;
  template <class BaseClass>
  class WithSplitStreamingMethod_StreamMetrics : public BaseClass {
   private:
    void BaseClassMustBeDerivedFromService(const Service *service) {}
   public:
    WithSplitStreamingMethod_StreamMetrics() {
      ::grpc::Service::MarkMethodStreamed(3,
        new ::grpc::SplitServerStreamingHandler< ::google::protobuf::Empty, ::dmi::Metric>(std::bind(&WithSplitStreamingMethod_StreamMetrics<BaseClass>::StreamedStreamMetrics, this, std::placeholders::_1, std::placeholders::_2)));
    }
    ~WithSplitStreamingMethod_StreamMetrics() override {
      BaseClassMustBeDerivedFromService(this);
    }
    // disable regular version of this method
    ::grpc::Status StreamMetrics(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::grpc::ServerWriter< ::dmi::Metric>* writer) final override {
      abort();
      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
    }
    // replace default version of method with split streamed
    virtual ::grpc::Status StreamedStreamMetrics(::grpc::ServerContext* context, ::grpc::ServerSplitStreamer< ::google::protobuf::Empty,::dmi::Metric>* server_split_streamer) = 0;
  };
  typedef WithSplitStreamingMethod_StreamMetrics<Service > SplitStreamedService;
  typedef WithStreamedUnaryMethod_ListMetrics<WithStreamedUnaryMethod_UpdateMetricsConfiguration<WithStreamedUnaryMethod_GetMetric<WithSplitStreamingMethod_StreamMetrics<Service > > > > StreamedService;
};

}  // namespace dmi


#endif  // GRPC_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto__INCLUDED
