1# Copyright 2017 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15"""TensorFlow monitoring APIs.""" 16 17from __future__ import absolute_import 18from __future__ import division 19from __future__ import print_function 20 21import collections 22 23from tensorflow.core.framework import summary_pb2 24from tensorflow.python import pywrap_tfe 25from tensorflow.python.client import pywrap_tf_session 26from tensorflow.python.framework import c_api_util 27from tensorflow.python.util import compat 28 29_MetricMethod = collections.namedtuple('MetricMethod', 'create delete get_cell') 30_counter_methods = [ 31 _MetricMethod( 32 create=pywrap_tfe.TFE_MonitoringNewCounter0, 33 delete=pywrap_tfe.TFE_MonitoringDeleteCounter0, 34 get_cell=pywrap_tfe.TFE_MonitoringGetCellCounter0), 35 _MetricMethod( 36 create=pywrap_tfe.TFE_MonitoringNewCounter1, 37 delete=pywrap_tfe.TFE_MonitoringDeleteCounter1, 38 get_cell=pywrap_tfe.TFE_MonitoringGetCellCounter1), 39 _MetricMethod( 40 create=pywrap_tfe.TFE_MonitoringNewCounter2, 41 delete=pywrap_tfe.TFE_MonitoringDeleteCounter2, 42 get_cell=pywrap_tfe.TFE_MonitoringGetCellCounter2), 43] 44_int_gauge_methods = [ 45 _MetricMethod( 46 create=pywrap_tfe.TFE_MonitoringNewIntGauge0, 47 delete=pywrap_tfe.TFE_MonitoringDeleteIntGauge0, 48 get_cell=pywrap_tfe.TFE_MonitoringGetCellIntGauge0), 49 _MetricMethod( 50 create=pywrap_tfe.TFE_MonitoringNewIntGauge1, 51 delete=pywrap_tfe.TFE_MonitoringDeleteIntGauge1, 52 get_cell=pywrap_tfe.TFE_MonitoringGetCellIntGauge1), 53 _MetricMethod( 54 create=pywrap_tfe.TFE_MonitoringNewIntGauge2, 55 delete=pywrap_tfe.TFE_MonitoringDeleteIntGauge2, 56 get_cell=pywrap_tfe.TFE_MonitoringGetCellIntGauge2), 57] 58_string_gauge_methods = [ 59 _MetricMethod( 60 create=pywrap_tfe.TFE_MonitoringNewStringGauge0, 61 delete=pywrap_tfe.TFE_MonitoringDeleteStringGauge0, 62 get_cell=pywrap_tfe.TFE_MonitoringGetCellStringGauge0), 63 _MetricMethod( 64 create=pywrap_tfe.TFE_MonitoringNewStringGauge1, 65 delete=pywrap_tfe.TFE_MonitoringDeleteStringGauge1, 66 get_cell=pywrap_tfe.TFE_MonitoringGetCellStringGauge1), 67 _MetricMethod( 68 create=pywrap_tfe.TFE_MonitoringNewStringGauge2, 69 delete=pywrap_tfe.TFE_MonitoringDeleteStringGauge2, 70 get_cell=pywrap_tfe.TFE_MonitoringGetCellStringGauge2), 71] 72_bool_gauge_methods = [ 73 _MetricMethod( 74 create=pywrap_tfe.TFE_MonitoringNewBoolGauge0, 75 delete=pywrap_tfe.TFE_MonitoringDeleteBoolGauge0, 76 get_cell=pywrap_tfe.TFE_MonitoringGetCellBoolGauge0), 77 _MetricMethod( 78 create=pywrap_tfe.TFE_MonitoringNewBoolGauge1, 79 delete=pywrap_tfe.TFE_MonitoringDeleteBoolGauge1, 80 get_cell=pywrap_tfe.TFE_MonitoringGetCellBoolGauge1), 81 _MetricMethod( 82 create=pywrap_tfe.TFE_MonitoringNewBoolGauge2, 83 delete=pywrap_tfe.TFE_MonitoringDeleteBoolGauge2, 84 get_cell=pywrap_tfe.TFE_MonitoringGetCellBoolGauge2), 85] 86_sampler_methods = [ 87 _MetricMethod( 88 create=pywrap_tfe.TFE_MonitoringNewSampler0, 89 delete=pywrap_tfe.TFE_MonitoringDeleteSampler0, 90 get_cell=pywrap_tfe.TFE_MonitoringGetCellSampler0), 91 _MetricMethod( 92 create=pywrap_tfe.TFE_MonitoringNewSampler1, 93 delete=pywrap_tfe.TFE_MonitoringDeleteSampler1, 94 get_cell=pywrap_tfe.TFE_MonitoringGetCellSampler1), 95 _MetricMethod( 96 create=pywrap_tfe.TFE_MonitoringNewSampler2, 97 delete=pywrap_tfe.TFE_MonitoringDeleteSampler2, 98 get_cell=pywrap_tfe.TFE_MonitoringGetCellSampler2), 99] 100 101 102class Metric(object): 103 """The base class of metric.""" 104 105 def __init__(self, metric_name, metric_methods, label_length, *args): 106 """Creates a new metric. 107 108 Args: 109 metric_name: name of the metric class. 110 metric_methods: list of swig metric methods. 111 label_length: length of label args. 112 *args: the arguments to call create method. 113 """ 114 self._metric_name = metric_name 115 self._metric_methods = metric_methods 116 self._label_length = label_length 117 118 if label_length >= len(self._metric_methods): 119 raise ValueError('Cannot create {} metric with label >= {}'.format( 120 self._metric_name, len(self._metric_methods))) 121 122 self._metric = self._metric_methods[self._label_length].create(*args) 123 124 def __del__(self): 125 try: 126 deleter = self._metric_methods[self._label_length].delete 127 metric = self._metric 128 except AttributeError: 129 return 130 131 if deleter is not None: 132 deleter(metric) 133 134 def get_cell(self, *labels): 135 """Retrieves the cell.""" 136 if len(labels) != self._label_length: 137 raise ValueError('The {} expects taking {} labels'.format( 138 self._metric_name, self._label_length)) 139 return self._metric_methods[self._label_length].get_cell( 140 self._metric, *labels) 141 142 143class CounterCell(object): 144 """CounterCell stores each value of a Counter.""" 145 146 def __init__(self, cell): 147 """Creates a new CounterCell. 148 149 Args: 150 cell: A c pointer of TFE_MonitoringCounterCell. 151 """ 152 self._cell = cell 153 154 def increase_by(self, value): 155 """Atomically increments the value. 156 157 Args: 158 value: non-negative value. 159 """ 160 pywrap_tfe.TFE_MonitoringCounterCellIncrementBy(self._cell, value) 161 162 def value(self): 163 """Retrieves the current value.""" 164 return pywrap_tfe.TFE_MonitoringCounterCellValue(self._cell) 165 166 167class Counter(Metric): 168 """A stateful class for updating a cumulative integer metric. 169 170 This class encapsulates a set of values (or a single value for a label-less 171 metric). Each value is identified by a tuple of labels. The class allows the 172 user to increment each value. 173 """ 174 175 def __init__(self, name, description, *labels): 176 """Creates a new Counter. 177 178 Args: 179 name: name of the new metric. 180 description: description of the new metric. 181 *labels: The label list of the new metric. 182 """ 183 super(Counter, self).__init__('Counter', _counter_methods, len(labels), 184 name, description, *labels) 185 186 def get_cell(self, *labels): 187 """Retrieves the cell.""" 188 return CounterCell(super(Counter, self).get_cell(*labels)) 189 190 191class IntGaugeCell(object): 192 """A single integer value stored in an `IntGauge`.""" 193 194 def __init__(self, cell): 195 """Creates a new IntGaugeCell. 196 197 Args: 198 cell: A c pointer of TFE_MonitoringIntGaugeCell. 199 """ 200 self._cell = cell 201 202 def set(self, value): 203 """Atomically set the value. 204 205 Args: 206 value: integer value. 207 """ 208 pywrap_tfe.TFE_MonitoringIntGaugeCellSet(self._cell, value) 209 210 def value(self): 211 """Retrieves the current value.""" 212 return pywrap_tfe.TFE_MonitoringIntGaugeCellValue(self._cell) 213 214 215class IntGauge(Metric): 216 """A stateful class for updating a gauge-like integer metric. 217 218 This class encapsulates a set of integer values (or a single value for a 219 label-less metric). Each value is identified by a tuple of labels. The class 220 allows the user to set each value. 221 """ 222 223 def __init__(self, name, description, *labels): 224 """Creates a new IntGauge. 225 226 Args: 227 name: name of the new metric. 228 description: description of the new metric. 229 *labels: The label list of the new metric. 230 """ 231 super(IntGauge, self).__init__('IntGauge', _int_gauge_methods, len(labels), 232 name, description, *labels) 233 234 def get_cell(self, *labels): 235 """Retrieves the cell.""" 236 return IntGaugeCell(super(IntGauge, self).get_cell(*labels)) 237 238 239class StringGaugeCell(object): 240 """A single string value stored in an `StringGauge`.""" 241 242 def __init__(self, cell): 243 """Creates a new StringGaugeCell. 244 245 Args: 246 cell: A c pointer of TFE_MonitoringStringGaugeCell. 247 """ 248 self._cell = cell 249 250 def set(self, value): 251 """Atomically set the value. 252 253 Args: 254 value: string value. 255 """ 256 pywrap_tfe.TFE_MonitoringStringGaugeCellSet(self._cell, value) 257 258 def value(self): 259 """Retrieves the current value.""" 260 with c_api_util.tf_buffer() as buffer_: 261 pywrap_tfe.TFE_MonitoringStringGaugeCellValue(self._cell, buffer_) 262 value = pywrap_tf_session.TF_GetBuffer(buffer_).decode('utf-8') 263 return value 264 265 266class StringGauge(Metric): 267 """A stateful class for updating a gauge-like string metric. 268 269 This class encapsulates a set of string values (or a single value for a 270 label-less metric). Each value is identified by a tuple of labels. The class 271 allows the user to set each value. 272 """ 273 274 def __init__(self, name, description, *labels): 275 """Creates a new StringGauge. 276 277 Args: 278 name: name of the new metric. 279 description: description of the new metric. 280 *labels: The label list of the new metric. 281 """ 282 super(StringGauge, self).__init__('StringGauge', _string_gauge_methods, 283 len(labels), name, description, *labels) 284 285 def get_cell(self, *labels): 286 """Retrieves the cell.""" 287 return StringGaugeCell(super(StringGauge, self).get_cell(*labels)) 288 289 290class BoolGaugeCell(object): 291 """A single boolean value stored in an `BoolGauge`.""" 292 293 def __init__(self, cell): 294 """Creates a new BoolGaugeCell. 295 296 Args: 297 cell: A c pointer of TFE_MonitoringBoolGaugeCell. 298 """ 299 self._cell = cell 300 301 def set(self, value): 302 """Atomically set the value. 303 304 Args: 305 value: bool value. 306 """ 307 pywrap_tfe.TFE_MonitoringBoolGaugeCellSet(self._cell, value) 308 309 def value(self): 310 """Retrieves the current value.""" 311 return pywrap_tfe.TFE_MonitoringBoolGaugeCellValue(self._cell) 312 313 314class BoolGauge(Metric): 315 """A stateful class for updating a gauge-like bool metric. 316 317 This class encapsulates a set of boolean values (or a single value for a 318 label-less metric). Each value is identified by a tuple of labels. The class 319 allows the user to set each value. 320 """ 321 322 def __init__(self, name, description, *labels): 323 """Creates a new BoolGauge. 324 325 Args: 326 name: name of the new metric. 327 description: description of the new metric. 328 *labels: The label list of the new metric. 329 """ 330 super(BoolGauge, self).__init__('BoolGauge', _bool_gauge_methods, 331 len(labels), name, description, *labels) 332 333 def get_cell(self, *labels): 334 """Retrieves the cell.""" 335 return BoolGaugeCell(super(BoolGauge, self).get_cell(*labels)) 336 337 338class SamplerCell(object): 339 """SamplerCell stores each value of a Sampler.""" 340 341 def __init__(self, cell): 342 """Creates a new SamplerCell. 343 344 Args: 345 cell: A c pointer of TFE_MonitoringSamplerCell. 346 """ 347 self._cell = cell 348 349 def add(self, value): 350 """Atomically add a sample. 351 352 Args: 353 value: float value. 354 """ 355 pywrap_tfe.TFE_MonitoringSamplerCellAdd(self._cell, value) 356 357 def value(self): 358 """Retrieves the current distribution of samples. 359 360 Returns: 361 A HistogramProto describing the distribution of samples. 362 """ 363 with c_api_util.tf_buffer() as buffer_: 364 pywrap_tfe.TFE_MonitoringSamplerCellValue(self._cell, buffer_) 365 proto_data = pywrap_tf_session.TF_GetBuffer(buffer_) 366 histogram_proto = summary_pb2.HistogramProto() 367 histogram_proto.ParseFromString(compat.as_bytes(proto_data)) 368 return histogram_proto 369 370 371class Buckets(object): 372 """Bucketing strategies for the samplers.""" 373 374 def __init__(self, buckets): 375 """Creates a new Buckets. 376 377 Args: 378 buckets: A c pointer of TFE_MonitoringBuckets. 379 """ 380 self.buckets = buckets 381 382 def __del__(self): 383 pywrap_tfe.TFE_MonitoringDeleteBuckets(self.buckets) 384 385 386class ExponentialBuckets(Buckets): 387 """Exponential bucketing strategy. 388 389 Sets up buckets of the form: 390 [-DBL_MAX, ..., scale * growth^i, 391 scale * growth_factor^(i + 1), ..., DBL_MAX]. 392 """ 393 394 def __init__(self, scale, growth_factor, bucket_count): 395 """Creates a new exponential Buckets. 396 397 Args: 398 scale: float 399 growth_factor: float 400 bucket_count: integer 401 """ 402 super(ExponentialBuckets, self).__init__( 403 pywrap_tfe.TFE_MonitoringNewExponentialBuckets(scale, growth_factor, 404 bucket_count)) 405 406 407class Sampler(Metric): 408 """A stateful class for updating a cumulative histogram metric. 409 410 This class encapsulates a set of histograms (or a single histogram for a 411 label-less metric) configured with a list of increasing bucket boundaries. 412 Each histogram is identified by a tuple of labels. The class allows the 413 user to add a sample to each histogram value. 414 """ 415 416 def __init__(self, name, buckets, description, *labels): 417 """Creates a new Sampler. 418 419 Args: 420 name: name of the new metric. 421 buckets: bucketing strategy of the new metric. 422 description: description of the new metric. 423 *labels: The label list of the new metric. 424 """ 425 super(Sampler, self).__init__('Sampler', _sampler_methods, len(labels), 426 name, buckets.buckets, description, *labels) 427 428 def get_cell(self, *labels): 429 """Retrieves the cell.""" 430 return SamplerCell(super(Sampler, self).get_cell(*labels)) 431