tensorbored 2.21.0rc1769983804__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. tensorbored/__init__.py +112 -0
  2. tensorbored/_vendor/__init__.py +0 -0
  3. tensorbored/_vendor/bleach/__init__.py +125 -0
  4. tensorbored/_vendor/bleach/_vendor/__init__.py +0 -0
  5. tensorbored/_vendor/bleach/_vendor/html5lib/__init__.py +35 -0
  6. tensorbored/_vendor/bleach/_vendor/html5lib/_ihatexml.py +289 -0
  7. tensorbored/_vendor/bleach/_vendor/html5lib/_inputstream.py +918 -0
  8. tensorbored/_vendor/bleach/_vendor/html5lib/_tokenizer.py +1735 -0
  9. tensorbored/_vendor/bleach/_vendor/html5lib/_trie/__init__.py +5 -0
  10. tensorbored/_vendor/bleach/_vendor/html5lib/_trie/_base.py +40 -0
  11. tensorbored/_vendor/bleach/_vendor/html5lib/_trie/py.py +67 -0
  12. tensorbored/_vendor/bleach/_vendor/html5lib/_utils.py +159 -0
  13. tensorbored/_vendor/bleach/_vendor/html5lib/constants.py +2946 -0
  14. tensorbored/_vendor/bleach/_vendor/html5lib/filters/__init__.py +0 -0
  15. tensorbored/_vendor/bleach/_vendor/html5lib/filters/alphabeticalattributes.py +29 -0
  16. tensorbored/_vendor/bleach/_vendor/html5lib/filters/base.py +12 -0
  17. tensorbored/_vendor/bleach/_vendor/html5lib/filters/inject_meta_charset.py +73 -0
  18. tensorbored/_vendor/bleach/_vendor/html5lib/filters/lint.py +93 -0
  19. tensorbored/_vendor/bleach/_vendor/html5lib/filters/optionaltags.py +207 -0
  20. tensorbored/_vendor/bleach/_vendor/html5lib/filters/sanitizer.py +916 -0
  21. tensorbored/_vendor/bleach/_vendor/html5lib/filters/whitespace.py +38 -0
  22. tensorbored/_vendor/bleach/_vendor/html5lib/html5parser.py +2795 -0
  23. tensorbored/_vendor/bleach/_vendor/html5lib/serializer.py +409 -0
  24. tensorbored/_vendor/bleach/_vendor/html5lib/treeadapters/__init__.py +30 -0
  25. tensorbored/_vendor/bleach/_vendor/html5lib/treeadapters/genshi.py +54 -0
  26. tensorbored/_vendor/bleach/_vendor/html5lib/treeadapters/sax.py +50 -0
  27. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/__init__.py +88 -0
  28. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/base.py +417 -0
  29. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/dom.py +239 -0
  30. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/etree.py +343 -0
  31. tensorbored/_vendor/bleach/_vendor/html5lib/treebuilders/etree_lxml.py +392 -0
  32. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/__init__.py +154 -0
  33. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/base.py +252 -0
  34. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/dom.py +43 -0
  35. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/etree.py +131 -0
  36. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/etree_lxml.py +215 -0
  37. tensorbored/_vendor/bleach/_vendor/html5lib/treewalkers/genshi.py +69 -0
  38. tensorbored/_vendor/bleach/_vendor/parse.py +1078 -0
  39. tensorbored/_vendor/bleach/callbacks.py +32 -0
  40. tensorbored/_vendor/bleach/html5lib_shim.py +757 -0
  41. tensorbored/_vendor/bleach/linkifier.py +633 -0
  42. tensorbored/_vendor/bleach/parse_shim.py +1 -0
  43. tensorbored/_vendor/bleach/sanitizer.py +638 -0
  44. tensorbored/_vendor/bleach/six_shim.py +19 -0
  45. tensorbored/_vendor/webencodings/__init__.py +342 -0
  46. tensorbored/_vendor/webencodings/labels.py +231 -0
  47. tensorbored/_vendor/webencodings/mklabels.py +59 -0
  48. tensorbored/_vendor/webencodings/x_user_defined.py +325 -0
  49. tensorbored/assets.py +36 -0
  50. tensorbored/auth.py +102 -0
  51. tensorbored/backend/__init__.py +0 -0
  52. tensorbored/backend/application.py +604 -0
  53. tensorbored/backend/auth_context_middleware.py +38 -0
  54. tensorbored/backend/client_feature_flags.py +113 -0
  55. tensorbored/backend/empty_path_redirect.py +46 -0
  56. tensorbored/backend/event_processing/__init__.py +0 -0
  57. tensorbored/backend/event_processing/data_ingester.py +276 -0
  58. tensorbored/backend/event_processing/data_provider.py +535 -0
  59. tensorbored/backend/event_processing/directory_loader.py +142 -0
  60. tensorbored/backend/event_processing/directory_watcher.py +272 -0
  61. tensorbored/backend/event_processing/event_accumulator.py +950 -0
  62. tensorbored/backend/event_processing/event_file_inspector.py +463 -0
  63. tensorbored/backend/event_processing/event_file_loader.py +292 -0
  64. tensorbored/backend/event_processing/event_multiplexer.py +521 -0
  65. tensorbored/backend/event_processing/event_util.py +68 -0
  66. tensorbored/backend/event_processing/io_wrapper.py +223 -0
  67. tensorbored/backend/event_processing/plugin_asset_util.py +104 -0
  68. tensorbored/backend/event_processing/plugin_event_accumulator.py +721 -0
  69. tensorbored/backend/event_processing/plugin_event_multiplexer.py +522 -0
  70. tensorbored/backend/event_processing/reservoir.py +266 -0
  71. tensorbored/backend/event_processing/tag_types.py +29 -0
  72. tensorbored/backend/experiment_id.py +71 -0
  73. tensorbored/backend/experimental_plugin.py +51 -0
  74. tensorbored/backend/http_util.py +263 -0
  75. tensorbored/backend/json_util.py +70 -0
  76. tensorbored/backend/path_prefix.py +67 -0
  77. tensorbored/backend/process_graph.py +74 -0
  78. tensorbored/backend/security_validator.py +202 -0
  79. tensorbored/compat/__init__.py +69 -0
  80. tensorbored/compat/proto/__init__.py +0 -0
  81. tensorbored/compat/proto/allocation_description_pb2.py +35 -0
  82. tensorbored/compat/proto/api_def_pb2.py +82 -0
  83. tensorbored/compat/proto/attr_value_pb2.py +80 -0
  84. tensorbored/compat/proto/cluster_pb2.py +58 -0
  85. tensorbored/compat/proto/config_pb2.py +271 -0
  86. tensorbored/compat/proto/coordination_config_pb2.py +45 -0
  87. tensorbored/compat/proto/cost_graph_pb2.py +87 -0
  88. tensorbored/compat/proto/cpp_shape_inference_pb2.py +70 -0
  89. tensorbored/compat/proto/debug_pb2.py +65 -0
  90. tensorbored/compat/proto/event_pb2.py +149 -0
  91. tensorbored/compat/proto/full_type_pb2.py +74 -0
  92. tensorbored/compat/proto/function_pb2.py +157 -0
  93. tensorbored/compat/proto/graph_debug_info_pb2.py +111 -0
  94. tensorbored/compat/proto/graph_pb2.py +41 -0
  95. tensorbored/compat/proto/histogram_pb2.py +39 -0
  96. tensorbored/compat/proto/meta_graph_pb2.py +254 -0
  97. tensorbored/compat/proto/node_def_pb2.py +61 -0
  98. tensorbored/compat/proto/op_def_pb2.py +81 -0
  99. tensorbored/compat/proto/resource_handle_pb2.py +48 -0
  100. tensorbored/compat/proto/rewriter_config_pb2.py +93 -0
  101. tensorbored/compat/proto/rpc_options_pb2.py +35 -0
  102. tensorbored/compat/proto/saved_object_graph_pb2.py +193 -0
  103. tensorbored/compat/proto/saver_pb2.py +38 -0
  104. tensorbored/compat/proto/step_stats_pb2.py +116 -0
  105. tensorbored/compat/proto/struct_pb2.py +144 -0
  106. tensorbored/compat/proto/summary_pb2.py +111 -0
  107. tensorbored/compat/proto/tensor_description_pb2.py +38 -0
  108. tensorbored/compat/proto/tensor_pb2.py +68 -0
  109. tensorbored/compat/proto/tensor_shape_pb2.py +46 -0
  110. tensorbored/compat/proto/tfprof_log_pb2.py +307 -0
  111. tensorbored/compat/proto/trackable_object_graph_pb2.py +90 -0
  112. tensorbored/compat/proto/types_pb2.py +105 -0
  113. tensorbored/compat/proto/variable_pb2.py +62 -0
  114. tensorbored/compat/proto/verifier_config_pb2.py +38 -0
  115. tensorbored/compat/proto/versions_pb2.py +35 -0
  116. tensorbored/compat/tensorflow_stub/__init__.py +38 -0
  117. tensorbored/compat/tensorflow_stub/app.py +124 -0
  118. tensorbored/compat/tensorflow_stub/compat/__init__.py +131 -0
  119. tensorbored/compat/tensorflow_stub/compat/v1/__init__.py +20 -0
  120. tensorbored/compat/tensorflow_stub/dtypes.py +692 -0
  121. tensorbored/compat/tensorflow_stub/error_codes.py +169 -0
  122. tensorbored/compat/tensorflow_stub/errors.py +507 -0
  123. tensorbored/compat/tensorflow_stub/flags.py +124 -0
  124. tensorbored/compat/tensorflow_stub/io/__init__.py +17 -0
  125. tensorbored/compat/tensorflow_stub/io/gfile.py +1011 -0
  126. tensorbored/compat/tensorflow_stub/pywrap_tensorflow.py +285 -0
  127. tensorbored/compat/tensorflow_stub/tensor_shape.py +1035 -0
  128. tensorbored/context.py +129 -0
  129. tensorbored/data/__init__.py +0 -0
  130. tensorbored/data/grpc_provider.py +365 -0
  131. tensorbored/data/ingester.py +46 -0
  132. tensorbored/data/proto/__init__.py +0 -0
  133. tensorbored/data/proto/data_provider_pb2.py +517 -0
  134. tensorbored/data/proto/data_provider_pb2_grpc.py +374 -0
  135. tensorbored/data/provider.py +1365 -0
  136. tensorbored/data/server_ingester.py +301 -0
  137. tensorbored/data_compat.py +159 -0
  138. tensorbored/dataclass_compat.py +224 -0
  139. tensorbored/default.py +124 -0
  140. tensorbored/errors.py +130 -0
  141. tensorbored/lazy.py +99 -0
  142. tensorbored/main.py +48 -0
  143. tensorbored/main_lib.py +62 -0
  144. tensorbored/manager.py +487 -0
  145. tensorbored/notebook.py +441 -0
  146. tensorbored/plugin_util.py +266 -0
  147. tensorbored/plugins/__init__.py +0 -0
  148. tensorbored/plugins/audio/__init__.py +0 -0
  149. tensorbored/plugins/audio/audio_plugin.py +229 -0
  150. tensorbored/plugins/audio/metadata.py +69 -0
  151. tensorbored/plugins/audio/plugin_data_pb2.py +37 -0
  152. tensorbored/plugins/audio/summary.py +230 -0
  153. tensorbored/plugins/audio/summary_v2.py +124 -0
  154. tensorbored/plugins/base_plugin.py +367 -0
  155. tensorbored/plugins/core/__init__.py +0 -0
  156. tensorbored/plugins/core/core_plugin.py +981 -0
  157. tensorbored/plugins/custom_scalar/__init__.py +0 -0
  158. tensorbored/plugins/custom_scalar/custom_scalars_plugin.py +320 -0
  159. tensorbored/plugins/custom_scalar/layout_pb2.py +85 -0
  160. tensorbored/plugins/custom_scalar/metadata.py +35 -0
  161. tensorbored/plugins/custom_scalar/summary.py +79 -0
  162. tensorbored/plugins/debugger_v2/__init__.py +0 -0
  163. tensorbored/plugins/debugger_v2/debug_data_multiplexer.py +631 -0
  164. tensorbored/plugins/debugger_v2/debug_data_provider.py +634 -0
  165. tensorbored/plugins/debugger_v2/debugger_v2_plugin.py +504 -0
  166. tensorbored/plugins/distribution/__init__.py +0 -0
  167. tensorbored/plugins/distribution/compressor.py +158 -0
  168. tensorbored/plugins/distribution/distributions_plugin.py +116 -0
  169. tensorbored/plugins/distribution/metadata.py +19 -0
  170. tensorbored/plugins/graph/__init__.py +0 -0
  171. tensorbored/plugins/graph/graph_util.py +129 -0
  172. tensorbored/plugins/graph/graphs_plugin.py +336 -0
  173. tensorbored/plugins/graph/keras_util.py +328 -0
  174. tensorbored/plugins/graph/metadata.py +42 -0
  175. tensorbored/plugins/histogram/__init__.py +0 -0
  176. tensorbored/plugins/histogram/histograms_plugin.py +144 -0
  177. tensorbored/plugins/histogram/metadata.py +63 -0
  178. tensorbored/plugins/histogram/plugin_data_pb2.py +34 -0
  179. tensorbored/plugins/histogram/summary.py +234 -0
  180. tensorbored/plugins/histogram/summary_v2.py +292 -0
  181. tensorbored/plugins/hparams/__init__.py +14 -0
  182. tensorbored/plugins/hparams/_keras.py +93 -0
  183. tensorbored/plugins/hparams/api.py +130 -0
  184. tensorbored/plugins/hparams/api_pb2.py +208 -0
  185. tensorbored/plugins/hparams/backend_context.py +606 -0
  186. tensorbored/plugins/hparams/download_data.py +158 -0
  187. tensorbored/plugins/hparams/error.py +26 -0
  188. tensorbored/plugins/hparams/get_experiment.py +71 -0
  189. tensorbored/plugins/hparams/hparams_plugin.py +206 -0
  190. tensorbored/plugins/hparams/hparams_util_pb2.py +69 -0
  191. tensorbored/plugins/hparams/json_format_compat.py +38 -0
  192. tensorbored/plugins/hparams/list_metric_evals.py +57 -0
  193. tensorbored/plugins/hparams/list_session_groups.py +1040 -0
  194. tensorbored/plugins/hparams/metadata.py +125 -0
  195. tensorbored/plugins/hparams/metrics.py +41 -0
  196. tensorbored/plugins/hparams/plugin_data_pb2.py +69 -0
  197. tensorbored/plugins/hparams/summary.py +205 -0
  198. tensorbored/plugins/hparams/summary_v2.py +597 -0
  199. tensorbored/plugins/image/__init__.py +0 -0
  200. tensorbored/plugins/image/images_plugin.py +232 -0
  201. tensorbored/plugins/image/metadata.py +65 -0
  202. tensorbored/plugins/image/plugin_data_pb2.py +34 -0
  203. tensorbored/plugins/image/summary.py +159 -0
  204. tensorbored/plugins/image/summary_v2.py +130 -0
  205. tensorbored/plugins/mesh/__init__.py +14 -0
  206. tensorbored/plugins/mesh/mesh_plugin.py +292 -0
  207. tensorbored/plugins/mesh/metadata.py +152 -0
  208. tensorbored/plugins/mesh/plugin_data_pb2.py +37 -0
  209. tensorbored/plugins/mesh/summary.py +251 -0
  210. tensorbored/plugins/mesh/summary_v2.py +214 -0
  211. tensorbored/plugins/metrics/__init__.py +0 -0
  212. tensorbored/plugins/metrics/metadata.py +17 -0
  213. tensorbored/plugins/metrics/metrics_plugin.py +623 -0
  214. tensorbored/plugins/pr_curve/__init__.py +0 -0
  215. tensorbored/plugins/pr_curve/metadata.py +75 -0
  216. tensorbored/plugins/pr_curve/plugin_data_pb2.py +34 -0
  217. tensorbored/plugins/pr_curve/pr_curves_plugin.py +241 -0
  218. tensorbored/plugins/pr_curve/summary.py +574 -0
  219. tensorbored/plugins/profile_redirect/__init__.py +0 -0
  220. tensorbored/plugins/profile_redirect/profile_redirect_plugin.py +49 -0
  221. tensorbored/plugins/projector/__init__.py +67 -0
  222. tensorbored/plugins/projector/metadata.py +26 -0
  223. tensorbored/plugins/projector/projector_config_pb2.py +54 -0
  224. tensorbored/plugins/projector/projector_plugin.py +795 -0
  225. tensorbored/plugins/projector/tf_projector_plugin/index.js +32 -0
  226. tensorbored/plugins/projector/tf_projector_plugin/projector_binary.html +524 -0
  227. tensorbored/plugins/projector/tf_projector_plugin/projector_binary.js +15536 -0
  228. tensorbored/plugins/scalar/__init__.py +0 -0
  229. tensorbored/plugins/scalar/metadata.py +60 -0
  230. tensorbored/plugins/scalar/plugin_data_pb2.py +34 -0
  231. tensorbored/plugins/scalar/scalars_plugin.py +181 -0
  232. tensorbored/plugins/scalar/summary.py +109 -0
  233. tensorbored/plugins/scalar/summary_v2.py +124 -0
  234. tensorbored/plugins/text/__init__.py +0 -0
  235. tensorbored/plugins/text/metadata.py +62 -0
  236. tensorbored/plugins/text/plugin_data_pb2.py +34 -0
  237. tensorbored/plugins/text/summary.py +114 -0
  238. tensorbored/plugins/text/summary_v2.py +124 -0
  239. tensorbored/plugins/text/text_plugin.py +288 -0
  240. tensorbored/plugins/wit_redirect/__init__.py +0 -0
  241. tensorbored/plugins/wit_redirect/wit_redirect_plugin.py +49 -0
  242. tensorbored/program.py +910 -0
  243. tensorbored/summary/__init__.py +35 -0
  244. tensorbored/summary/_output.py +124 -0
  245. tensorbored/summary/_tf/__init__.py +14 -0
  246. tensorbored/summary/_tf/summary/__init__.py +178 -0
  247. tensorbored/summary/_writer.py +105 -0
  248. tensorbored/summary/v1.py +51 -0
  249. tensorbored/summary/v2.py +25 -0
  250. tensorbored/summary/writer/__init__.py +13 -0
  251. tensorbored/summary/writer/event_file_writer.py +291 -0
  252. tensorbored/summary/writer/record_writer.py +50 -0
  253. tensorbored/util/__init__.py +0 -0
  254. tensorbored/util/encoder.py +116 -0
  255. tensorbored/util/grpc_util.py +311 -0
  256. tensorbored/util/img_mime_type_detector.py +40 -0
  257. tensorbored/util/io_util.py +20 -0
  258. tensorbored/util/lazy_tensor_creator.py +110 -0
  259. tensorbored/util/op_evaluator.py +104 -0
  260. tensorbored/util/platform_util.py +20 -0
  261. tensorbored/util/tb_logging.py +24 -0
  262. tensorbored/util/tensor_util.py +617 -0
  263. tensorbored/util/timing.py +122 -0
  264. tensorbored/version.py +21 -0
  265. tensorbored/webfiles.zip +0 -0
  266. tensorbored-2.21.0rc1769983804.dist-info/METADATA +49 -0
  267. tensorbored-2.21.0rc1769983804.dist-info/RECORD +271 -0
  268. tensorbored-2.21.0rc1769983804.dist-info/WHEEL +5 -0
  269. tensorbored-2.21.0rc1769983804.dist-info/entry_points.txt +6 -0
  270. tensorbored-2.21.0rc1769983804.dist-info/licenses/LICENSE +739 -0
  271. tensorbored-2.21.0rc1769983804.dist-info/top_level.txt +1 -0
