diff --git a/cpp/dmi/hw_metrics_mgmt_service.pb.cc b/cpp/dmi/hw_metrics_mgmt_service.pb.cc
new file mode 100644
index 0000000..389e53d
--- /dev/null
+++ b/cpp/dmi/hw_metrics_mgmt_service.pb.cc
@@ -0,0 +1,4155 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/hw_metrics_mgmt_service.proto
+
+#include "dmi/hw_metrics_mgmt_service.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Uuid_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_ComponentSensorData_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<2> scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+namespace dmi {
+class MetricConfigDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<MetricConfig> _instance;
+} _MetricConfig_default_instance_;
+class MetricsConfigDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<MetricsConfig> _instance;
+} _MetricsConfig_default_instance_;
+class ListMetricsResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ListMetricsResponse> _instance;
+} _ListMetricsResponse_default_instance_;
+class MetricsConfigurationRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<MetricsConfigurationRequest> _instance;
+  const ::dmi::MetricsConfig* changes_;
+  bool reset_to_default_;
+} _MetricsConfigurationRequest_default_instance_;
+class MetricsConfigurationResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<MetricsConfigurationResponse> _instance;
+} _MetricsConfigurationResponse_default_instance_;
+class MetricMetaDataDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<MetricMetaData> _instance;
+} _MetricMetaData_default_instance_;
+class MetricDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Metric> _instance;
+} _Metric_default_instance_;
+class GetMetricRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<GetMetricRequest> _instance;
+} _GetMetricRequest_default_instance_;
+class GetMetricResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<GetMetricResponse> _instance;
+} _GetMetricResponse_default_instance_;
+}  // namespace dmi
+static void InitDefaultsMetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_MetricConfig_default_instance_;
+    new (ptr) ::dmi::MetricConfig();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::MetricConfig::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsMetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {}};
+
+static void InitDefaultsMetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_MetricsConfig_default_instance_;
+    new (ptr) ::dmi::MetricsConfig();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::MetricsConfig::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsMetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ListMetricsResponse_default_instance_;
+    new (ptr) ::dmi::ListMetricsResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ListMetricsResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_ListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsMetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_MetricsConfigurationRequest_default_instance_;
+    new (ptr) ::dmi::MetricsConfigurationRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::MetricsConfigurationRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_MetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsMetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,
+      &scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsMetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_MetricsConfigurationResponse_default_instance_;
+    new (ptr) ::dmi::MetricsConfigurationResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::MetricsConfigurationResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_MetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsMetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {}};
+
+static void InitDefaultsMetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_MetricMetaData_default_instance_;
+    new (ptr) ::dmi::MetricMetaData();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::MetricMetaData::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsMetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsMetric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_Metric_default_instance_;
+    new (ptr) ::dmi::Metric();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::Metric::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsMetric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,
+      &scc_info_ComponentSensorData_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsGetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_GetMetricRequest_default_instance_;
+    new (ptr) ::dmi::GetMetricRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::GetMetricRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_GetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsGetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsGetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_GetMetricResponse_default_instance_;
+    new (ptr) ::dmi::GetMetricResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::GetMetricResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_GetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsGetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};
+
+void InitDefaults_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  ::google::protobuf::internal::InitSCC(&scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_MetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_MetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_GetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_GetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+}
+
+::google::protobuf::Metadata file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[9];
+const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[4];
+constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = nullptr;
+
+const ::google::protobuf::uint32 TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricConfig, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricConfig, metric_id_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricConfig, is_configured_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricConfig, poll_interval_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfig, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfig, metrics_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, metrics_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationRequest, _oneof_case_[0]),
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationRequest, device_uuid_),
+  offsetof(::dmi::MetricsConfigurationRequestDefaultTypeInternal, changes_),
+  offsetof(::dmi::MetricsConfigurationRequestDefaultTypeInternal, reset_to_default_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationRequest, operation_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricMetaData, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricMetaData, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricMetaData, component_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricMetaData, component_name_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::Metric, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::Metric, metric_id_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Metric, metric_metadata_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Metric, value_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricRequest, meta_data_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricRequest, metric_id_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, metric_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, reason_detail_),
+};
+static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, -1, sizeof(::dmi::MetricConfig)},
+  { 8, -1, sizeof(::dmi::MetricsConfig)},
+  { 14, -1, sizeof(::dmi::ListMetricsResponse)},
+  { 23, -1, sizeof(::dmi::MetricsConfigurationRequest)},
+  { 32, -1, sizeof(::dmi::MetricsConfigurationResponse)},
+  { 40, -1, sizeof(::dmi::MetricMetaData)},
+  { 48, -1, sizeof(::dmi::Metric)},
+  { 56, -1, sizeof(::dmi::GetMetricRequest)},
+  { 63, -1, sizeof(::dmi::GetMetricResponse)},
+};
+
+static ::google::protobuf::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricConfig_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricsConfig_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ListMetricsResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricsConfigurationRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricsConfigurationResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricMetaData_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_Metric_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetMetricRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetMetricResponse_default_instance_),
+};
+
+::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = {
+  {}, AddDescriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, "dmi/hw_metrics_mgmt_service.proto", schemas,
+  file_default_instances, TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto::offsets,
+  file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, 9, file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, file_level_service_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto,
+};
+
+const char descriptor_table_protodef_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[] =
+  "\n!dmi/hw_metrics_mgmt_service.proto\022\003dmi"
+  "\032\021dmi/commons.proto\032\014dmi/hw.proto\"a\n\014Met"
+  "ricConfig\022#\n\tmetric_id\030\001 \001(\0162\020.dmi.Metri"
+  "cNames\022\025\n\ris_configured\030\002 \001(\010\022\025\n\rpoll_in"
+  "terval\030\003 \001(\r\"3\n\rMetricsConfig\022\"\n\007metrics"
+  "\030\001 \003(\0132\021.dmi.MetricConfig\"\377\001\n\023ListMetric"
+  "sResponse\022\033\n\006status\030\001 \001(\0162\013.dmi.Status\022/"
+  "\n\006reason\030\002 \001(\0162\037.dmi.ListMetricsResponse"
+  ".Reason\022#\n\007metrics\030\003 \001(\0132\022.dmi.MetricsCo"
+  "nfig\022\025\n\rreason_detail\030\004 \001(\t\"^\n\006Reason\022\024\n"
+  "\020UNDEFINED_REASON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022"
+  "\022\n\016INTERNAL_ERROR\020\002\022\026\n\022DEVICE_UNREACHABL"
+  "E\020\003\"\215\001\n\033MetricsConfigurationRequest\022\036\n\013d"
+  "evice_uuid\030\001 \001(\0132\t.dmi.Uuid\022%\n\007changes\030\002"
+  " \001(\0132\022.dmi.MetricsConfigH\000\022\032\n\020reset_to_d"
+  "efault\030\003 \001(\010H\000B\013\n\toperation\"\240\002\n\034MetricsC"
+  "onfigurationResponse\022\033\n\006status\030\001 \001(\0162\013.d"
+  "mi.Status\0228\n\006reason\030\002 \001(\0162(.dmi.MetricsC"
+  "onfigurationResponse.Reason\022\025\n\rreason_de"
+  "tail\030\003 \001(\t\"\221\001\n\006Reason\022\024\n\020UNDEFINED_REASO"
+  "N\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERNAL_ERRO"
+  "R\020\002\022\035\n\031POLL_INTERVAL_UNSUPPORTED\020\003\022\022\n\016IN"
+  "VALID_METRIC\020\004\022\026\n\022DEVICE_UNREACHABLE\020\005\"k"
+  "\n\016MetricMetaData\022\036\n\013device_uuid\030\001 \001(\0132\t."
+  "dmi.Uuid\022!\n\016component_uuid\030\002 \001(\0132\t.dmi.U"
+  "uid\022\026\n\016component_name\030\003 \001(\t\"\204\001\n\006Metric\022#"
+  "\n\tmetric_id\030\001 \001(\0162\020.dmi.MetricNames\022,\n\017m"
+  "etric_metadata\030\002 \001(\0132\023.dmi.MetricMetaDat"
+  "a\022\'\n\005value\030\003 \001(\0132\030.dmi.ComponentSensorDa"
+  "ta\"_\n\020GetMetricRequest\022&\n\tmeta_data\030\001 \001("
+  "\0132\023.dmi.MetricMetaData\022#\n\tmetric_id\030\002 \001("
+  "\0162\020.dmi.MetricNames\"\237\002\n\021GetMetricRespons"
+  "e\022\033\n\006status\030\001 \001(\0162\013.dmi.Status\022-\n\006reason"
+  "\030\002 \001(\0162\035.dmi.GetMetricResponse.Reason\022\033\n"
+  "\006metric\030\003 \001(\0132\013.dmi.Metric\022\025\n\rreason_det"
+  "ail\030\004 \001(\t\"\211\001\n\006Reason\022\024\n\020UNDEFINED_REASON"
+  "\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\025\n\021UNKNOWN_COMPON"
+  "ENT\020\002\022\022\n\016INTERNAL_ERROR\020\003\022\022\n\016INVALID_MET"
+  "RIC\020\004\022\026\n\022DEVICE_UNREACHABLE\020\005*\331\005\n\013Metric"
+  "Names\022\031\n\025METRIC_NAME_UNDEFINED\020\000\022\024\n\020METR"
+  "IC_FAN_SPEED\020\001\022\023\n\017METRIC_CPU_TEMP\020d\022\037\n\033M"
+  "ETRIC_CPU_USAGE_PERCENTAGE\020e\022\034\n\027METRIC_T"
+  "RANSCEIVER_TEMP\020\310\001\022\037\n\032METRIC_TRANSCEIVER"
+  "_VOLTAGE\020\311\001\022\034\n\027METRIC_TRANSCEIVER_BIAS\020\312"
+  "\001\022 \n\033METRIC_TRANSCEIVER_RX_POWER\020\313\001\022 \n\033M"
+  "ETRIC_TRANSCEIVER_TX_POWER\020\314\001\022\"\n\035METRIC_"
+  "TRANSCEIVER_WAVELENGTH\020\315\001\022\025\n\020METRIC_DISK"
+  "_TEMP\020\254\002\022\031\n\024METRIC_DISK_CAPACITY\020\255\002\022\026\n\021M"
+  "ETRIC_DISK_USAGE\020\256\002\022!\n\034METRIC_DISK_USAGE"
+  "_PERCENTAGE\020\257\002\022&\n!METRIC_DISK_READ_WRITE"
+  "_PERCENTAGE\020\260\002\022(\n#METRIC_DISK_FAULTY_CEL"
+  "LS_PERCENTAGE\020\261\002\022\024\n\017METRIC_RAM_TEMP\020\220\003\022\030"
+  "\n\023METRIC_RAM_CAPACITY\020\221\003\022\025\n\020METRIC_RAM_U"
+  "SAGE\020\222\003\022 \n\033METRIC_RAM_USAGE_PERCENTAGE\020\223"
+  "\003\022\025\n\020METRIC_POWER_MAX\020\364\003\022\027\n\022METRIC_POWER"
+  "_USAGE\020\365\003\022\"\n\035METRIC_POWER_USAGE_PERCENTA"
+  "GE\020\366\003\022\"\n\035METRIC_INNER_SURROUNDING_TEMP\020\330"
+  "\0042\371\001\n\036NativeMetricsManagementService\0228\n\013"
+  "ListMetrics\022\017.dmi.HardwareID\032\030.dmi.ListM"
+  "etricsResponse\022a\n\032UpdateMetricsConfigura"
+  "tion\022 .dmi.MetricsConfigurationRequest\032!"
+  ".dmi.MetricsConfigurationResponse\022:\n\tGet"
+  "Metric\022\025.dmi.GetMetricRequest\032\026.dmi.GetM"
+  "etricResponseB;Z9github.com/opencord/dev"
+  "ice-management-interface/v3/go/dmib\006prot"
+  "o3"
+  ;
+::google::protobuf::internal::DescriptorTable descriptor_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = {
+  false, InitDefaults_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, 
+  descriptor_table_protodef_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto,
+  "dmi/hw_metrics_mgmt_service.proto", &assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, 2602,
+};
+
+void AddDescriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  static constexpr ::google::protobuf::internal::InitFunc deps[2] =
+  {
+    ::AddDescriptors_dmi_2fcommons_2eproto,
+    ::AddDescriptors_dmi_2fhw_2eproto,
+  };
+ ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, deps, 2);
+}
+
+// Force running AddDescriptors() at dynamic initialization time.
+static bool dynamic_init_dummy_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = []() { AddDescriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto(); return true; }();
+namespace dmi {
+const ::google::protobuf::EnumDescriptor* ListMetricsResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[0];
+}
+bool ListMetricsResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const ListMetricsResponse_Reason ListMetricsResponse::UNDEFINED_REASON;
+const ListMetricsResponse_Reason ListMetricsResponse::UNKNOWN_DEVICE;
+const ListMetricsResponse_Reason ListMetricsResponse::INTERNAL_ERROR;
+const ListMetricsResponse_Reason ListMetricsResponse::DEVICE_UNREACHABLE;
+const ListMetricsResponse_Reason ListMetricsResponse::Reason_MIN;
+const ListMetricsResponse_Reason ListMetricsResponse::Reason_MAX;
+const int ListMetricsResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* MetricsConfigurationResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[1];
+}
+bool MetricsConfigurationResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::UNDEFINED_REASON;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::UNKNOWN_DEVICE;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::INTERNAL_ERROR;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::POLL_INTERVAL_UNSUPPORTED;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::INVALID_METRIC;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::DEVICE_UNREACHABLE;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::Reason_MIN;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::Reason_MAX;
+const int MetricsConfigurationResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* GetMetricResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[2];
+}
+bool GetMetricResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const GetMetricResponse_Reason GetMetricResponse::UNDEFINED_REASON;
+const GetMetricResponse_Reason GetMetricResponse::UNKNOWN_DEVICE;
+const GetMetricResponse_Reason GetMetricResponse::UNKNOWN_COMPONENT;
+const GetMetricResponse_Reason GetMetricResponse::INTERNAL_ERROR;
+const GetMetricResponse_Reason GetMetricResponse::INVALID_METRIC;
+const GetMetricResponse_Reason GetMetricResponse::DEVICE_UNREACHABLE;
+const GetMetricResponse_Reason GetMetricResponse::Reason_MIN;
+const GetMetricResponse_Reason GetMetricResponse::Reason_MAX;
+const int GetMetricResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* MetricNames_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[3];
+}
+bool MetricNames_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 100:
+    case 101:
+    case 200:
+    case 201:
+    case 202:
+    case 203:
+    case 204:
+    case 205:
+    case 300:
+    case 301:
+    case 302:
+    case 303:
+    case 304:
+    case 305:
+    case 400:
+    case 401:
+    case 402:
+    case 403:
+    case 500:
+    case 501:
+    case 502:
+    case 600:
+      return true;
+    default:
+      return false;
+  }
+}
+
+
+// ===================================================================
+
+void MetricConfig::InitAsDefaultInstance() {
+}
+class MetricConfig::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MetricConfig::kMetricIdFieldNumber;
+const int MetricConfig::kIsConfiguredFieldNumber;
+const int MetricConfig::kPollIntervalFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MetricConfig::MetricConfig()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.MetricConfig)
+}
+MetricConfig::MetricConfig(const MetricConfig& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::memcpy(&metric_id_, &from.metric_id_,
+    static_cast<size_t>(reinterpret_cast<char*>(&poll_interval_) -
+    reinterpret_cast<char*>(&metric_id_)) + sizeof(poll_interval_));
+  // @@protoc_insertion_point(copy_constructor:dmi.MetricConfig)
+}
+
+void MetricConfig::SharedCtor() {
+  ::memset(&metric_id_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&poll_interval_) -
+      reinterpret_cast<char*>(&metric_id_)) + sizeof(poll_interval_));
+}
+
+MetricConfig::~MetricConfig() {
+  // @@protoc_insertion_point(destructor:dmi.MetricConfig)
+  SharedDtor();
+}
+
+void MetricConfig::SharedDtor() {
+}
+
+void MetricConfig::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const MetricConfig& MetricConfig::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void MetricConfig::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.MetricConfig)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  ::memset(&metric_id_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&poll_interval_) -
+      reinterpret_cast<char*>(&metric_id_)) + sizeof(poll_interval_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* MetricConfig::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<MetricConfig*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.MetricNames metric_id = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_metric_id(static_cast<::dmi::MetricNames>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // bool is_configured = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        msg->set_is_configured(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // uint32 poll_interval = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
+        msg->set_poll_interval(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool MetricConfig::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.MetricConfig)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.MetricNames metric_id = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_metric_id(static_cast< ::dmi::MetricNames >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // bool is_configured = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &is_configured_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // uint32 poll_interval = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
+
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &poll_interval_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.MetricConfig)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.MetricConfig)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void MetricConfig::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.MetricConfig)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.MetricNames metric_id = 1;
+  if (this->metric_id() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->metric_id(), output);
+  }
+
+  // bool is_configured = 2;
+  if (this->is_configured() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_configured(), output);
+  }
+
+  // uint32 poll_interval = 3;
+  if (this->poll_interval() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(3, this->poll_interval(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.MetricConfig)
+}
+
+::google::protobuf::uint8* MetricConfig::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricConfig)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.MetricNames metric_id = 1;
+  if (this->metric_id() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->metric_id(), target);
+  }
+
+  // bool is_configured = 2;
+  if (this->is_configured() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_configured(), target);
+  }
+
+  // uint32 poll_interval = 3;
+  if (this->poll_interval() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(3, this->poll_interval(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricConfig)
+  return target;
+}
+
+size_t MetricConfig::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.MetricConfig)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.MetricNames metric_id = 1;
+  if (this->metric_id() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->metric_id());
+  }
+
+  // bool is_configured = 2;
+  if (this->is_configured() != 0) {
+    total_size += 1 + 1;
+  }
+
+  // uint32 poll_interval = 3;
+  if (this->poll_interval() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::UInt32Size(
+        this->poll_interval());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void MetricConfig::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricConfig)
+  GOOGLE_DCHECK_NE(&from, this);
+  const MetricConfig* source =
+      ::google::protobuf::DynamicCastToGenerated<MetricConfig>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricConfig)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricConfig)
+    MergeFrom(*source);
+  }
+}
+
+void MetricConfig::MergeFrom(const MetricConfig& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricConfig)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.metric_id() != 0) {
+    set_metric_id(from.metric_id());
+  }
+  if (from.is_configured() != 0) {
+    set_is_configured(from.is_configured());
+  }
+  if (from.poll_interval() != 0) {
+    set_poll_interval(from.poll_interval());
+  }
+}
+
+void MetricConfig::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricConfig)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MetricConfig::CopyFrom(const MetricConfig& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricConfig)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MetricConfig::IsInitialized() const {
+  return true;
+}
+
+void MetricConfig::Swap(MetricConfig* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MetricConfig::InternalSwap(MetricConfig* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(metric_id_, other->metric_id_);
+  swap(is_configured_, other->is_configured_);
+  swap(poll_interval_, other->poll_interval_);
+}
+
+::google::protobuf::Metadata MetricConfig::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void MetricsConfig::InitAsDefaultInstance() {
+}
+class MetricsConfig::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MetricsConfig::kMetricsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MetricsConfig::MetricsConfig()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.MetricsConfig)
+}
+MetricsConfig::MetricsConfig(const MetricsConfig& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr),
+      metrics_(from.metrics_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  // @@protoc_insertion_point(copy_constructor:dmi.MetricsConfig)
+}
+
+void MetricsConfig::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+}
+
+MetricsConfig::~MetricsConfig() {
+  // @@protoc_insertion_point(destructor:dmi.MetricsConfig)
+  SharedDtor();
+}
+
+void MetricsConfig::SharedDtor() {
+}
+
+void MetricsConfig::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const MetricsConfig& MetricsConfig::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void MetricsConfig::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.MetricsConfig)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  metrics_.Clear();
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* MetricsConfig::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<MetricsConfig*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // repeated .dmi.MetricConfig metrics = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        do {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          parser_till_end = ::dmi::MetricConfig::_InternalParse;
+          object = msg->add_metrics();
+          if (size > end - ptr) goto len_delim_till_end;
+          ptr += size;
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+              {parser_till_end, object}, ptr - size, ptr));
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 10 && (ptr += 1));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool MetricsConfig::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.MetricsConfig)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .dmi.MetricConfig metrics = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+                input, add_metrics()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.MetricsConfig)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.MetricsConfig)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void MetricsConfig::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.MetricsConfig)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // repeated .dmi.MetricConfig metrics = 1;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->metrics_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1,
+      this->metrics(static_cast<int>(i)),
+      output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.MetricsConfig)
+}
+
+::google::protobuf::uint8* MetricsConfig::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricsConfig)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // repeated .dmi.MetricConfig metrics = 1;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->metrics_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, this->metrics(static_cast<int>(i)), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricsConfig)
+  return target;
+}
+
+size_t MetricsConfig::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.MetricsConfig)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated .dmi.MetricConfig metrics = 1;
+  {
+    unsigned int count = static_cast<unsigned int>(this->metrics_size());
+    total_size += 1UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->metrics(static_cast<int>(i)));
+    }
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void MetricsConfig::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricsConfig)
+  GOOGLE_DCHECK_NE(&from, this);
+  const MetricsConfig* source =
+      ::google::protobuf::DynamicCastToGenerated<MetricsConfig>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricsConfig)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricsConfig)
+    MergeFrom(*source);
+  }
+}
+
+void MetricsConfig::MergeFrom(const MetricsConfig& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricsConfig)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  metrics_.MergeFrom(from.metrics_);
+}
+
+void MetricsConfig::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricsConfig)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MetricsConfig::CopyFrom(const MetricsConfig& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricsConfig)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MetricsConfig::IsInitialized() const {
+  return true;
+}
+
+void MetricsConfig::Swap(MetricsConfig* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MetricsConfig::InternalSwap(MetricsConfig* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  CastToBase(&metrics_)->InternalSwap(CastToBase(&other->metrics_));
+}
+
+::google::protobuf::Metadata MetricsConfig::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ListMetricsResponse::InitAsDefaultInstance() {
+  ::dmi::_ListMetricsResponse_default_instance_._instance.get_mutable()->metrics_ = const_cast< ::dmi::MetricsConfig*>(
+      ::dmi::MetricsConfig::internal_default_instance());
+}
+class ListMetricsResponse::HasBitSetters {
+ public:
+  static const ::dmi::MetricsConfig& metrics(const ListMetricsResponse* msg);
+};
+
+const ::dmi::MetricsConfig&
+ListMetricsResponse::HasBitSetters::metrics(const ListMetricsResponse* msg) {
+  return *msg->metrics_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ListMetricsResponse::kStatusFieldNumber;
+const int ListMetricsResponse::kReasonFieldNumber;
+const int ListMetricsResponse::kMetricsFieldNumber;
+const int ListMetricsResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ListMetricsResponse::ListMetricsResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ListMetricsResponse)
+}
+ListMetricsResponse::ListMetricsResponse(const ListMetricsResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_metrics()) {
+    metrics_ = new ::dmi::MetricsConfig(*from.metrics_);
+  } else {
+    metrics_ = nullptr;
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.ListMetricsResponse)
+}
+
+void ListMetricsResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&metrics_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&metrics_)) + sizeof(reason_));
+}
+
+ListMetricsResponse::~ListMetricsResponse() {
+  // @@protoc_insertion_point(destructor:dmi.ListMetricsResponse)
+  SharedDtor();
+}
+
+void ListMetricsResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete metrics_;
+}
+
+void ListMetricsResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ListMetricsResponse& ListMetricsResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ListMetricsResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ListMetricsResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && metrics_ != nullptr) {
+    delete metrics_;
+  }
+  metrics_ = nullptr;
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ListMetricsResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ListMetricsResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ListMetricsResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::ListMetricsResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.MetricsConfig metrics = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::MetricsConfig::_InternalParse;
+        object = msg->mutable_metrics();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ListMetricsResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ListMetricsResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ListMetricsResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ListMetricsResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::ListMetricsResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.MetricsConfig metrics = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_metrics()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ListMetricsResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ListMetricsResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ListMetricsResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ListMetricsResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ListMetricsResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.ListMetricsResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // .dmi.MetricsConfig metrics = 3;
+  if (this->has_metrics()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::metrics(this), output);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ListMetricsResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ListMetricsResponse)
+}
+
+::google::protobuf::uint8* ListMetricsResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ListMetricsResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.ListMetricsResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // .dmi.MetricsConfig metrics = 3;
+  if (this->has_metrics()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::metrics(this), target);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ListMetricsResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ListMetricsResponse)
+  return target;
+}
+
+size_t ListMetricsResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ListMetricsResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.MetricsConfig metrics = 3;
+  if (this->has_metrics()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *metrics_);
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.ListMetricsResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ListMetricsResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ListMetricsResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ListMetricsResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<ListMetricsResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ListMetricsResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ListMetricsResponse)
+    MergeFrom(*source);
+  }
+}
+
+void ListMetricsResponse::MergeFrom(const ListMetricsResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ListMetricsResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_metrics()) {
+    mutable_metrics()->::dmi::MetricsConfig::MergeFrom(from.metrics());
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void ListMetricsResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ListMetricsResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ListMetricsResponse::CopyFrom(const ListMetricsResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ListMetricsResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ListMetricsResponse::IsInitialized() const {
+  return true;
+}
+
+void ListMetricsResponse::Swap(ListMetricsResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ListMetricsResponse::InternalSwap(ListMetricsResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(metrics_, other->metrics_);
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata ListMetricsResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void MetricsConfigurationRequest::InitAsDefaultInstance() {
+  ::dmi::_MetricsConfigurationRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+  ::dmi::_MetricsConfigurationRequest_default_instance_.changes_ = const_cast< ::dmi::MetricsConfig*>(
+      ::dmi::MetricsConfig::internal_default_instance());
+  ::dmi::_MetricsConfigurationRequest_default_instance_.reset_to_default_ = false;
+}
+class MetricsConfigurationRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const MetricsConfigurationRequest* msg);
+  static const ::dmi::MetricsConfig& changes(const MetricsConfigurationRequest* msg);
+};
+
+const ::dmi::Uuid&
+MetricsConfigurationRequest::HasBitSetters::device_uuid(const MetricsConfigurationRequest* msg) {
+  return *msg->device_uuid_;
+}
+const ::dmi::MetricsConfig&
+MetricsConfigurationRequest::HasBitSetters::changes(const MetricsConfigurationRequest* msg) {
+  return *msg->operation_.changes_;
+}
+void MetricsConfigurationRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+void MetricsConfigurationRequest::set_allocated_changes(::dmi::MetricsConfig* changes) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  clear_operation();
+  if (changes) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      changes = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, changes, submessage_arena);
+    }
+    set_has_changes();
+    operation_.changes_ = changes;
+  }
+  // @@protoc_insertion_point(field_set_allocated:dmi.MetricsConfigurationRequest.changes)
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MetricsConfigurationRequest::kDeviceUuidFieldNumber;
+const int MetricsConfigurationRequest::kChangesFieldNumber;
+const int MetricsConfigurationRequest::kResetToDefaultFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MetricsConfigurationRequest::MetricsConfigurationRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.MetricsConfigurationRequest)
+}
+MetricsConfigurationRequest::MetricsConfigurationRequest(const MetricsConfigurationRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  clear_has_operation();
+  switch (from.operation_case()) {
+    case kChanges: {
+      mutable_changes()->::dmi::MetricsConfig::MergeFrom(from.changes());
+      break;
+    }
+    case kResetToDefault: {
+      set_reset_to_default(from.reset_to_default());
+      break;
+    }
+    case OPERATION_NOT_SET: {
+      break;
+    }
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.MetricsConfigurationRequest)
+}
+
+void MetricsConfigurationRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_MetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  device_uuid_ = nullptr;
+  clear_has_operation();
+}
+
+MetricsConfigurationRequest::~MetricsConfigurationRequest() {
+  // @@protoc_insertion_point(destructor:dmi.MetricsConfigurationRequest)
+  SharedDtor();
+}
+
+void MetricsConfigurationRequest::SharedDtor() {
+  if (this != internal_default_instance()) delete device_uuid_;
+  if (has_operation()) {
+    clear_operation();
+  }
+}
+
+void MetricsConfigurationRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const MetricsConfigurationRequest& MetricsConfigurationRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_MetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void MetricsConfigurationRequest::clear_operation() {
+// @@protoc_insertion_point(one_of_clear_start:dmi.MetricsConfigurationRequest)
+  switch (operation_case()) {
+    case kChanges: {
+      delete operation_.changes_;
+      break;
+    }
+    case kResetToDefault: {
+      // No need to clear
+      break;
+    }
+    case OPERATION_NOT_SET: {
+      break;
+    }
+  }
+  _oneof_case_[0] = OPERATION_NOT_SET;
+}
+
+
+void MetricsConfigurationRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.MetricsConfigurationRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  clear_operation();
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* MetricsConfigurationRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<MetricsConfigurationRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.MetricsConfig changes = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::MetricsConfig::_InternalParse;
+        object = msg->mutable_changes();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // bool reset_to_default = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
+        msg->set_reset_to_default(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool MetricsConfigurationRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.MetricsConfigurationRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.MetricsConfig changes = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_changes()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // bool reset_to_default = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
+          clear_operation();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &operation_.reset_to_default_)));
+          set_has_reset_to_default();
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.MetricsConfigurationRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.MetricsConfigurationRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void MetricsConfigurationRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.MetricsConfigurationRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // .dmi.MetricsConfig changes = 2;
+  if (has_changes()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::changes(this), output);
+  }
+
+  // bool reset_to_default = 3;
+  if (has_reset_to_default()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->reset_to_default(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.MetricsConfigurationRequest)
+}
+
+::google::protobuf::uint8* MetricsConfigurationRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricsConfigurationRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // .dmi.MetricsConfig changes = 2;
+  if (has_changes()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::changes(this), target);
+  }
+
+  // bool reset_to_default = 3;
+  if (has_reset_to_default()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->reset_to_default(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricsConfigurationRequest)
+  return target;
+}
+
+size_t MetricsConfigurationRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.MetricsConfigurationRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  switch (operation_case()) {
+    // .dmi.MetricsConfig changes = 2;
+    case kChanges: {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          *operation_.changes_);
+      break;
+    }
+    // bool reset_to_default = 3;
+    case kResetToDefault: {
+      total_size += 1 + 1;
+      break;
+    }
+    case OPERATION_NOT_SET: {
+      break;
+    }
+  }
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void MetricsConfigurationRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricsConfigurationRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const MetricsConfigurationRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<MetricsConfigurationRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricsConfigurationRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricsConfigurationRequest)
+    MergeFrom(*source);
+  }
+}
+
+void MetricsConfigurationRequest::MergeFrom(const MetricsConfigurationRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricsConfigurationRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+  switch (from.operation_case()) {
+    case kChanges: {
+      mutable_changes()->::dmi::MetricsConfig::MergeFrom(from.changes());
+      break;
+    }
+    case kResetToDefault: {
+      set_reset_to_default(from.reset_to_default());
+      break;
+    }
+    case OPERATION_NOT_SET: {
+      break;
+    }
+  }
+}
+
+void MetricsConfigurationRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricsConfigurationRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MetricsConfigurationRequest::CopyFrom(const MetricsConfigurationRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricsConfigurationRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MetricsConfigurationRequest::IsInitialized() const {
+  return true;
+}
+
+void MetricsConfigurationRequest::Swap(MetricsConfigurationRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MetricsConfigurationRequest::InternalSwap(MetricsConfigurationRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(device_uuid_, other->device_uuid_);
+  swap(operation_, other->operation_);
+  swap(_oneof_case_[0], other->_oneof_case_[0]);
+}
+
+::google::protobuf::Metadata MetricsConfigurationRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void MetricsConfigurationResponse::InitAsDefaultInstance() {
+}
+class MetricsConfigurationResponse::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MetricsConfigurationResponse::kStatusFieldNumber;
+const int MetricsConfigurationResponse::kReasonFieldNumber;
+const int MetricsConfigurationResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MetricsConfigurationResponse::MetricsConfigurationResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.MetricsConfigurationResponse)
+}
+MetricsConfigurationResponse::MetricsConfigurationResponse(const MetricsConfigurationResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.MetricsConfigurationResponse)
+}
+
+void MetricsConfigurationResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_MetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+}
+
+MetricsConfigurationResponse::~MetricsConfigurationResponse() {
+  // @@protoc_insertion_point(destructor:dmi.MetricsConfigurationResponse)
+  SharedDtor();
+}
+
+void MetricsConfigurationResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void MetricsConfigurationResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const MetricsConfigurationResponse& MetricsConfigurationResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_MetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void MetricsConfigurationResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.MetricsConfigurationResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* MetricsConfigurationResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<MetricsConfigurationResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.MetricsConfigurationResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::MetricsConfigurationResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.MetricsConfigurationResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool MetricsConfigurationResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.MetricsConfigurationResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.MetricsConfigurationResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::MetricsConfigurationResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.MetricsConfigurationResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.MetricsConfigurationResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.MetricsConfigurationResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void MetricsConfigurationResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.MetricsConfigurationResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.MetricsConfigurationResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.MetricsConfigurationResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.MetricsConfigurationResponse)
+}
+
+::google::protobuf::uint8* MetricsConfigurationResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricsConfigurationResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.MetricsConfigurationResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.MetricsConfigurationResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricsConfigurationResponse)
+  return target;
+}
+
+size_t MetricsConfigurationResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.MetricsConfigurationResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.MetricsConfigurationResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void MetricsConfigurationResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricsConfigurationResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const MetricsConfigurationResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<MetricsConfigurationResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricsConfigurationResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricsConfigurationResponse)
+    MergeFrom(*source);
+  }
+}
+
+void MetricsConfigurationResponse::MergeFrom(const MetricsConfigurationResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricsConfigurationResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void MetricsConfigurationResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricsConfigurationResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MetricsConfigurationResponse::CopyFrom(const MetricsConfigurationResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricsConfigurationResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MetricsConfigurationResponse::IsInitialized() const {
+  return true;
+}
+
+void MetricsConfigurationResponse::Swap(MetricsConfigurationResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MetricsConfigurationResponse::InternalSwap(MetricsConfigurationResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata MetricsConfigurationResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void MetricMetaData::InitAsDefaultInstance() {
+  ::dmi::_MetricMetaData_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+  ::dmi::_MetricMetaData_default_instance_._instance.get_mutable()->component_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class MetricMetaData::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const MetricMetaData* msg);
+  static const ::dmi::Uuid& component_uuid(const MetricMetaData* msg);
+};
+
+const ::dmi::Uuid&
+MetricMetaData::HasBitSetters::device_uuid(const MetricMetaData* msg) {
+  return *msg->device_uuid_;
+}
+const ::dmi::Uuid&
+MetricMetaData::HasBitSetters::component_uuid(const MetricMetaData* msg) {
+  return *msg->component_uuid_;
+}
+void MetricMetaData::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+void MetricMetaData::clear_component_uuid() {
+  if (GetArenaNoVirtual() == nullptr && component_uuid_ != nullptr) {
+    delete component_uuid_;
+  }
+  component_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MetricMetaData::kDeviceUuidFieldNumber;
+const int MetricMetaData::kComponentUuidFieldNumber;
+const int MetricMetaData::kComponentNameFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MetricMetaData::MetricMetaData()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.MetricMetaData)
+}
+MetricMetaData::MetricMetaData(const MetricMetaData& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  component_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.component_name().size() > 0) {
+    component_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.component_name_);
+  }
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  if (from.has_component_uuid()) {
+    component_uuid_ = new ::dmi::Uuid(*from.component_uuid_);
+  } else {
+    component_uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.MetricMetaData)
+}
+
+void MetricMetaData::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  component_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&device_uuid_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&component_uuid_) -
+      reinterpret_cast<char*>(&device_uuid_)) + sizeof(component_uuid_));
+}
+
+MetricMetaData::~MetricMetaData() {
+  // @@protoc_insertion_point(destructor:dmi.MetricMetaData)
+  SharedDtor();
+}
+
+void MetricMetaData::SharedDtor() {
+  component_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete device_uuid_;
+  if (this != internal_default_instance()) delete component_uuid_;
+}
+
+void MetricMetaData::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const MetricMetaData& MetricMetaData::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void MetricMetaData::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.MetricMetaData)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  component_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && component_uuid_ != nullptr) {
+    delete component_uuid_;
+  }
+  component_uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* MetricMetaData::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<MetricMetaData*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.Uuid component_uuid = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_component_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string component_name = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.MetricMetaData.component_name");
+        object = msg->mutable_component_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool MetricMetaData::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.MetricMetaData)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Uuid component_uuid = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_component_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string component_name = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_component_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->component_name().data(), static_cast<int>(this->component_name().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.MetricMetaData.component_name"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.MetricMetaData)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.MetricMetaData)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void MetricMetaData::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.MetricMetaData)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::component_uuid(this), output);
+  }
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->component_name().data(), static_cast<int>(this->component_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.MetricMetaData.component_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->component_name(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.MetricMetaData)
+}
+
+::google::protobuf::uint8* MetricMetaData::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricMetaData)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::component_uuid(this), target);
+  }
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->component_name().data(), static_cast<int>(this->component_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.MetricMetaData.component_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->component_name(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricMetaData)
+  return target;
+}
+
+size_t MetricMetaData::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.MetricMetaData)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->component_name());
+  }
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *component_uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void MetricMetaData::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricMetaData)
+  GOOGLE_DCHECK_NE(&from, this);
+  const MetricMetaData* source =
+      ::google::protobuf::DynamicCastToGenerated<MetricMetaData>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricMetaData)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricMetaData)
+    MergeFrom(*source);
+  }
+}
+
+void MetricMetaData::MergeFrom(const MetricMetaData& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricMetaData)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.component_name().size() > 0) {
+
+    component_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.component_name_);
+  }
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+  if (from.has_component_uuid()) {
+    mutable_component_uuid()->::dmi::Uuid::MergeFrom(from.component_uuid());
+  }
+}
+
+void MetricMetaData::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricMetaData)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MetricMetaData::CopyFrom(const MetricMetaData& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricMetaData)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MetricMetaData::IsInitialized() const {
+  return true;
+}
+
+void MetricMetaData::Swap(MetricMetaData* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MetricMetaData::InternalSwap(MetricMetaData* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  component_name_.Swap(&other->component_name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(device_uuid_, other->device_uuid_);
+  swap(component_uuid_, other->component_uuid_);
+}
+
+::google::protobuf::Metadata MetricMetaData::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void Metric::InitAsDefaultInstance() {
+  ::dmi::_Metric_default_instance_._instance.get_mutable()->metric_metadata_ = const_cast< ::dmi::MetricMetaData*>(
+      ::dmi::MetricMetaData::internal_default_instance());
+  ::dmi::_Metric_default_instance_._instance.get_mutable()->value_ = const_cast< ::dmi::ComponentSensorData*>(
+      ::dmi::ComponentSensorData::internal_default_instance());
+}
+class Metric::HasBitSetters {
+ public:
+  static const ::dmi::MetricMetaData& metric_metadata(const Metric* msg);
+  static const ::dmi::ComponentSensorData& value(const Metric* msg);
+};
+
+const ::dmi::MetricMetaData&
+Metric::HasBitSetters::metric_metadata(const Metric* msg) {
+  return *msg->metric_metadata_;
+}
+const ::dmi::ComponentSensorData&
+Metric::HasBitSetters::value(const Metric* msg) {
+  return *msg->value_;
+}
+void Metric::clear_value() {
+  if (GetArenaNoVirtual() == nullptr && value_ != nullptr) {
+    delete value_;
+  }
+  value_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Metric::kMetricIdFieldNumber;
+const int Metric::kMetricMetadataFieldNumber;
+const int Metric::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Metric::Metric()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.Metric)
+}
+Metric::Metric(const Metric& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_metric_metadata()) {
+    metric_metadata_ = new ::dmi::MetricMetaData(*from.metric_metadata_);
+  } else {
+    metric_metadata_ = nullptr;
+  }
+  if (from.has_value()) {
+    value_ = new ::dmi::ComponentSensorData(*from.value_);
+  } else {
+    value_ = nullptr;
+  }
+  metric_id_ = from.metric_id_;
+  // @@protoc_insertion_point(copy_constructor:dmi.Metric)
+}
+
+void Metric::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::memset(&metric_metadata_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&metric_id_) -
+      reinterpret_cast<char*>(&metric_metadata_)) + sizeof(metric_id_));
+}
+
+Metric::~Metric() {
+  // @@protoc_insertion_point(destructor:dmi.Metric)
+  SharedDtor();
+}
+
+void Metric::SharedDtor() {
+  if (this != internal_default_instance()) delete metric_metadata_;
+  if (this != internal_default_instance()) delete value_;
+}
+
+void Metric::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const Metric& Metric::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void Metric::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.Metric)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && metric_metadata_ != nullptr) {
+    delete metric_metadata_;
+  }
+  metric_metadata_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && value_ != nullptr) {
+    delete value_;
+  }
+  value_ = nullptr;
+  metric_id_ = 0;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* Metric::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<Metric*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.MetricNames metric_id = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_metric_id(static_cast<::dmi::MetricNames>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.MetricMetaData metric_metadata = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::MetricMetaData::_InternalParse;
+        object = msg->mutable_metric_metadata();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.ComponentSensorData value = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::ComponentSensorData::_InternalParse;
+        object = msg->mutable_value();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool Metric::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.Metric)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.MetricNames metric_id = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_metric_id(static_cast< ::dmi::MetricNames >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.MetricMetaData metric_metadata = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_metric_metadata()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ComponentSensorData value = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_value()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.Metric)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.Metric)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void Metric::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.Metric)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.MetricNames metric_id = 1;
+  if (this->metric_id() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->metric_id(), output);
+  }
+
+  // .dmi.MetricMetaData metric_metadata = 2;
+  if (this->has_metric_metadata()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::metric_metadata(this), output);
+  }
+
+  // .dmi.ComponentSensorData value = 3;
+  if (this->has_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::value(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.Metric)
+}
+
+::google::protobuf::uint8* Metric::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.Metric)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.MetricNames metric_id = 1;
+  if (this->metric_id() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->metric_id(), target);
+  }
+
+  // .dmi.MetricMetaData metric_metadata = 2;
+  if (this->has_metric_metadata()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::metric_metadata(this), target);
+  }
+
+  // .dmi.ComponentSensorData value = 3;
+  if (this->has_value()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::value(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.Metric)
+  return target;
+}
+
+size_t Metric::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.Metric)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.MetricMetaData metric_metadata = 2;
+  if (this->has_metric_metadata()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *metric_metadata_);
+  }
+
+  // .dmi.ComponentSensorData value = 3;
+  if (this->has_value()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *value_);
+  }
+
+  // .dmi.MetricNames metric_id = 1;
+  if (this->metric_id() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->metric_id());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void Metric::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.Metric)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Metric* source =
+      ::google::protobuf::DynamicCastToGenerated<Metric>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.Metric)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.Metric)
+    MergeFrom(*source);
+  }
+}
+
+void Metric::MergeFrom(const Metric& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.Metric)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_metric_metadata()) {
+    mutable_metric_metadata()->::dmi::MetricMetaData::MergeFrom(from.metric_metadata());
+  }
+  if (from.has_value()) {
+    mutable_value()->::dmi::ComponentSensorData::MergeFrom(from.value());
+  }
+  if (from.metric_id() != 0) {
+    set_metric_id(from.metric_id());
+  }
+}
+
+void Metric::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.Metric)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Metric::CopyFrom(const Metric& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.Metric)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Metric::IsInitialized() const {
+  return true;
+}
+
+void Metric::Swap(Metric* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Metric::InternalSwap(Metric* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(metric_metadata_, other->metric_metadata_);
+  swap(value_, other->value_);
+  swap(metric_id_, other->metric_id_);
+}
+
+::google::protobuf::Metadata Metric::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void GetMetricRequest::InitAsDefaultInstance() {
+  ::dmi::_GetMetricRequest_default_instance_._instance.get_mutable()->meta_data_ = const_cast< ::dmi::MetricMetaData*>(
+      ::dmi::MetricMetaData::internal_default_instance());
+}
+class GetMetricRequest::HasBitSetters {
+ public:
+  static const ::dmi::MetricMetaData& meta_data(const GetMetricRequest* msg);
+};
+
+const ::dmi::MetricMetaData&
+GetMetricRequest::HasBitSetters::meta_data(const GetMetricRequest* msg) {
+  return *msg->meta_data_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GetMetricRequest::kMetaDataFieldNumber;
+const int GetMetricRequest::kMetricIdFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GetMetricRequest::GetMetricRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.GetMetricRequest)
+}
+GetMetricRequest::GetMetricRequest(const GetMetricRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_meta_data()) {
+    meta_data_ = new ::dmi::MetricMetaData(*from.meta_data_);
+  } else {
+    meta_data_ = nullptr;
+  }
+  metric_id_ = from.metric_id_;
+  // @@protoc_insertion_point(copy_constructor:dmi.GetMetricRequest)
+}
+
+void GetMetricRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_GetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::memset(&meta_data_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&metric_id_) -
+      reinterpret_cast<char*>(&meta_data_)) + sizeof(metric_id_));
+}
+
+GetMetricRequest::~GetMetricRequest() {
+  // @@protoc_insertion_point(destructor:dmi.GetMetricRequest)
+  SharedDtor();
+}
+
+void GetMetricRequest::SharedDtor() {
+  if (this != internal_default_instance()) delete meta_data_;
+}
+
+void GetMetricRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const GetMetricRequest& GetMetricRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_GetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void GetMetricRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.GetMetricRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && meta_data_ != nullptr) {
+    delete meta_data_;
+  }
+  meta_data_ = nullptr;
+  metric_id_ = 0;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* GetMetricRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<GetMetricRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.MetricMetaData meta_data = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::MetricMetaData::_InternalParse;
+        object = msg->mutable_meta_data();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.MetricNames metric_id = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_metric_id(static_cast<::dmi::MetricNames>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool GetMetricRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.GetMetricRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.MetricMetaData meta_data = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_meta_data()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.MetricNames metric_id = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_metric_id(static_cast< ::dmi::MetricNames >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.GetMetricRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.GetMetricRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void GetMetricRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.GetMetricRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.MetricMetaData meta_data = 1;
+  if (this->has_meta_data()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::meta_data(this), output);
+  }
+
+  // .dmi.MetricNames metric_id = 2;
+  if (this->metric_id() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->metric_id(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.GetMetricRequest)
+}
+
+::google::protobuf::uint8* GetMetricRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetMetricRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.MetricMetaData meta_data = 1;
+  if (this->has_meta_data()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::meta_data(this), target);
+  }
+
+  // .dmi.MetricNames metric_id = 2;
+  if (this->metric_id() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->metric_id(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetMetricRequest)
+  return target;
+}
+
+size_t GetMetricRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.GetMetricRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.MetricMetaData meta_data = 1;
+  if (this->has_meta_data()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *meta_data_);
+  }
+
+  // .dmi.MetricNames metric_id = 2;
+  if (this->metric_id() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->metric_id());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void GetMetricRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetMetricRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const GetMetricRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<GetMetricRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetMetricRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetMetricRequest)
+    MergeFrom(*source);
+  }
+}
+
+void GetMetricRequest::MergeFrom(const GetMetricRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetMetricRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_meta_data()) {
+    mutable_meta_data()->::dmi::MetricMetaData::MergeFrom(from.meta_data());
+  }
+  if (from.metric_id() != 0) {
+    set_metric_id(from.metric_id());
+  }
+}
+
+void GetMetricRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetMetricRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GetMetricRequest::CopyFrom(const GetMetricRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.GetMetricRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetMetricRequest::IsInitialized() const {
+  return true;
+}
+
+void GetMetricRequest::Swap(GetMetricRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void GetMetricRequest::InternalSwap(GetMetricRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(meta_data_, other->meta_data_);
+  swap(metric_id_, other->metric_id_);
+}
+
+::google::protobuf::Metadata GetMetricRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void GetMetricResponse::InitAsDefaultInstance() {
+  ::dmi::_GetMetricResponse_default_instance_._instance.get_mutable()->metric_ = const_cast< ::dmi::Metric*>(
+      ::dmi::Metric::internal_default_instance());
+}
+class GetMetricResponse::HasBitSetters {
+ public:
+  static const ::dmi::Metric& metric(const GetMetricResponse* msg);
+};
+
+const ::dmi::Metric&
+GetMetricResponse::HasBitSetters::metric(const GetMetricResponse* msg) {
+  return *msg->metric_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GetMetricResponse::kStatusFieldNumber;
+const int GetMetricResponse::kReasonFieldNumber;
+const int GetMetricResponse::kMetricFieldNumber;
+const int GetMetricResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GetMetricResponse::GetMetricResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.GetMetricResponse)
+}
+GetMetricResponse::GetMetricResponse(const GetMetricResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_metric()) {
+    metric_ = new ::dmi::Metric(*from.metric_);
+  } else {
+    metric_ = nullptr;
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.GetMetricResponse)
+}
+
+void GetMetricResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_GetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&metric_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&metric_)) + sizeof(reason_));
+}
+
+GetMetricResponse::~GetMetricResponse() {
+  // @@protoc_insertion_point(destructor:dmi.GetMetricResponse)
+  SharedDtor();
+}
+
+void GetMetricResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete metric_;
+}
+
+void GetMetricResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const GetMetricResponse& GetMetricResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_GetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void GetMetricResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.GetMetricResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && metric_ != nullptr) {
+    delete metric_;
+  }
+  metric_ = nullptr;
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* GetMetricResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<GetMetricResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.GetMetricResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::GetMetricResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.Metric metric = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Metric::_InternalParse;
+        object = msg->mutable_metric();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.GetMetricResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool GetMetricResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.GetMetricResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.GetMetricResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::GetMetricResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Metric metric = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_metric()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.GetMetricResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.GetMetricResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.GetMetricResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void GetMetricResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.GetMetricResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.GetMetricResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // .dmi.Metric metric = 3;
+  if (this->has_metric()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::metric(this), output);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetMetricResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.GetMetricResponse)
+}
+
+::google::protobuf::uint8* GetMetricResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetMetricResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.GetMetricResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // .dmi.Metric metric = 3;
+  if (this->has_metric()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::metric(this), target);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetMetricResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetMetricResponse)
+  return target;
+}
+
+size_t GetMetricResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.GetMetricResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Metric metric = 3;
+  if (this->has_metric()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *metric_);
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.GetMetricResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void GetMetricResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetMetricResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const GetMetricResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<GetMetricResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetMetricResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetMetricResponse)
+    MergeFrom(*source);
+  }
+}
+
+void GetMetricResponse::MergeFrom(const GetMetricResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetMetricResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_metric()) {
+    mutable_metric()->::dmi::Metric::MergeFrom(from.metric());
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void GetMetricResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetMetricResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GetMetricResponse::CopyFrom(const GetMetricResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.GetMetricResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetMetricResponse::IsInitialized() const {
+  return true;
+}
+
+void GetMetricResponse::Swap(GetMetricResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void GetMetricResponse::InternalSwap(GetMetricResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(metric_, other->metric_);
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata GetMetricResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> PROTOBUF_NOINLINE ::dmi::MetricConfig* Arena::CreateMaybeMessage< ::dmi::MetricConfig >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::MetricConfig >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::MetricsConfig* Arena::CreateMaybeMessage< ::dmi::MetricsConfig >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::MetricsConfig >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ListMetricsResponse* Arena::CreateMaybeMessage< ::dmi::ListMetricsResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ListMetricsResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::MetricsConfigurationRequest* Arena::CreateMaybeMessage< ::dmi::MetricsConfigurationRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::MetricsConfigurationRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::MetricsConfigurationResponse* Arena::CreateMaybeMessage< ::dmi::MetricsConfigurationResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::MetricsConfigurationResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::MetricMetaData* Arena::CreateMaybeMessage< ::dmi::MetricMetaData >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::MetricMetaData >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::Metric* Arena::CreateMaybeMessage< ::dmi::Metric >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::Metric >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::GetMetricRequest* Arena::CreateMaybeMessage< ::dmi::GetMetricRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::GetMetricRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::GetMetricResponse* Arena::CreateMaybeMessage< ::dmi::GetMetricResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::GetMetricResponse >(arena);
+}
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+#include <google/protobuf/port_undef.inc>
