From a193adb70919f2ffb8e61edfb4d899b78ad5efeb Mon Sep 17 00:00:00 2001 From: Xiao Yu <fishx@google.com> Date: Thu, 18 Apr 2019 14:25:12 -0700 Subject: [PATCH] Refactor monitoring gauge and sampler API to an object-based API. PiperOrigin-RevId: 244258066 --- tensorflow/c/eager/c_api_experimental.cc | 406 +++++++++++++++--- tensorflow/c/eager/c_api_experimental.h | 187 +++++++- tensorflow/c/eager/c_api_experimental_test.cc | 111 ++++- tensorflow/c/eager/c_api_internal.h | 94 ++++ tensorflow/python/eager/BUILD | 4 +- tensorflow/python/eager/monitoring.py | 339 +++++++++++++-- tensorflow/python/eager/monitoring_test.py | 58 ++- tensorflow/python/pywrap_tfe.i | 48 ++- 8 files changed, 1124 insertions(+), 123 deletions(-) diff --git a/tensorflow/c/eager/c_api_experimental.cc b/tensorflow/c/eager/c_api_experimental.cc index 6cbd73fac0e..acf7e9c92d0 100644 --- a/tensorflow/c/eager/c_api_experimental.cc +++ b/tensorflow/c/eager/c_api_experimental.cc @@ -99,59 +99,6 @@ bool TFE_ProfilerClientStartTracing(const char* service_addr, return s.ok(); } -static tensorflow::mutex gauges_map_lock(tensorflow::LINKER_INITIALIZED); - -static std::unordered_map<string, - tensorflow::monitoring::Gauge<tensorflow::int64, 1>*>* -get_gauges_map() EXCLUSIVE_LOCKS_REQUIRED(gauges_map_lock) { - static std::unordered_map< - string, tensorflow::monitoring::Gauge<tensorflow::int64, 1>*>* - gauges_map = new std::unordered_map< - string, tensorflow::monitoring::Gauge<tensorflow::int64, 1>*>; - return gauges_map; -} - -static tensorflow::mutex samplers_map_lock(tensorflow::LINKER_INITIALIZED); - -static std::unordered_map<string, tensorflow::monitoring::Sampler<1>*>* -get_samplers_map() EXCLUSIVE_LOCKS_REQUIRED(samplers_map_lock) { - static std::unordered_map<string, tensorflow::monitoring::Sampler<1>*>* - samplers_map = - new std::unordered_map<string, tensorflow::monitoring::Sampler<1>*>; - return samplers_map; -} - -void TFE_MonitoringSetGauge(const char* name, const char* label, - int64_t value) { - tensorflow::mutex_lock l(gauges_map_lock); - auto gauges_map = get_gauges_map(); - if (gauges_map->find(name) == gauges_map->end()) { - gauges_map->emplace( - name, tensorflow::monitoring::Gauge<tensorflow::int64, 1>::New( - name, - tensorflow::strings::StrCat( - name, " :Gauge metric collected from Python API."), - "metric_descriptor")); - } - gauges_map->at(name)->GetCell(label)->Set(value); -} - -void TFE_MonitoringAddSampler(const char* name, const char* label, - double value) { - tensorflow::mutex_lock l(samplers_map_lock); - auto samplers_map = get_samplers_map(); - if (samplers_map->find(name) == samplers_map->end()) { - samplers_map->emplace( - name, tensorflow::monitoring::Sampler<1>::New( - {name, - tensorflow::strings::StrCat( - name, " :Counter metric collected from Python API."), - "metric_descriptor"}, - {tensorflow::monitoring::Buckets::Exponential(1, 2, 30)})); - } - samplers_map->at(name)->GetCell(label)->Add(value); -} - void TFE_MonitoringCounterCellIncrementBy(TFE_MonitoringCounterCell* cell, int64_t value) { cell->cell.IncrementBy(value); @@ -166,6 +113,10 @@ TFE_MonitoringCounter0* TFE_MonitoringNewCounter0(const char* name, const char* description) { auto* result = new TFE_MonitoringCounter0({name, description}); Set_TF_Status_from_Status(status, result->counter->GetStatus()); + if (!result->counter->GetStatus().ok()) { + delete result; + return nullptr; + } return result; } @@ -185,6 +136,10 @@ TFE_MonitoringCounter1* TFE_MonitoringNewCounter1(const char* name, const char* label1) { auto* result = new TFE_MonitoringCounter1({name, description, label1}); Set_TF_Status_from_Status(status, result->counter->GetStatus()); + if (!result->counter->GetStatus().ok()) { + delete result; + return nullptr; + } return result; } @@ -206,6 +161,10 @@ TFE_MonitoringCounter2* TFE_MonitoringNewCounter2(const char* name, auto* result = new TFE_MonitoringCounter2({name, description, label1, label2}); Set_TF_Status_from_Status(status, result->counter->GetStatus()); + if (!result->counter->GetStatus().ok()) { + delete result; + return nullptr; + } return result; } @@ -218,3 +177,344 @@ TFE_MonitoringCounterCell* TFE_MonitoringGetCellCounter2( return static_cast<TFE_MonitoringCounterCell*>( static_cast<void*>(counter->counter->GetCell(label1, label2))); } + +void TFE_MonitoringIntGaugeCellSet(TFE_MonitoringIntGaugeCell* cell, + int64_t value) { + cell->cell.Set(value); +} + +int64_t TFE_MonitoringIntGaugeCellValue(TFE_MonitoringIntGaugeCell* cell) { + return cell->cell.value(); +} + +TFE_MonitoringIntGauge0* TFE_MonitoringNewIntGauge0(const char* name, + TF_Status* status, + const char* description) { + auto* result = new TFE_MonitoringIntGauge0({name, description}); + Set_TF_Status_from_Status(status, result->gauge->GetStatus()); + if (!result->gauge->GetStatus().ok()) { + delete result; + return nullptr; + } + return result; +} + +void TFE_MonitoringDeleteIntGauge0(TFE_MonitoringIntGauge0* gauge) { + delete gauge; +} + +TFE_MonitoringIntGaugeCell* TFE_MonitoringGetCellIntGauge0( + TFE_MonitoringIntGauge0* gauge) { + return static_cast<TFE_MonitoringIntGaugeCell*>( + static_cast<void*>(gauge->gauge->GetCell())); +} + +TFE_MonitoringIntGauge1* TFE_MonitoringNewIntGauge1(const char* name, + TF_Status* status, + const char* description, + const char* label1) { + auto* result = new TFE_MonitoringIntGauge1({name, description, label1}); + Set_TF_Status_from_Status(status, result->gauge->GetStatus()); + if (!result->gauge->GetStatus().ok()) { + delete result; + return nullptr; + } + return result; +} + +void TFE_MonitoringDeleteIntGauge1(TFE_MonitoringIntGauge1* gauge) { + delete gauge; +} + +TFE_MonitoringIntGaugeCell* TFE_MonitoringGetCellIntGauge1( + TFE_MonitoringIntGauge1* gauge, const char* label1) { + return static_cast<TFE_MonitoringIntGaugeCell*>( + static_cast<void*>(gauge->gauge->GetCell(label1))); +} + +TFE_MonitoringIntGauge2* TFE_MonitoringNewIntGauge2(const char* name, + TF_Status* status, + const char* description, + const char* label1, + const char* label2) { + auto* result = + new TFE_MonitoringIntGauge2({name, description, label1, label2}); + Set_TF_Status_from_Status(status, result->gauge->GetStatus()); + if (!result->gauge->GetStatus().ok()) { + delete result; + return nullptr; + } + return result; +} + +void TFE_MonitoringDeleteIntGauge2(TFE_MonitoringIntGauge2* gauge) { + delete gauge; +} + +TFE_MonitoringIntGaugeCell* TFE_MonitoringGetCellIntGauge2( + TFE_MonitoringIntGauge2* gauge, const char* label1, const char* label2) { + return static_cast<TFE_MonitoringIntGaugeCell*>( + static_cast<void*>(gauge->gauge->GetCell(label1, label2))); +} + +void TFE_MonitoringStringGaugeCellSet(TFE_MonitoringStringGaugeCell* cell, + const char* value) { + cell->cell.Set({value}); +} + +const void TFE_MonitoringStringGaugeCellValue( + TFE_MonitoringStringGaugeCell* cell, TF_Buffer* buf) { + tensorflow::string value = cell->cell.value(); + void* data = tensorflow::port::Malloc(value.length()); + value.copy(static_cast<char*>(data), value.length(), 0); + buf->data = data; + buf->length = value.length(); + buf->data_deallocator = [](void* data, size_t length) { + tensorflow::port::Free(data); + }; +} + +TFE_MonitoringStringGauge0* TFE_MonitoringNewStringGauge0( + const char* name, TF_Status* status, const char* description) { + auto* result = new TFE_MonitoringStringGauge0({name, description}); + Set_TF_Status_from_Status(status, result->gauge->GetStatus()); + if (!result->gauge->GetStatus().ok()) { + delete result; + return nullptr; + } + return result; +} + +void TFE_MonitoringDeleteStringGauge0(TFE_MonitoringStringGauge0* gauge) { + delete gauge; +} + +TFE_MonitoringStringGaugeCell* TFE_MonitoringGetCellStringGauge0( + TFE_MonitoringStringGauge0* gauge) { + return static_cast<TFE_MonitoringStringGaugeCell*>( + static_cast<void*>(gauge->gauge->GetCell())); +} + +TFE_MonitoringStringGauge1* TFE_MonitoringNewStringGauge1( + const char* name, TF_Status* status, const char* description, + const char* label1) { + auto* result = new TFE_MonitoringStringGauge1({name, description, label1}); + Set_TF_Status_from_Status(status, result->gauge->GetStatus()); + if (!result->gauge->GetStatus().ok()) { + delete result; + return nullptr; + } + return result; +} + +void TFE_MonitoringDeleteStringGauge1(TFE_MonitoringStringGauge1* gauge) { + delete gauge; +} + +TFE_MonitoringStringGaugeCell* TFE_MonitoringGetCellStringGauge1( + TFE_MonitoringStringGauge1* gauge, const char* label1) { + return static_cast<TFE_MonitoringStringGaugeCell*>( + static_cast<void*>(gauge->gauge->GetCell(label1))); +} + +TFE_MonitoringStringGauge2* TFE_MonitoringNewStringGauge2( + const char* name, TF_Status* status, const char* description, + const char* label1, const char* label2) { + auto* result = + new TFE_MonitoringStringGauge2({name, description, label1, label2}); + Set_TF_Status_from_Status(status, result->gauge->GetStatus()); + if (!result->gauge->GetStatus().ok()) { + delete result; + return nullptr; + } + return result; +} + +void TFE_MonitoringDeleteStringGauge2(TFE_MonitoringStringGauge2* gauge) { + delete gauge; +} + +TFE_MonitoringStringGaugeCell* TFE_MonitoringGetCellStringGauge2( + TFE_MonitoringStringGauge2* gauge, const char* label1, const char* label2) { + return static_cast<TFE_MonitoringStringGaugeCell*>( + static_cast<void*>(gauge->gauge->GetCell(label1, label2))); +} + +void TFE_MonitoringBoolGaugeCellSet(TFE_MonitoringBoolGaugeCell* cell, + bool value) { + cell->cell.Set(value); +} + +bool TFE_MonitoringBoolGaugeCellValue(TFE_MonitoringBoolGaugeCell* cell) { + return cell->cell.value(); +} + +TFE_MonitoringBoolGauge0* TFE_MonitoringNewBoolGauge0(const char* name, + TF_Status* status, + const char* description) { + auto* result = new TFE_MonitoringBoolGauge0({name, description}); + Set_TF_Status_from_Status(status, result->gauge->GetStatus()); + if (!result->gauge->GetStatus().ok()) { + delete result; + return nullptr; + } + return result; +} + +void TFE_MonitoringDeleteBoolGauge0(TFE_MonitoringBoolGauge0* gauge) { + delete gauge; +} + +TFE_MonitoringBoolGaugeCell* TFE_MonitoringGetCellBoolGauge0( + TFE_MonitoringBoolGauge0* gauge) { + return static_cast<TFE_MonitoringBoolGaugeCell*>( + static_cast<void*>(gauge->gauge->GetCell())); +} + +TFE_MonitoringBoolGauge1* TFE_MonitoringNewBoolGauge1(const char* name, + TF_Status* status, + const char* description, + const char* label1) { + auto* result = new TFE_MonitoringBoolGauge1({name, description, label1}); + Set_TF_Status_from_Status(status, result->gauge->GetStatus()); + if (!result->gauge->GetStatus().ok()) { + delete result; + return nullptr; + } + return result; +} + +void TFE_MonitoringDeleteBoolGauge1(TFE_MonitoringBoolGauge1* gauge) { + delete gauge; +} + +TFE_MonitoringBoolGaugeCell* TFE_MonitoringGetCellBoolGauge1( + TFE_MonitoringBoolGauge1* gauge, const char* label1) { + return static_cast<TFE_MonitoringBoolGaugeCell*>( + static_cast<void*>(gauge->gauge->GetCell(label1))); +} + +TFE_MonitoringBoolGauge2* TFE_MonitoringNewBoolGauge2(const char* name, + TF_Status* status, + const char* description, + const char* label1, + const char* label2) { + auto* result = + new TFE_MonitoringBoolGauge2({name, description, label1, label2}); + Set_TF_Status_from_Status(status, result->gauge->GetStatus()); + if (!result->gauge->GetStatus().ok()) { + delete result; + return nullptr; + } + return result; +} + +void TFE_MonitoringDeleteBoolGauge2(TFE_MonitoringBoolGauge2* gauge) { + delete gauge; +} + +TFE_MonitoringBoolGaugeCell* TFE_MonitoringGetCellBoolGauge2( + TFE_MonitoringBoolGauge2* gauge, const char* label1, const char* label2) { + return static_cast<TFE_MonitoringBoolGaugeCell*>( + static_cast<void*>(gauge->gauge->GetCell(label1, label2))); +} + +void TFE_MonitoringSamplerCellAdd(TFE_MonitoringSamplerCell* cell, + double value) { + cell->cell.Add(value); +} + +void TFE_MonitoringSamplerCellValue(TFE_MonitoringSamplerCell* cell, + TF_Buffer* buf) { + string content; + cell->cell.value().SerializeToString(&content); + void* data = tensorflow::port::Malloc(content.length()); + content.copy(static_cast<char*>(data), content.length(), 0); + buf->data = data; + buf->length = content.length(); + buf->data_deallocator = [](void* data, size_t length) { + tensorflow::port::Free(data); + }; +} + +TFE_MonitoringBuckets* TFE_MonitoringNewExponentialBuckets(double scale, + double growth_factor, + int bucket_count) { + return new TFE_MonitoringBuckets([scale, growth_factor, bucket_count]() { + return tensorflow::monitoring::Buckets::Exponential(scale, growth_factor, + bucket_count); + }); +} + +void TFE_MonitoringDeleteBuckets(TFE_MonitoringBuckets* buckets) { + delete buckets; +} + +TFE_MonitoringSampler0* TFE_MonitoringNewSampler0( + const char* name, TFE_MonitoringBuckets* buckets, TF_Status* status, + const char* description) { + auto* result = new TFE_MonitoringSampler0( + {name, buckets->create_buckets(), description}); + Set_TF_Status_from_Status(status, result->sampler->GetStatus()); + if (!result->sampler->GetStatus().ok()) { + delete result; + return nullptr; + } + return result; +} + +void TFE_MonitoringDeleteSampler0(TFE_MonitoringSampler0* sampler) { + delete sampler; +} + +TFE_MonitoringSamplerCell* TFE_MonitoringGetCellSampler0( + TFE_MonitoringSampler0* sampler) { + return static_cast<TFE_MonitoringSamplerCell*>( + static_cast<void*>(sampler->sampler->GetCell())); +} + +TFE_MonitoringSampler1* TFE_MonitoringNewSampler1( + const char* name, TFE_MonitoringBuckets* buckets, TF_Status* status, + const char* description, const char* label1) { + auto* result = new TFE_MonitoringSampler1( + {name, buckets->create_buckets(), description, label1}); + Set_TF_Status_from_Status(status, result->sampler->GetStatus()); + if (!result->sampler->GetStatus().ok()) { + delete result; + return nullptr; + } + return result; +} + +void TFE_MonitoringDeleteSampler1(TFE_MonitoringSampler1* sampler) { + delete sampler; +} + +TFE_MonitoringSamplerCell* TFE_MonitoringGetCellSampler1( + TFE_MonitoringSampler1* sampler, const char* label1) { + return static_cast<TFE_MonitoringSamplerCell*>( + static_cast<void*>(sampler->sampler->GetCell(label1))); +} + +TFE_MonitoringSampler2* TFE_MonitoringNewSampler2( + const char* name, TFE_MonitoringBuckets* buckets, TF_Status* status, + const char* description, const char* label1, const char* label2) { + auto* result = new TFE_MonitoringSampler2( + {name, buckets->create_buckets(), description, label1, label2}); + Set_TF_Status_from_Status(status, result->sampler->GetStatus()); + if (!result->sampler->GetStatus().ok()) { + delete result; + return nullptr; + } + return result; +} + +void TFE_MonitoringDeleteSampler2(TFE_MonitoringSampler2* sampler) { + delete sampler; +} + +TFE_MonitoringSamplerCell* TFE_MonitoringGetCellSampler2( + TFE_MonitoringSampler2* sampler, const char* label1, const char* label2) { + return static_cast<TFE_MonitoringSamplerCell*>( + static_cast<void*>(sampler->sampler->GetCell(label1, label2))); +} diff --git a/tensorflow/c/eager/c_api_experimental.h b/tensorflow/c/eager/c_api_experimental.h index 11fed825d15..4dc57e1eec5 100644 --- a/tensorflow/c/eager/c_api_experimental.h +++ b/tensorflow/c/eager/c_api_experimental.h @@ -87,19 +87,7 @@ TF_CAPI_EXPORT extern bool TFE_ProfilerClientStartTracing( const char* service_addr, const char* logdir, const char* worker_list, bool include_dataset_ops, int duration_ms, int num_tracing_attempts); -// Set the value of a Gauge metric. If the metric with given name does not -// exist, it will create a new Gauge metric. Right now it only supports type -// int64, consider to add more type supports if needed. -TF_CAPI_EXPORT extern void TFE_MonitoringSetGauge(const char* name, - const char* label, - int64_t value); - -// Add the given value to a Sampler metric. If the metric with given name -// does not exist, it will create a new Sampler metric. -TF_CAPI_EXPORT extern void TFE_MonitoringAddSampler(const char* name, - const char* label, - double value); - +// TODO(fishx): Move these monitoring APIs into a separate file. // ----------------------------------------------------------------------------- // Monitoring Counter APIs. // These APIs de-templated monitoring Counter for swig. @@ -149,6 +137,179 @@ TF_CAPI_EXPORT extern void TFE_MonitoringDeleteCounter2( TF_CAPI_EXPORT extern TFE_MonitoringCounterCell* TFE_MonitoringGetCellCounter2( TFE_MonitoringCounter2* counter, const char* label1, const char* label2); +// ----------------------------------------------------------------------------- +// Monitoring Gauge APIs. +// These APIs de-templated monitoring Gauge for swig. + +typedef struct TFE_MonitoringIntGaugeCell TFE_MonitoringIntGaugeCell; + +// Atomically set the value of the cell. +TF_CAPI_EXPORT extern void TFE_MonitoringIntGaugeCellSet( + TFE_MonitoringIntGaugeCell* cell, int64_t value); + +// Retrieves the current value of the cell. +TF_CAPI_EXPORT extern int64_t TFE_MonitoringIntGaugeCellValue( + TFE_MonitoringIntGaugeCell* cell); + +// APIs for Int Gauge without label. +typedef struct TFE_MonitoringIntGauge0 TFE_MonitoringIntGauge0; +TF_CAPI_EXPORT extern TFE_MonitoringIntGauge0* TFE_MonitoringNewIntGauge0( + const char* name, TF_Status* out_status, const char* description); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteIntGauge0( + TFE_MonitoringIntGauge0* gauge); +TF_CAPI_EXPORT extern TFE_MonitoringIntGaugeCell* +TFE_MonitoringGetCellIntGauge0(TFE_MonitoringIntGauge0* gauge); + +// APIs for Int Gauge with 1 label. +typedef struct TFE_MonitoringIntGauge1 TFE_MonitoringIntGauge1; +TF_CAPI_EXPORT extern TFE_MonitoringIntGauge1* TFE_MonitoringNewIntGauge1( + const char* name, TF_Status* out_status, const char* description, + const char* label1); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteIntGauge1( + TFE_MonitoringIntGauge1* gauge); +TF_CAPI_EXPORT extern TFE_MonitoringIntGaugeCell* +TFE_MonitoringGetCellIntGauge1(TFE_MonitoringIntGauge1* gauge, + const char* label1); + +// APIs for Int Gauge with 2 label. +typedef struct TFE_MonitoringIntGauge2 TFE_MonitoringIntGauge2; +TF_CAPI_EXPORT extern TFE_MonitoringIntGauge2* TFE_MonitoringNewIntGauge2( + const char* name, TF_Status* out_status, const char* description, + const char* label1, const char* label2); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteIntGauge2( + TFE_MonitoringIntGauge2* gauge); +TF_CAPI_EXPORT extern TFE_MonitoringIntGaugeCell* +TFE_MonitoringGetCellIntGauge2(TFE_MonitoringIntGauge2* gauge, + const char* label1, const char* label2); + +typedef struct TFE_MonitoringStringGaugeCell TFE_MonitoringStringGaugeCell; +TF_CAPI_EXPORT extern void TFE_MonitoringStringGaugeCellSet( + TFE_MonitoringStringGaugeCell* cell, const char* value); +// Retrieves the string value and saves it in buffer. +TF_CAPI_EXPORT extern const void TFE_MonitoringStringGaugeCellValue( + TFE_MonitoringStringGaugeCell* cell, TF_Buffer* buf); + +// APIs for String Gauge without label. +typedef struct TFE_MonitoringStringGauge0 TFE_MonitoringStringGauge0; +TF_CAPI_EXPORT extern TFE_MonitoringStringGauge0* TFE_MonitoringNewStringGauge0( + const char* name, TF_Status* out_status, const char* description); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteStringGauge0( + TFE_MonitoringStringGauge0* gauge); +TF_CAPI_EXPORT extern TFE_MonitoringStringGaugeCell* +TFE_MonitoringGetCellStringGauge0(TFE_MonitoringStringGauge0* gauge); + +// APIs for String Gauge with 1 label. +typedef struct TFE_MonitoringStringGauge1 TFE_MonitoringStringGauge1; +TF_CAPI_EXPORT extern TFE_MonitoringStringGauge1* TFE_MonitoringNewStringGauge1( + const char* name, TF_Status* out_status, const char* description, + const char* label1); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteStringGauge1( + TFE_MonitoringStringGauge1* gauge); +TF_CAPI_EXPORT extern TFE_MonitoringStringGaugeCell* +TFE_MonitoringGetCellStringGauge1(TFE_MonitoringStringGauge1* gauge, + const char* label1); + +// APIs for String Gauge with 2 label. +typedef struct TFE_MonitoringStringGauge2 TFE_MonitoringStringGauge2; +TF_CAPI_EXPORT extern TFE_MonitoringStringGauge2* TFE_MonitoringNewStringGauge2( + const char* name, TF_Status* out_status, const char* description, + const char* label1, const char* label2); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteStringGauge2( + TFE_MonitoringStringGauge2* gauge); +TF_CAPI_EXPORT extern TFE_MonitoringStringGaugeCell* +TFE_MonitoringGetCellStringGauge2(TFE_MonitoringStringGauge2* gauge, + const char* label1, const char* label2); + +typedef struct TFE_MonitoringBoolGaugeCell TFE_MonitoringBoolGaugeCell; +TF_CAPI_EXPORT extern void TFE_MonitoringBoolGaugeCellSet( + TFE_MonitoringBoolGaugeCell* cell, bool value); +TF_CAPI_EXPORT extern bool TFE_MonitoringBoolGaugeCellValue( + TFE_MonitoringBoolGaugeCell* cell); + +// APIs for Bool Gauge without label. +typedef struct TFE_MonitoringBoolGauge0 TFE_MonitoringBoolGauge0; +TF_CAPI_EXPORT extern TFE_MonitoringBoolGauge0* TFE_MonitoringNewBoolGauge0( + const char* name, TF_Status* out_status, const char* description); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteBoolGauge0( + TFE_MonitoringBoolGauge0* gauge); +TF_CAPI_EXPORT extern TFE_MonitoringBoolGaugeCell* +TFE_MonitoringGetCellBoolGauge0(TFE_MonitoringBoolGauge0* gauge); + +// APIs for Bool Gauge with 1 label. +typedef struct TFE_MonitoringBoolGauge1 TFE_MonitoringBoolGauge1; +TF_CAPI_EXPORT extern TFE_MonitoringBoolGauge1* TFE_MonitoringNewBoolGauge1( + const char* name, TF_Status* out_status, const char* description, + const char* label1); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteBoolGauge1( + TFE_MonitoringBoolGauge1* gauge); +TF_CAPI_EXPORT extern TFE_MonitoringBoolGaugeCell* +TFE_MonitoringGetCellBoolGauge1(TFE_MonitoringBoolGauge1* gauge, + const char* label1); + +// APIs for Bool Gauge with 2 label. +typedef struct TFE_MonitoringBoolGauge2 TFE_MonitoringBoolGauge2; +TF_CAPI_EXPORT extern TFE_MonitoringBoolGauge2* TFE_MonitoringNewBoolGauge2( + const char* name, TF_Status* out_status, const char* description, + const char* label1, const char* label2); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteBoolGauge2( + TFE_MonitoringBoolGauge2* gauge); +TF_CAPI_EXPORT extern TFE_MonitoringBoolGaugeCell* +TFE_MonitoringGetCellBoolGauge2(TFE_MonitoringBoolGauge2* gauge, + const char* label1, const char* label2); + +// ----------------------------------------------------------------------------- +// Monitoring Sampler APIs. +// These APIs de-templated monitoring Sampler for swig. + +typedef struct TFE_MonitoringSamplerCell TFE_MonitoringSamplerCell; + +// Atomically add the value of the cell. +TF_CAPI_EXPORT extern void TFE_MonitoringSamplerCellAdd( + TFE_MonitoringSamplerCell* cell, double value); + +// Retrieves the current value of the cell. The return value is a HistogramProto +// saved in buffer. +TF_CAPI_EXPORT extern void TFE_MonitoringSamplerCellValue( + TFE_MonitoringSamplerCell* cell, TF_Buffer* buf); + +// APIs for sampler buckets +typedef struct TFE_MonitoringBuckets TFE_MonitoringBuckets; +TF_CAPI_EXPORT extern TFE_MonitoringBuckets* +TFE_MonitoringNewExponentialBuckets(double scale, double growth_factor, + int bucket_count); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteBuckets( + TFE_MonitoringBuckets* buckets); + +// APIs for Sampler without label. +typedef struct TFE_MonitoringSampler0 TFE_MonitoringSampler0; +TF_CAPI_EXPORT extern TFE_MonitoringSampler0* TFE_MonitoringNewSampler0( + const char* name, TFE_MonitoringBuckets* buckets, TF_Status* out_status, + const char* description); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteSampler0( + TFE_MonitoringSampler0* sampler); +TF_CAPI_EXPORT extern TFE_MonitoringSamplerCell* TFE_MonitoringGetCellSampler0( + TFE_MonitoringSampler0* sampler); + +// APIs for Sampler with 1 label. +typedef struct TFE_MonitoringSampler1 TFE_MonitoringSampler1; +TF_CAPI_EXPORT extern TFE_MonitoringSampler1* TFE_MonitoringNewSampler1( + const char* name, TFE_MonitoringBuckets* buckets, TF_Status* out_status, + const char* description, const char* label1); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteSampler1( + TFE_MonitoringSampler1* sampler); +TF_CAPI_EXPORT extern TFE_MonitoringSamplerCell* TFE_MonitoringGetCellSampler1( + TFE_MonitoringSampler1* sampler, const char* label1); + +// APIs for Sampler with 2 label. +typedef struct TFE_MonitoringSampler2 TFE_MonitoringSampler2; +TF_CAPI_EXPORT extern TFE_MonitoringSampler2* TFE_MonitoringNewSampler2( + const char* name, TFE_MonitoringBuckets* buckets, TF_Status* out_status, + const char* description, const char* label1, const char* label2); +TF_CAPI_EXPORT extern void TFE_MonitoringDeleteSampler2( + TFE_MonitoringSampler2* sampler); +TF_CAPI_EXPORT extern TFE_MonitoringSamplerCell* TFE_MonitoringGetCellSampler2( + TFE_MonitoringSampler2* sampler, const char* label1, const char* label2); + #ifdef __cplusplus } /* end extern "C" */ #endif diff --git a/tensorflow/c/eager/c_api_experimental_test.cc b/tensorflow/c/eager/c_api_experimental_test.cc index 3f45dd7679e..4e48a7591a9 100644 --- a/tensorflow/c/eager/c_api_experimental_test.cc +++ b/tensorflow/c/eager/c_api_experimental_test.cc @@ -131,23 +131,6 @@ TEST(CAPI, MultipleProfilerSession) { TFE_DeleteProfilerContext(profiler_context); } -TEST(CAPI, MonitoringSetGauge) { - TFE_MonitoringSetGauge("test/gauge", "label", 1); - auto* collection_registry = monitoring::CollectionRegistry::Default(); - monitoring::CollectionRegistry::CollectMetricsOptions options; - std::unique_ptr<monitoring::CollectedMetrics> metrics = - collection_registry->CollectMetrics(options); - - EXPECT_EQ("test/gauge", metrics->point_set_map.at("test/gauge")->metric_name); - EXPECT_EQ(1, - metrics->point_set_map.at("test/gauge")->points.at(0)->int64_value); - - TFE_MonitoringSetGauge("test/gauge", "label", 5); - metrics = collection_registry->CollectMetrics(options); - EXPECT_EQ(5, - metrics->point_set_map.at("test/gauge")->points.at(0)->int64_value); -} - TEST(CAPI, MonitoringCounter0) { TF_Status* status = TF_NewStatus(); auto* counter = @@ -200,8 +183,59 @@ TEST(CAPI, MonitoringCounterMultiple) { TFE_MonitoringDeleteCounter2(counter2); } -TEST(CAPI, MonitoringAddSampler) { - TFE_MonitoringAddSampler("test/sampler", "label", 1.0); +TEST(CAPI, MonitoringGauge0) { + TF_Status* status = TF_NewStatus(); + auto* gauge = TFE_MonitoringNewIntGauge0("test/gauge", status, "test"); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + auto* cell = TFE_MonitoringGetCellIntGauge0(gauge); + TFE_MonitoringIntGaugeCellSet(cell, 1); + EXPECT_EQ(TFE_MonitoringIntGaugeCellValue(cell), 1); + auto* collection_registry = monitoring::CollectionRegistry::Default(); + monitoring::CollectionRegistry::CollectMetricsOptions options; + std::unique_ptr<monitoring::CollectedMetrics> metrics = + collection_registry->CollectMetrics(options); + + EXPECT_EQ("test/gauge", metrics->point_set_map.at("test/gauge")->metric_name); + EXPECT_EQ(1, + metrics->point_set_map.at("test/gauge")->points.at(0)->int64_value); + + TFE_MonitoringIntGaugeCellSet(cell, 5); + metrics = collection_registry->CollectMetrics(options); + EXPECT_EQ(5, + metrics->point_set_map.at("test/gauge")->points.at(0)->int64_value); + TF_DeleteStatus(status); +} + +TEST(CAPI, MonitoringMultipleGauge) { + TF_Status* status = TF_NewStatus(); + auto* gauge1 = + TFE_MonitoringNewBoolGauge1("test/gauge1", status, "test", "label1"); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + auto* cell1 = TFE_MonitoringGetCellBoolGauge1(gauge1, "foo"); + TFE_MonitoringBoolGaugeCellSet(cell1, true); + EXPECT_TRUE(TFE_MonitoringBoolGaugeCellValue(cell1)); + + auto* gauge2 = TFE_MonitoringNewStringGauge2("test/gauge2", status, "test", + "label1", "label2"); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + auto* cell2 = TFE_MonitoringGetCellStringGauge2(gauge2, "foo", "bar"); + TFE_MonitoringStringGaugeCellSet(cell2, "str"); + auto* buf = new TF_Buffer; + TFE_MonitoringStringGaugeCellValue(cell2, buf); + string data(static_cast<const char*>(buf->data), buf->length); + delete buf; + EXPECT_EQ(data, "str"); + TF_DeleteStatus(status); +} + +TEST(CAPI, MonitoringSampler0) { + TF_Status* status = TF_NewStatus(); + auto* buckets = TFE_MonitoringNewExponentialBuckets(1.0, 2.0, 2); + auto* sampler = + TFE_MonitoringNewSampler0("test/sampler", buckets, status, "test"); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + auto* cell = TFE_MonitoringGetCellSampler0(sampler); + TFE_MonitoringSamplerCellAdd(cell, 1.0); auto* collection_registry = monitoring::CollectionRegistry::Default(); monitoring::CollectionRegistry::CollectMetricsOptions options; std::unique_ptr<monitoring::CollectedMetrics> metrics = @@ -213,11 +247,48 @@ TEST(CAPI, MonitoringAddSampler) { ->points.at(0) ->histogram_value.sum()); - TFE_MonitoringAddSampler("test/sampler", "label", 5.0); + TFE_MonitoringSamplerCellAdd(cell, 5.0); metrics = collection_registry->CollectMetrics(options); EXPECT_EQ(6.0, metrics->point_set_map.at("test/sampler") ->points.at(0) ->histogram_value.sum()); + TFE_MonitoringDeleteBuckets(buckets); + TF_DeleteStatus(status); +} + +TEST(CAPI, MonitoringMultipleSampler) { + TF_Status* status = TF_NewStatus(); + auto* buckets = TFE_MonitoringNewExponentialBuckets(1.0, 2.0, 2); + auto* sampler1 = TFE_MonitoringNewSampler1("test/sampler1", buckets, status, + "test", "label1"); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + auto* cell1 = TFE_MonitoringGetCellSampler1(sampler1, "foo"); + TFE_MonitoringSamplerCellAdd(cell1, 1.0); + TFE_MonitoringSamplerCellAdd(cell1, 2.0); + TF_Buffer* result1 = TF_NewBuffer(); + TFE_MonitoringSamplerCellValue(cell1, result1); + tensorflow::HistogramProto hitogram1; + EXPECT_TRUE(hitogram1.ParseFromString( + {reinterpret_cast<const char*>(result1->data), result1->length})); + EXPECT_EQ(hitogram1.sum(), 3.0); + delete result1; + + auto* sampler2 = TFE_MonitoringNewSampler2("test/sampler2", buckets, status, + "test", "label1", "label2"); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + auto* cell2 = TFE_MonitoringGetCellSampler2(sampler2, "foo", "bar"); + TFE_MonitoringSamplerCellAdd(cell2, 2.0); + TFE_MonitoringSamplerCellAdd(cell2, 3.0); + TF_Buffer* result2 = TF_NewBuffer(); + TFE_MonitoringSamplerCellValue(cell2, result2); + tensorflow::HistogramProto hitogram2; + EXPECT_TRUE(hitogram2.ParseFromString( + {reinterpret_cast<const char*>(result2->data), result2->length})); + EXPECT_EQ(hitogram2.sum(), 5.0); + delete result2; + + TFE_MonitoringDeleteBuckets(buckets); + TF_DeleteStatus(status); } } // namespace diff --git a/tensorflow/c/eager/c_api_internal.h b/tensorflow/c/eager/c_api_internal.h index 30711086168..f8ba50fda2e 100644 --- a/tensorflow/c/eager/c_api_internal.h +++ b/tensorflow/c/eager/c_api_internal.h @@ -50,6 +50,8 @@ limitations under the License. #include "tensorflow/core/lib/gtl/map_util.h" #include "tensorflow/core/lib/gtl/stl_util.h" #include "tensorflow/core/lib/monitoring/counter.h" +#include "tensorflow/core/lib/monitoring/gauge.h" +#include "tensorflow/core/lib/monitoring/sampler.h" #include "tensorflow/core/platform/mutex.h" #include "tensorflow/core/platform/thread_annotations.h" #include "tensorflow/core/profiler/lib/profiler_session.h" @@ -159,6 +161,98 @@ struct TFE_MonitoringCounter2 : TFE_MonitoringCounter<2> { using TFE_MonitoringCounter::TFE_MonitoringCounter; }; +struct TFE_MonitoringIntGaugeCell { + tensorflow::monitoring::GaugeCell<tensorflow::int64> cell; +}; +struct TFE_MonitoringStringGaugeCell { + tensorflow::monitoring::GaugeCell<tensorflow::string> cell; +}; +struct TFE_MonitoringBoolGaugeCell { + tensorflow::monitoring::GaugeCell<bool> cell; +}; + +template <typename ValueType, int NumLabels> +struct TFE_MonitoringGauge { + template <typename... LabelDesc> + TFE_MonitoringGauge(const char* name, const char* description, + LabelDesc&&... label) { + gauge = absl::WrapUnique( + tensorflow::monitoring::Gauge<ValueType, NumLabels>::New( + name, description, label...)); + } + + std::unique_ptr<tensorflow::monitoring::Gauge<ValueType, NumLabels>> gauge; +}; + +struct TFE_MonitoringIntGauge0 : TFE_MonitoringGauge<tensorflow::int64, 0> { + using TFE_MonitoringGauge::TFE_MonitoringGauge; +}; +struct TFE_MonitoringIntGauge1 : TFE_MonitoringGauge<tensorflow::int64, 1> { + using TFE_MonitoringGauge::TFE_MonitoringGauge; +}; +struct TFE_MonitoringIntGauge2 : TFE_MonitoringGauge<tensorflow::int64, 2> { + using TFE_MonitoringGauge::TFE_MonitoringGauge; +}; + +struct TFE_MonitoringStringGauge0 : TFE_MonitoringGauge<tensorflow::string, 0> { + using TFE_MonitoringGauge::TFE_MonitoringGauge; +}; +struct TFE_MonitoringStringGauge1 : TFE_MonitoringGauge<tensorflow::string, 1> { + using TFE_MonitoringGauge::TFE_MonitoringGauge; +}; +struct TFE_MonitoringStringGauge2 : TFE_MonitoringGauge<tensorflow::string, 2> { + using TFE_MonitoringGauge::TFE_MonitoringGauge; +}; + +struct TFE_MonitoringBoolGauge0 : TFE_MonitoringGauge<bool, 0> { + using TFE_MonitoringGauge::TFE_MonitoringGauge; +}; +struct TFE_MonitoringBoolGauge1 : TFE_MonitoringGauge<bool, 1> { + using TFE_MonitoringGauge::TFE_MonitoringGauge; +}; +struct TFE_MonitoringBoolGauge2 : TFE_MonitoringGauge<bool, 2> { + using TFE_MonitoringGauge::TFE_MonitoringGauge; +}; + +struct TFE_MonitoringBuckets { + TFE_MonitoringBuckets( + std::function<std::unique_ptr<tensorflow::monitoring::Buckets>(void)> + fn) { + create_buckets = fn; + } + + std::function<std::unique_ptr<tensorflow::monitoring::Buckets>(void)> + create_buckets; +}; + +struct TFE_MonitoringSamplerCell { + tensorflow::monitoring::SamplerCell cell; +}; + +template <int NumLabels> +struct TFE_MonitoringSampler { + template <typename... LabelDesc> + TFE_MonitoringSampler( + const char* name, + std::unique_ptr<tensorflow::monitoring::Buckets> buckets, + const char* description, LabelDesc&&... label) { + sampler = absl::WrapUnique(tensorflow::monitoring::Sampler<NumLabels>::New( + {name, description, label...}, std::move(buckets))); + } + + std::unique_ptr<tensorflow::monitoring::Sampler<NumLabels>> sampler; +}; + +struct TFE_MonitoringSampler0 : TFE_MonitoringSampler<0> { + using TFE_MonitoringSampler::TFE_MonitoringSampler; +}; +struct TFE_MonitoringSampler1 : TFE_MonitoringSampler<1> { + using TFE_MonitoringSampler::TFE_MonitoringSampler; +}; +struct TFE_MonitoringSampler2 : TFE_MonitoringSampler<2> { + using TFE_MonitoringSampler::TFE_MonitoringSampler; +}; + namespace tensorflow { // Set an AttrValue on the op. Doesn't handle the list types. void SetOpAttrValueScalar(TFE_Context* ctx, TFE_Op* op, diff --git a/tensorflow/python/eager/BUILD b/tensorflow/python/eager/BUILD index 17d038348e8..458ac15df22 100644 --- a/tensorflow/python/eager/BUILD +++ b/tensorflow/python/eager/BUILD @@ -1,6 +1,6 @@ licenses(["notice"]) # Apache 2.0 -load("//tensorflow:tensorflow.bzl", "tf_py_test", "tf_cc_binary") +load("//tensorflow:tensorflow.bzl", "tf_py_test") load("//tensorflow:tensorflow.bzl", "cuda_py_test") load( "//tensorflow/tools/test:performance.bzl", @@ -102,7 +102,9 @@ py_library( srcs_version = "PY2AND3", visibility = ["//tensorflow:internal"], deps = [ + "//tensorflow/python:c_api_util", "//tensorflow/python:pywrap_tensorflow", + "//tensorflow/python:util", ], ) diff --git a/tensorflow/python/eager/monitoring.py b/tensorflow/python/eager/monitoring.py index 335c2fdea57..fd4717f7905 100644 --- a/tensorflow/python/eager/monitoring.py +++ b/tensorflow/python/eager/monitoring.py @@ -20,7 +20,10 @@ from __future__ import print_function import collections +from tensorflow.core.framework import summary_pb2 from tensorflow.python import pywrap_tensorflow +from tensorflow.python.framework import c_api_util +from tensorflow.python.util import compat _MetricMethod = collections.namedtuple('MetricMethod', 'create delete get_cell') _counter_methods = [ @@ -37,32 +40,62 @@ _counter_methods = [ delete=pywrap_tensorflow.TFE_MonitoringDeleteCounter2, get_cell=pywrap_tensorflow.TFE_MonitoringGetCellCounter2), ] - - -def gauge(name, label, value): - """Set the value of a Gauge metric. - - If the metric with this name does not exist, it will create a new metric. - - Args: - name: metric name - label: long label - value: a int64 value - """ - pywrap_tensorflow.TFE_MonitoringSetGauge(name, label, value) - - -def sampler(name, label, value): - """Add the value of a Sampler metric. - - If the metric with this name does not exist, it will create a new metric. - - Args: - name: metric name - label: metric label - value: a double value - """ - pywrap_tensorflow.TFE_MonitoringAddSampler(name, label, value) +_int_gauge_methods = [ + _MetricMethod( + create=pywrap_tensorflow.TFE_MonitoringNewIntGauge0, + delete=pywrap_tensorflow.TFE_MonitoringDeleteIntGauge0, + get_cell=pywrap_tensorflow.TFE_MonitoringGetCellIntGauge0), + _MetricMethod( + create=pywrap_tensorflow.TFE_MonitoringNewIntGauge1, + delete=pywrap_tensorflow.TFE_MonitoringDeleteIntGauge1, + get_cell=pywrap_tensorflow.TFE_MonitoringGetCellIntGauge1), + _MetricMethod( + create=pywrap_tensorflow.TFE_MonitoringNewIntGauge2, + delete=pywrap_tensorflow.TFE_MonitoringDeleteIntGauge2, + get_cell=pywrap_tensorflow.TFE_MonitoringGetCellIntGauge2), +] +_string_gauge_methods = [ + _MetricMethod( + create=pywrap_tensorflow.TFE_MonitoringNewStringGauge0, + delete=pywrap_tensorflow.TFE_MonitoringDeleteStringGauge0, + get_cell=pywrap_tensorflow.TFE_MonitoringGetCellStringGauge0), + _MetricMethod( + create=pywrap_tensorflow.TFE_MonitoringNewStringGauge1, + delete=pywrap_tensorflow.TFE_MonitoringDeleteStringGauge1, + get_cell=pywrap_tensorflow.TFE_MonitoringGetCellStringGauge1), + _MetricMethod( + create=pywrap_tensorflow.TFE_MonitoringNewStringGauge2, + delete=pywrap_tensorflow.TFE_MonitoringDeleteStringGauge2, + get_cell=pywrap_tensorflow.TFE_MonitoringGetCellStringGauge2), +] +_bool_gauge_methods = [ + _MetricMethod( + create=pywrap_tensorflow.TFE_MonitoringNewBoolGauge0, + delete=pywrap_tensorflow.TFE_MonitoringDeleteBoolGauge0, + get_cell=pywrap_tensorflow.TFE_MonitoringGetCellBoolGauge0), + _MetricMethod( + create=pywrap_tensorflow.TFE_MonitoringNewBoolGauge1, + delete=pywrap_tensorflow.TFE_MonitoringDeleteBoolGauge1, + get_cell=pywrap_tensorflow.TFE_MonitoringGetCellBoolGauge1), + _MetricMethod( + create=pywrap_tensorflow.TFE_MonitoringNewBoolGauge2, + delete=pywrap_tensorflow.TFE_MonitoringDeleteBoolGauge2, + get_cell=pywrap_tensorflow.TFE_MonitoringGetCellBoolGauge2), +] +_sampler_methods = [ + _MetricMethod( + create=pywrap_tensorflow.TFE_MonitoringNewSampler0, + delete=pywrap_tensorflow.TFE_MonitoringDeleteSampler0, + get_cell=pywrap_tensorflow.TFE_MonitoringGetCellSampler0), + _MetricMethod( + create=pywrap_tensorflow.TFE_MonitoringNewSampler1, + delete=pywrap_tensorflow.TFE_MonitoringDeleteSampler1, + get_cell=pywrap_tensorflow.TFE_MonitoringGetCellSampler1), + _MetricMethod( + create=pywrap_tensorflow.TFE_MonitoringNewSampler2, + delete=pywrap_tensorflow.TFE_MonitoringDeleteSampler2, + get_cell=pywrap_tensorflow.TFE_MonitoringGetCellSampler2), +] class Metric(object): @@ -88,7 +121,8 @@ class Metric(object): self._metric = self._metric_methods[self._label_length].create(*args) def __del__(self): - self._metric_methods[self._label_length].delete(self._metric) + if hasattr(self, '_metric'): + self._metric_methods[self._label_length].delete(self._metric) def get_cell(self, *labels): """Retrieves the cell.""" @@ -124,7 +158,12 @@ class CounterCell(object): class Counter(Metric): - """A stateful class for updating a cumulative integer metric.""" + """A stateful class for updating a cumulative integer metric. + + This class encapsulates a set of values (or a single value for a label-less + metric). Each value is identified by a tuple of labels. The class allows the + user to increment each value. + """ def __init__(self, name, description, *labels): """Creates a new Counter. @@ -132,7 +171,7 @@ class Counter(Metric): Args: name: name of the new metric. description: description of the new metric. - *labels: The label list of the new metrics + *labels: The label list of the new metric. """ super(Counter, self).__init__('Counter', _counter_methods, len(labels), name, description, *labels) @@ -140,3 +179,245 @@ class Counter(Metric): def get_cell(self, *labels): """Retrieves the cell.""" return CounterCell(super(Counter, self).get_cell(*labels)) + + +class IntGaugeCell(object): + """A single integer value stored in an `IntGauge`.""" + + def __init__(self, cell): + """Creates a new IntGaugeCell. + + Args: + cell: A c pointer of TFE_MonitoringIntGaugeCell. + """ + self._cell = cell + + def set(self, value): + """Atomically set the value. + + Args: + value: integer value. + """ + pywrap_tensorflow.TFE_MonitoringIntGaugeCellSet(self._cell, value) + + def value(self): + """Retrieves the current value.""" + return pywrap_tensorflow.TFE_MonitoringIntGaugeCellValue(self._cell) + + +class IntGauge(Metric): + """A stateful class for updating a gauge-like integer metric. + + This class encapsulates a set of integer values (or a single value for a + label-less metric). Each value is identified by a tuple of labels. The class + allows the user to set each value. + """ + + def __init__(self, name, description, *labels): + """Creates a new IntGauge. + + Args: + name: name of the new metric. + description: description of the new metric. + *labels: The label list of the new metric. + """ + super(IntGauge, self).__init__('IntGauge', _int_gauge_methods, len(labels), + name, description, *labels) + + def get_cell(self, *labels): + """Retrieves the cell.""" + return IntGaugeCell(super(IntGauge, self).get_cell(*labels)) + + +class StringGaugeCell(object): + """A single string value stored in an `StringGauge`.""" + + def __init__(self, cell): + """Creates a new StringGaugeCell. + + Args: + cell: A c pointer of TFE_MonitoringStringGaugeCell. + """ + self._cell = cell + + def set(self, value): + """Atomically set the value. + + Args: + value: string value. + """ + pywrap_tensorflow.TFE_MonitoringStringGaugeCellSet(self._cell, value) + + def value(self): + """Retrieves the current value.""" + with c_api_util.tf_buffer() as buffer_: + pywrap_tensorflow.TFE_MonitoringStringGaugeCellValue(self._cell, buffer_) + value = pywrap_tensorflow.TF_GetBuffer(buffer_).decode('utf-8') + return value + + +class StringGauge(Metric): + """A stateful class for updating a gauge-like string metric. + + This class encapsulates a set of string values (or a single value for a + label-less metric). Each value is identified by a tuple of labels. The class + allows the user to set each value. + """ + + def __init__(self, name, description, *labels): + """Creates a new StringGauge. + + Args: + name: name of the new metric. + description: description of the new metric. + *labels: The label list of the new metric. + """ + super(StringGauge, self).__init__('StringGauge', _string_gauge_methods, + len(labels), name, description, *labels) + + def get_cell(self, *labels): + """Retrieves the cell.""" + return StringGaugeCell(super(StringGauge, self).get_cell(*labels)) + + +class BoolGaugeCell(object): + """A single boolean value stored in an `BoolGauge`.""" + + def __init__(self, cell): + """Creates a new BoolGaugeCell. + + Args: + cell: A c pointer of TFE_MonitoringBoolGaugeCell. + """ + self._cell = cell + + def set(self, value): + """Atomically set the value. + + Args: + value: bool value. + """ + pywrap_tensorflow.TFE_MonitoringBoolGaugeCellSet(self._cell, value) + + def value(self): + """Retrieves the current value.""" + return pywrap_tensorflow.TFE_MonitoringBoolGaugeCellValue(self._cell) + + +class BoolGauge(Metric): + """A stateful class for updating a gauge-like bool metric. + + This class encapsulates a set of boolean values (or a single value for a + label-less metric). Each value is identified by a tuple of labels. The class + allows the user to set each value. + """ + + def __init__(self, name, description, *labels): + """Creates a new BoolGauge. + + Args: + name: name of the new metric. + description: description of the new metric. + *labels: The label list of the new metric. + """ + super(BoolGauge, self).__init__('BoolGauge', _bool_gauge_methods, + len(labels), name, description, *labels) + + def get_cell(self, *labels): + """Retrieves the cell.""" + return BoolGaugeCell(super(BoolGauge, self).get_cell(*labels)) + + +class SamplerCell(object): + """SamplerCell stores each value of a Sampler.""" + + def __init__(self, cell): + """Creates a new SamplerCell. + + Args: + cell: A c pointer of TFE_MonitoringSamplerCell. + """ + self._cell = cell + + def add(self, value): + """Atomically add a sample. + + Args: + value: float value. + """ + pywrap_tensorflow.TFE_MonitoringSamplerCellAdd(self._cell, value) + + def value(self): + """Retrieves the current distribution of samples. + + Returns: + A HistogramProto describing the distribution of samples. + """ + with c_api_util.tf_buffer() as buffer_: + pywrap_tensorflow.TFE_MonitoringSamplerCellValue(self._cell, buffer_) + proto_data = pywrap_tensorflow.TF_GetBuffer(buffer_) + histogram_proto = summary_pb2.HistogramProto() + histogram_proto.ParseFromString(compat.as_bytes(proto_data)) + return histogram_proto + + +class Buckets(object): + """Bucketing strategies for the samplers.""" + + def __init__(self, buckets): + """Creates a new Buckets. + + Args: + buckets: A c pointer of TFE_MonitoringBuckets. + """ + self.buckets = buckets + + def __del__(self): + pywrap_tensorflow.TFE_MonitoringDeleteBuckets(self.buckets) + + +class ExponentialBuckets(Buckets): + """Exponential bucketing strategy. + + Sets up buckets of the form: + [-DBL_MAX, ..., scale * growth^i, + scale * growth_factor^(i + 1), ..., DBL_MAX]. + """ + + def __init__(self, scale, growth_factor, bucket_count): + """Creates a new exponential Buckets. + + Args: + scale: float + growth_factor: float + bucket_count: integer + """ + super(ExponentialBuckets, self).__init__( + pywrap_tensorflow.TFE_MonitoringNewExponentialBuckets( + scale, growth_factor, bucket_count)) + + +class Sampler(Metric): + """A stateful class for updating a cumulative histogram metric. + + This class encapsulates a set of histograms (or a single histogram for a + label-less metric) configured with a list of increasing bucket boundaries. + Each histogram is identified by a tuple of labels. The class allows the + user to add a sample to each histogram value. + """ + + def __init__(self, name, buckets, description, *labels): + """Creates a new Sampler. + + Args: + name: name of the new metric. + buckets: bucketing strategy of the new metric. + description: description of the new metric. + *labels: The label list of the new metric. + """ + super(Sampler, self).__init__('Sampler', _sampler_methods, len(labels), + name, buckets.buckets, description, *labels) + + def get_cell(self, *labels): + """Retrieves the cell.""" + return SamplerCell(super(Sampler, self).get_cell(*labels)) diff --git a/tensorflow/python/eager/monitoring_test.py b/tensorflow/python/eager/monitoring_test.py index cc3ef39ba3d..3f601735ef2 100644 --- a/tensorflow/python/eager/monitoring_test.py +++ b/tensorflow/python/eager/monitoring_test.py @@ -26,11 +26,6 @@ from tensorflow.python.framework import test_util class MonitoringTest(test_util.TensorFlowTestCase): - def test_monitoring(self): - # These methods should not throw any exception. - monitoring.gauge('test/gauge', 'label', 1) - monitoring.sampler('test/sampler', 'label', 1.0) - def test_counter(self): counter = monitoring.Counter('test/counter', 'test counter') counter.get_cell().increase_by(1) @@ -52,6 +47,59 @@ class MonitoringTest(test_util.TensorFlowTestCase): with self.assertRaises(errors.AlreadyExistsError): counter2 = monitoring.Counter('test/same_counter', 'test counter') # pylint: disable=unused-variable + def test_int_gauge(self): + gauge = monitoring.IntGauge('test/gauge', 'test gauge') + gauge.get_cell().set(1) + self.assertEqual(gauge.get_cell().value(), 1) + gauge.get_cell().set(5) + self.assertEqual(gauge.get_cell().value(), 5) + + gauge1 = monitoring.IntGauge('test/gauge1', 'test gauge1', 'label1') + gauge1.get_cell('foo').set(2) + self.assertEqual(gauge1.get_cell('foo').value(), 2) + + def test_string_gauge(self): + gauge = monitoring.StringGauge('test/gauge', 'test gauge') + gauge.get_cell().set('left') + self.assertEqual(gauge.get_cell().value(), 'left') + gauge.get_cell().set('right') + self.assertEqual(gauge.get_cell().value(), 'right') + + gauge1 = monitoring.StringGauge('test/gauge1', 'test gauge1', 'label1') + gauge1.get_cell('foo').set('start') + self.assertEqual(gauge1.get_cell('foo').value(), 'start') + + def test_bool_gauge(self): + gauge = monitoring.BoolGauge('test/gauge', 'test gauge') + gauge.get_cell().set(True) + self.assertTrue(gauge.get_cell().value()) + gauge.get_cell().set(False) + self.assertFalse(gauge.get_cell().value()) + + gauge1 = monitoring.BoolGauge('test/gauge1', 'test gauge1', 'label1') + gauge1.get_cell('foo').set(True) + self.assertTrue(gauge1.get_cell('foo').value()) + + def test_sampler(self): + buckets = monitoring.ExponentialBuckets(1.0, 2.0, 2) + sampler = monitoring.Sampler('test/sampler', buckets, 'test sampler') + sampler.get_cell().add(1.0) + sampler.get_cell().add(5.0) + histogram_proto = sampler.get_cell().value() + self.assertEqual(histogram_proto.min, 1.0) + self.assertEqual(histogram_proto.num, 2.0) + self.assertEqual(histogram_proto.sum, 6.0) + + sampler1 = monitoring.Sampler('test/sampler1', buckets, 'test sampler', + 'label1') + sampler1.get_cell('foo').add(2.0) + sampler1.get_cell('foo').add(4.0) + sampler1.get_cell('bar').add(8.0) + histogram_proto1 = sampler1.get_cell('foo').value() + self.assertEqual(histogram_proto1.max, 4.0) + self.assertEqual(histogram_proto1.num, 2.0) + self.assertEqual(histogram_proto1.sum, 6.0) + if __name__ == '__main__': test.main() diff --git a/tensorflow/python/pywrap_tfe.i b/tensorflow/python/pywrap_tfe.i index f3810a00f45..09cf06aea00 100755 --- a/tensorflow/python/pywrap_tfe.i +++ b/tensorflow/python/pywrap_tfe.i @@ -84,8 +84,6 @@ limitations under the License. %rename("%s") TFE_EnableCollectiveOps; %rename("%s") TF_ListPhysicalDevices; %rename("%s") TF_PickUnusedPortOrDie; -%rename("%s") TFE_MonitoringSetGauge; -%rename("%s") TFE_MonitoringAddSampler; %rename("%s") TFE_MonitoringCounterCellIncrementBy; %rename("%s") TFE_MonitoringCounterCellValue; %rename("%s") TFE_MonitoringNewCounter0; @@ -97,6 +95,52 @@ limitations under the License. %rename("%s") TFE_MonitoringNewCounter2; %rename("%s") TFE_MonitoringDeleteCounter2; %rename("%s") TFE_MonitoringGetCellCounter2; +%rename("%s") TFE_MonitoringIntGaugeCellSet; +%rename("%s") TFE_MonitoringIntGaugeCellValue; +%rename("%s") TFE_MonitoringNewIntGauge0; +%rename("%s") TFE_MonitoringDeleteIntGauge0; +%rename("%s") TFE_MonitoringGetCellIntGauge0; +%rename("%s") TFE_MonitoringNewIntGauge1; +%rename("%s") TFE_MonitoringDeleteIntGauge1; +%rename("%s") TFE_MonitoringGetCellIntGauge1; +%rename("%s") TFE_MonitoringNewIntGauge2; +%rename("%s") TFE_MonitoringDeleteIntGauge2; +%rename("%s") TFE_MonitoringGetCellIntGauge2; +%rename("%s") TFE_MonitoringStringGaugeCellSet; +%rename("%s") TFE_MonitoringStringGaugeCellValue; +%rename("%s") TFE_MonitoringNewStringGauge0; +%rename("%s") TFE_MonitoringDeleteStringGauge0; +%rename("%s") TFE_MonitoringGetCellStringGauge0; +%rename("%s") TFE_MonitoringNewStringGauge1; +%rename("%s") TFE_MonitoringDeleteStringGauge1; +%rename("%s") TFE_MonitoringGetCellStringGauge1; +%rename("%s") TFE_MonitoringNewStringGauge2; +%rename("%s") TFE_MonitoringDeleteStringGauge2; +%rename("%s") TFE_MonitoringGetCellStringGauge2; +%rename("%s") TFE_MonitoringBoolGaugeCellSet; +%rename("%s") TFE_MonitoringBoolGaugeCellValue; +%rename("%s") TFE_MonitoringNewBoolGauge0; +%rename("%s") TFE_MonitoringDeleteBoolGauge0; +%rename("%s") TFE_MonitoringGetCellBoolGauge0; +%rename("%s") TFE_MonitoringNewBoolGauge1; +%rename("%s") TFE_MonitoringDeleteBoolGauge1; +%rename("%s") TFE_MonitoringGetCellBoolGauge1; +%rename("%s") TFE_MonitoringNewBoolGauge2; +%rename("%s") TFE_MonitoringDeleteBoolGauge2; +%rename("%s") TFE_MonitoringGetCellBoolGauge2; +%rename("%s") TFE_MonitoringSamplerCellAdd; +%rename("%s") TFE_MonitoringSamplerCellValue; +%rename("%s") TFE_MonitoringNewExponentialBuckets; +%rename("%s") TFE_MonitoringDeleteBuckets; +%rename("%s") TFE_MonitoringNewSampler0; +%rename("%s") TFE_MonitoringDeleteSampler0; +%rename("%s") TFE_MonitoringGetCellSampler0; +%rename("%s") TFE_MonitoringNewSampler1; +%rename("%s") TFE_MonitoringDeleteSampler1; +%rename("%s") TFE_MonitoringGetCellSampler1; +%rename("%s") TFE_MonitoringNewSampler2; +%rename("%s") TFE_MonitoringDeleteSampler2; +%rename("%s") TFE_MonitoringGetCellSampler2; %{ #include "tensorflow/python/eager/pywrap_tfe.h"