@@ -0,0 +1,631 @@
1
+ # Copyright 2019 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
+ """A wrapper around DebugDataReader used for retrieving tfdbg v2 data."""
16
+
17
+ import threading
18
+
19
+ from tensorbored import errors
20
+
21
+ # Dummy run name for the debugger.
22
+ # Currently, the `DebuggerV2ExperimentMultiplexer` class is tied to a single
23
+ # logdir, which holds at most one DebugEvent file set in the tfdbg v2 (tfdbg2
24
+ # for short) format.
25
+ # TODO(cais): When tfdbg2 allows there to be multiple DebugEvent file sets in
26
+ # the same logdir, replace this magic string with actual run names.
27
+ DEFAULT_DEBUGGER_RUN_NAME = "__default_debugger_run__"
28
+
29
+ # Default number of alerts per monitor type.
30
+ # Limiting the number of alerts is based on the consideration that usually
31
+ # only the first few alerting events are the most critical and the subsequent
32
+ # ones are either repetitions of the earlier ones or caused by the earlier ones.
33
+ DEFAULT_PER_TYPE_ALERT_LIMIT = 1000
34
+
35
+ # Default interval between successive calls to `DebugDataReader.update()``.
36
+ DEFAULT_RELOAD_INTERVAL_SEC = 30
37
+
38
+
39
+ def run_repeatedly_in_background(target, interval_sec):
40
+ """Run a target task repeatedly in the background.
41
+
42
+ In the context of this module, `target` is the `update()` method of the
43
+ underlying reader for tfdbg2-format data.
44
+ This method is mocked by unit tests for deterministic behaviors during
45
+ testing.
46
+
47
+ Args:
48
+ target: The target task to run in the background, a callable with no args.
49
+ interval_sec: Time interval between repeats, in seconds.
50
+
51
+ Returns:
52
+ - A `threading.Event` object that can be used to interrupt an ongoing
53
+ waiting interval between successive runs of `target`. To interrupt the
54
+ interval, call the `set()` method of the object.
55
+ - The `threading.Thread` object on which `target` is run repeatedly.
56
+ """
57
+ event = threading.Event()
58
+
59
+ def _run_repeatedly():
60
+ while True:
61
+ target()
62
+ event.wait(interval_sec)
63
+ event.clear()
64
+
65
+ # Use `daemon=True` to make sure the thread doesn't block program exit.
66
+ thread = threading.Thread(target=_run_repeatedly, daemon=True)
67
+ thread.start()
68
+ return event, thread
69
+
70
+
71
+ def _alert_to_json(alert):
72
+ # TODO(cais): Replace this with Alert.to_json() when supported by the
73
+ # backend.
74
+ from tensorflow.python.debug.lib import debug_events_monitors
75
+
76
+ if isinstance(alert, debug_events_monitors.InfNanAlert):
77
+ return {
78
+ "alert_type": "InfNanAlert",
79
+ "op_type": alert.op_type,
80
+ "output_slot": alert.output_slot,
81
+ # TODO(cais): Once supported by backend, add 'op_name' key
82
+ # for intra-graph execution events.
83
+ "size": alert.size,
84
+ "num_neg_inf": alert.num_neg_inf,
85
+ "num_pos_inf": alert.num_pos_inf,
86
+ "num_nan": alert.num_nan,
87
+ "execution_index": alert.execution_index,
88
+ "graph_execution_trace_index": alert.graph_execution_trace_index,
89
+ }
90
+ else:
91
+ raise TypeError("Unrecognized alert subtype: %s" % type(alert))
92
+
93
+
94
+ def parse_tensor_name(tensor_name):
95
+ """Helper function that extracts op name and slot from tensor name."""
96
+ output_slot = 0
97
+ if ":" in tensor_name:
98
+ op_name, output_slot = tensor_name.split(":")
99
+ output_slot = int(output_slot)
100
+ else:
101
+ op_name = tensor_name
102
+ return op_name, output_slot
103
+
104
+
105
+ class DebuggerV2EventMultiplexer:
106
+ """A class used for accessing tfdbg v2 DebugEvent data on local filesystem.
107
+
108
+ This class is a short-term hack, mirroring the EventMultiplexer for the main
109
+ TensorBoard plugins (e.g., scalar, histogram and graphs.) As such, it only
110
+ implements the methods relevant to the Debugger V2 pluggin.
111
+
112
+ TODO(cais): Integrate it with EventMultiplexer and use the integrated class
113
+ from MultiplexerDataProvider for a single path of accessing debugger and
114
+ non-debugger data.
115
+ """
116
+
117
+ def __init__(self, logdir):
118
+ """Constructor for the `DebugEventMultiplexer`.
119
+
120
+ Args:
121
+ logdir: Path to the directory to load the tfdbg v2 data from.
122
+ """
123
+ self._logdir = logdir
124
+ self._reader = None
125
+ self._reader_lock = threading.Lock()
126
+ self._reload_needed_event = None
127
+ # Create the reader for the tfdbg2 data in the lodir as soon as
128
+ # the backend of the debugger-v2 plugin is created, so it doesn't need
129
+ # to wait for the first request from the FE to start loading data.
130
+ self._tryCreateReader()
131
+
132
+ def _tryCreateReader(self):
133
+ """Try creating reader for tfdbg2 data in the logdir.
134
+
135
+ If the reader has already been created, a new one will not be created and
136
+ this function is a no-op.
137
+
138
+ If a reader has not been created, create it and start periodic calls to
139
+ `update()` on a separate thread.
140
+ """
141
+ if self._reader:
142
+ return
143
+ with self._reader_lock:
144
+ if not self._reader:
145
+ try:
146
+ # TODO(cais): Avoid conditional imports and instead use
147
+ # plugin loader to gate the loading of this entire plugin.
148
+ from tensorflow.python.debug.lib import debug_events_reader
149
+ from tensorflow.python.debug.lib import (
150
+ debug_events_monitors,
151
+ )
152
+ except ImportError:
153
+ # This ensures graceful behavior when tensorflow install is
154
+ # unavailable or when the installed tensorflow version does not
155
+ # contain the required modules.
156
+ return
157
+
158
+ try:
159
+ self._reader = debug_events_reader.DebugDataReader(
160
+ self._logdir
161
+ )
162
+ except AttributeError:
163
+ # Gracefully fail for users without the required API changes to
164
+ # debug_events_reader.DebugDataReader introduced in
165
+ # TF 2.1.0.dev20200103. This should be safe to remove when
166
+ # TF 2.2 is released.
167
+ return
168
+ except ValueError:
169
+ # When no DebugEvent file set is found in the logdir, a
170
+ # `ValueError` is thrown.
171
+ return
172
+
173
+ self._monitors = [
174
+ debug_events_monitors.InfNanMonitor(
175
+ self._reader, limit=DEFAULT_PER_TYPE_ALERT_LIMIT
176
+ )
177
+ ]
178
+ self._reload_needed_event, _ = run_repeatedly_in_background(
179
+ self._reader.update, DEFAULT_RELOAD_INTERVAL_SEC
180
+ )
181
+
182
+ def _reloadReader(self):
183
+ """If a reader exists and has started period updating, unblock the update.
184
+
185
+ The updates are performed periodically with a sleep interval between
186
+ successive calls to the reader's update() method. Calling this method
187
+ interrupts the sleep immediately if one is ongoing.
188
+ """
189
+ if self._reload_needed_event:
190
+ self._reload_needed_event.set()
191
+
192
+ def FirstEventTimestamp(self, run):
193
+ """Return the timestamp of the first DebugEvent of the given run.
194
+
195
+ This may perform I/O if no events have been loaded yet for the run.
196
+
197
+ Args:
198
+ run: A string name of the run for which the timestamp is retrieved.
199
+ This currently must be hardcoded as `DEFAULT_DEBUGGER_RUN_NAME`,
200
+ as each logdir contains at most one DebugEvent file set (i.e., a
201
+ run of a tfdbg2-instrumented TensorFlow program.)
202
+
203
+ Returns:
204
+ The wall_time of the first event of the run, which will be in seconds
205
+ since the epoch as a `float`.
206
+ """
207
+ if self._reader is None:
208
+ raise ValueError("No tfdbg2 runs exists.")
209
+ if run != DEFAULT_DEBUGGER_RUN_NAME:
210
+ raise ValueError(
211
+ "Expected run name to be %s, but got %s"
212
+ % (DEFAULT_DEBUGGER_RUN_NAME, run)
213
+ )
214
+ return self._reader.starting_wall_time()
215
+
216
+ def PluginRunToTagToContent(self, plugin_name):
217
+ raise NotImplementedError(
218
+ "DebugDataMultiplexer.PluginRunToTagToContent() has not been "
219
+ "implemented yet."
220
+ )
221
+
222
+ def Runs(self):
223
+ """Return all the tfdbg2 run names in the logdir watched by this instance.
224
+
225
+ The `Run()` method of this class is specialized for the tfdbg2-format
226
+ DebugEvent files.
227
+
228
+ As a side effect, this method unblocks the underlying reader's period
229
+ reloading if a reader exists. This lets the reader update at a higher
230
+ frequency than the default one with 30-second sleeping period between
231
+ reloading when data is being queried actively from this instance.
232
+ Note that this `Runs()` method is used by all other public data-access
233
+ methods of this class (e.g., `ExecutionData()`, `GraphExecutionData()`).
234
+ Hence calls to those methods will lead to accelerated data reloading of
235
+ the reader.
236
+
237
+ Returns:
238
+ If tfdbg2-format data exists in the `logdir` of this object, returns:
239
+ ```
240
+ {runName: { "debugger-v2": [tag1, tag2, tag3] } }
241
+ ```
242
+ where `runName` is the hard-coded string `DEFAULT_DEBUGGER_RUN_NAME`
243
+ string. This is related to the fact that tfdbg2 currently contains
244
+ at most one DebugEvent file set per directory.
245
+ If no tfdbg2-format data exists in the `logdir`, an empty `dict`.
246
+ """
247
+ # Call `_tryCreateReader()` here to cover the possibility of tfdbg2
248
+ # data start being written to the logdir after the tensorboard backend
249
+ # starts.
250
+ self._tryCreateReader()
251
+ if self._reader:
252
+ # If a _reader exists, unblock its reloading (on a separate thread)
253
+ # immediately.
254
+ self._reloadReader()
255
+ return {
256
+ DEFAULT_DEBUGGER_RUN_NAME: {
257
+ # TODO(cais): Add the semantically meaningful tag names such as
258
+ # 'execution_digests_book', 'alerts_book'
259
+ "debugger-v2": []
260
+ }
261
+ }
262
+ else:
263
+ return {}
264
+
265
+ def _checkBeginEndIndices(self, begin, end, total_count):
266
+ if begin < 0:
267
+ raise errors.InvalidArgumentError(
268
+ "Invalid begin index (%d)" % begin
269
+ )
270
+ if end > total_count:
271
+ raise errors.InvalidArgumentError(
272
+ "end index (%d) out of bounds (%d)" % (end, total_count)
273
+ )
274
+ if end >= 0 and end < begin:
275
+ raise errors.InvalidArgumentError(
276
+ "end index (%d) is unexpectedly less than begin index (%d)"
277
+ % (end, begin)
278
+ )
279
+ if end < 0: # This means all digests.
280
+ end = total_count
281
+ return end
282
+
283
+ def Alerts(self, run, begin, end, alert_type_filter=None):
284
+ """Get alerts from the debugged TensorFlow program.
285
+
286
+ Args:
287
+ run: The tfdbg2 run to get Alerts from.
288
+ begin: Beginning alert index.
289
+ end: Ending alert index.
290
+ alert_type_filter: Optional filter string for alert type, used to
291
+ restrict retrieved alerts data to a single type. If used,
292
+ `begin` and `end` refer to the beginning and ending indices within
293
+ the filtered alert type.
294
+ """
295
+ from tensorflow.python.debug.lib import debug_events_monitors
296
+
297
+ runs = self.Runs()
298
+ if run not in runs:
299
+ # TODO(cais): This should generate a 400 response instead.
300
+ return None
301
+ alerts = []
302
+ alerts_breakdown = dict()
303
+ alerts_by_type = dict()
304
+ for monitor in self._monitors:
305
+ monitor_alerts = monitor.alerts()
306
+ if not monitor_alerts:
307
+ continue
308
+ alerts.extend(monitor_alerts)
309
+ # TODO(cais): Replace this with Alert.to_json() when
310
+ # monitor.alert_type() is available.
311
+ if isinstance(monitor, debug_events_monitors.InfNanMonitor):
312
+ alert_type = "InfNanAlert"
313
+ else:
314
+ alert_type = "__MiscellaneousAlert__"
315
+ alerts_breakdown[alert_type] = len(monitor_alerts)
316
+ alerts_by_type[alert_type] = monitor_alerts
317
+ num_alerts = len(alerts)
318
+ if alert_type_filter is not None:
319
+ if alert_type_filter not in alerts_breakdown:
320
+ raise errors.InvalidArgumentError(
321
+ "Filtering of alerts failed: alert type %s does not exist"
322
+ % alert_type_filter
323
+ )
324
+ alerts = alerts_by_type[alert_type_filter]
325
+ end = self._checkBeginEndIndices(begin, end, len(alerts))
326
+ return {
327
+ "begin": begin,
328
+ "end": end,
329
+ "alert_type": alert_type_filter,
330
+ "num_alerts": num_alerts,
331
+ "alerts_breakdown": alerts_breakdown,
332
+ "per_type_alert_limit": DEFAULT_PER_TYPE_ALERT_LIMIT,
333
+ "alerts": [_alert_to_json(alert) for alert in alerts[begin:end]],
334
+ }
335
+
336
+ def ExecutionDigests(self, run, begin, end):
337
+ """Get ExecutionDigests.
338
+
339
+ Args:
340
+ run: The tfdbg2 run to get `ExecutionDigest`s from.
341
+ begin: Beginning execution index.
342
+ end: Ending execution index.
343
+
344
+ Returns:
345
+ A JSON-serializable object containing the `ExecutionDigest`s and
346
+ related meta-information
347
+ """
348
+ runs = self.Runs()
349
+ if run not in runs:
350
+ return None
351
+ # TODO(cais): For scalability, use begin and end kwargs when available in
352
+ # `DebugDataReader.execution()`.`
353
+ execution_digests = self._reader.executions(digest=True)
354
+ end = self._checkBeginEndIndices(begin, end, len(execution_digests))
355
+ return {
356
+ "begin": begin,
357
+ "end": end,
358
+ "num_digests": len(execution_digests),
359
+ "execution_digests": [
360
+ digest.to_json() for digest in execution_digests[begin:end]
361
+ ],
362
+ }
363
+
364
+ def ExecutionData(self, run, begin, end):
365
+ """Get Execution data objects (Detailed, non-digest form).
366
+
367
+ Args:
368
+ run: The tfdbg2 run to get `ExecutionDigest`s from.
369
+ begin: Beginning execution index.
370
+ end: Ending execution index.
371
+
372
+ Returns:
373
+ A JSON-serializable object containing the `ExecutionDigest`s and
374
+ related meta-information
375
+ """
376
+ runs = self.Runs()
377
+ if run not in runs:
378
+ return None
379
+ execution_digests = self._reader.executions(digest=True)
380
+ end = self._checkBeginEndIndices(begin, end, len(execution_digests))
381
+ execution_digests = execution_digests[begin:end]
382
+ executions = self._reader.executions(digest=False, begin=begin, end=end)
383
+ return {
384
+ "begin": begin,
385
+ "end": end,
386
+ "executions": [execution.to_json() for execution in executions],
387
+ }
388
+
389
+ def GraphExecutionDigests(self, run, begin, end, trace_id=None):
390
+ """Get `GraphExecutionTraceDigest`s.
391
+
392
+ Args:
393
+ run: The tfdbg2 run to get `GraphExecutionTraceDigest`s from.
394
+ begin: Beginning graph-execution index.
395
+ end: Ending graph-execution index.
396
+
397
+ Returns:
398
+ A JSON-serializable object containing the `ExecutionDigest`s and
399
+ related meta-information
400
+ """
401
+ runs = self.Runs()
402
+ if run not in runs:
403
+ return None
404
+ # TODO(cais): Implement support for trace_id once the joining of eager
405
+ # execution and intra-graph execution is supported by DebugDataReader.
406
+ if trace_id is not None:
407
+ raise NotImplementedError(
408
+ "trace_id support for GraphExecutionTraceDigest is "
409
+ "not implemented yet."
410
+ )
411
+ graph_exec_digests = self._reader.graph_execution_traces(digest=True)
412
+ end = self._checkBeginEndIndices(begin, end, len(graph_exec_digests))
413
+ return {
414
+ "begin": begin,
415
+ "end": end,
416
+ "num_digests": len(graph_exec_digests),
417
+ "graph_execution_digests": [
418
+ digest.to_json() for digest in graph_exec_digests[begin:end]
419
+ ],
420
+ }
421
+
422
+ def GraphExecutionData(self, run, begin, end, trace_id=None):
423
+ """Get `GraphExecutionTrace`s.
424
+
425
+ Args:
426
+ run: The tfdbg2 run to get `GraphExecutionTrace`s from.
427
+ begin: Beginning graph-execution index.
428
+ end: Ending graph-execution index.
429
+
430
+ Returns:
431
+ A JSON-serializable object containing the `ExecutionDigest`s and
432
+ related meta-information
433
+ """
434
+ runs = self.Runs()
435
+ if run not in runs:
436
+ return None
437
+ # TODO(cais): Implement support for trace_id once the joining of eager
438
+ # execution and intra-graph execution is supported by DebugDataReader.
439
+ if trace_id is not None:
440
+ raise NotImplementedError(
441
+ "trace_id support for GraphExecutionTraceData is "
442
+ "not implemented yet."
443
+ )
444
+ digests = self._reader.graph_execution_traces(digest=True)
445
+ end = self._checkBeginEndIndices(begin, end, len(digests))
446
+ graph_executions = self._reader.graph_execution_traces(
447
+ digest=False, begin=begin, end=end
448
+ )
449
+ return {
450
+ "begin": begin,
451
+ "end": end,
452
+ "graph_executions": [
453
+ graph_exec.to_json() for graph_exec in graph_executions
454
+ ],
455
+ }
456
+
457
+ def GraphInfo(self, run, graph_id):
458
+ """Get the information regarding a TensorFlow graph.
459
+
460
+ Args:
461
+ run: Name of the run.
462
+ graph_id: Debugger-generated ID of the graph in question.
463
+ This information is available in the return values
464
+ of `GraphOpInfo`, `GraphExecution`, etc.
465
+
466
+ Returns:
467
+ A JSON-serializable object containing the information regarding
468
+ the TensorFlow graph.
469
+
470
+ Raises:
471
+ NotFoundError if the graph_id is not known to the debugger.
472
+ """
473
+ runs = self.Runs()
474
+ if run not in runs:
475
+ return None
476
+ try:
477
+ graph = self._reader.graph_by_id(graph_id)
478
+ except KeyError:
479
+ raise errors.NotFoundError(
480
+ 'There is no graph with ID "%s"' % graph_id
481
+ )
482
+ return graph.to_json()
483
+
484
+ def GraphOpInfo(self, run, graph_id, op_name):
485
+ """Get the information regarding a graph op's creation.
486
+
487
+ Args:
488
+ run: Name of the run.
489
+ graph_id: Debugger-generated ID of the graph that contains
490
+ the op in question. This ID is available from other methods
491
+ of this class, e.g., the return value of `GraphExecutionDigests()`.
492
+ op_name: Name of the op.
493
+
494
+ Returns:
495
+ A JSON-serializable object containing the information regarding
496
+ the op's creation and its immediate inputs and consumers.
497
+
498
+ Raises:
499
+ NotFoundError if the graph_id or op_name does not exist.
500
+ """
501
+ runs = self.Runs()
502
+ if run not in runs:
503
+ return None
504
+ try:
505
+ graph = self._reader.graph_by_id(graph_id)
506
+ except KeyError:
507
+ raise errors.NotFoundError(
508
+ 'There is no graph with ID "%s"' % graph_id
509
+ )
510
+ try:
511
+ op_creation_digest = graph.get_op_creation_digest(op_name)
512
+ except KeyError:
513
+ raise errors.NotFoundError(
514
+ 'There is no op named "%s" in graph with ID "%s"'
515
+ % (op_name, graph_id)
516
+ )
517
+ data_object = self._opCreationDigestToDataObject(
518
+ op_creation_digest, graph
519
+ )
520
+ # Populate data about immediate inputs.
521
+ for input_spec in data_object["inputs"]:
522
+ try:
523
+ input_op_digest = graph.get_op_creation_digest(
524
+ input_spec["op_name"]
525
+ )
526
+ except KeyError:
527
+ input_op_digest = None
528
+ if input_op_digest:
529
+ input_spec["data"] = self._opCreationDigestToDataObject(
530
+ input_op_digest, graph
531
+ )
532
+ # Populate data about immediate consuming ops.
533
+ for slot_consumer_specs in data_object["consumers"]:
534
+ for consumer_spec in slot_consumer_specs:
535
+ try:
536
+ digest = graph.get_op_creation_digest(
537
+ consumer_spec["op_name"]
538
+ )
539
+ except KeyError:
540
+ digest = None
541
+ if digest:
542
+ consumer_spec["data"] = self._opCreationDigestToDataObject(
543
+ digest, graph
544
+ )
545
+ return data_object
546
+
547
+ def _opCreationDigestToDataObject(self, op_creation_digest, graph):
548
+ if op_creation_digest is None:
549
+ return None
550
+ json_object = op_creation_digest.to_json()
551
+ del json_object["graph_id"]
552
+ json_object["graph_ids"] = self._getGraphStackIds(
553
+ op_creation_digest.graph_id
554
+ )
555
+ # TODO(cais): "num_outputs" should be populated in to_json() instead.
556
+ json_object["num_outputs"] = op_creation_digest.num_outputs
557
+ del json_object["input_names"]
558
+
559
+ json_object["inputs"] = []
560
+ for input_tensor_name in op_creation_digest.input_names or []:
561
+ input_op_name, output_slot = parse_tensor_name(input_tensor_name)
562
+ json_object["inputs"].append(
563
+ {"op_name": input_op_name, "output_slot": output_slot}
564
+ )
565
+ json_object["consumers"] = []
566
+ for _ in range(json_object["num_outputs"]):
567
+ json_object["consumers"].append([])
568
+ for src_slot, consumer_op_name, dst_slot in graph.get_op_consumers(
569
+ json_object["op_name"]
570
+ ):
571
+ json_object["consumers"][src_slot].append(
572
+ {"op_name": consumer_op_name, "input_slot": dst_slot}
573
+ )
574
+ return json_object
575
+
576
+ def _getGraphStackIds(self, graph_id):
577
+ """Retrieve the IDs of all outer graphs of a graph.
578
+
579
+ Args:
580
+ graph_id: Id of the graph being queried with respect to its outer
581
+ graphs context.
582
+
583
+ Returns:
584
+ A list of graph_ids, ordered from outermost to innermost, including
585
+ the input `graph_id` argument as the last item.
586
+ """
587
+ graph_ids = [graph_id]
588
+ graph = self._reader.graph_by_id(graph_id)
589
+ while graph.outer_graph_id:
590
+ graph_ids.insert(0, graph.outer_graph_id)
591
+ graph = self._reader.graph_by_id(graph.outer_graph_id)
592
+ return graph_ids
593
+
594
+ def SourceFileList(self, run):
595
+ runs = self.Runs()
596
+ if run not in runs:
597
+ return None
598
+ return self._reader.source_file_list()
599
+
600
+ def SourceLines(self, run, index):
601
+ runs = self.Runs()
602
+ if run not in runs:
603
+ return None
604
+ try:
605
+ host_name, file_path = self._reader.source_file_list()[index]
606
+ except IndexError:
607
+ raise errors.NotFoundError(
608
+ "There is no source-code file at index %d" % index
609
+ )
610
+ return {
611
+ "host_name": host_name,
612
+ "file_path": file_path,
613
+ "lines": self._reader.source_lines(host_name, file_path),
614
+ }
615
+
616
+ def StackFrames(self, run, stack_frame_ids):
617
+ runs = self.Runs()
618
+ if run not in runs:
619
+ return None
620
+ stack_frames = []
621
+ for stack_frame_id in stack_frame_ids:
622
+ if stack_frame_id not in self._reader._stack_frame_by_id:
623
+ raise errors.NotFoundError(
624
+ "Cannot find stack frame with ID %s" % stack_frame_id
625
+ )
626
+ # TODO(cais): Use public method (`stack_frame_by_id()`) when
627
+ # available.
628
+ # pylint: disable=protected-access
629
+ stack_frames.append(self._reader._stack_frame_by_id[stack_frame_id])
630
+ # pylint: enable=protected-access
631
+ return {"stack_frames": stack_frames}