• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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