aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/tensorboard/tensorboard.py
blob: dcbc50401c0c39f0e92e71709be7ab76a48805cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"""Serve TensorFlow summary data to a web frontend.

This is a simple web server to proxy data from the event_loader to the web, and
serve static web files.
"""

import BaseHTTPServer
import functools
import os
import socket
import SocketServer

import tensorflow.python.platform

from tensorflow.python.platform import app
from tensorflow.python.platform import flags
from tensorflow.python.platform import logging
from tensorflow.python.platform import status_bar
from tensorflow.python.summary import event_accumulator
from tensorflow.python.summary import event_multiplexer
from tensorflow.tensorboard import tensorboard_handler

flags.DEFINE_string('logdir', None, """
logdir specifies where TensorBoard will look to find TensorFlow event files
that it can display. In the simplest case, logdir is a directory containing
tfevents files. TensorBoard also supports comparing multiple TensorFlow
executions: to do this, you can use directory whose subdirectories contain
tfevents files, as in the following example:

foo/bar/logdir/
foo/bar/logdir/mnist_1/events.out.tfevents.1444088766
foo/bar/logdir/mnist_2/events.out.tfevents.1444090064

You may also pass a comma seperated list of log directories, and you can
assign names to individual log directories by putting a colon between the name
and the path, as in

tensorboard --logdir=name1:/path/to/logs/1,name2:/path/to/logs/2
""")
flags.DEFINE_boolean('debug', False, 'Whether to run the app in debug mode. '
                     'This increases log verbosity to DEBUG.')
flags.DEFINE_string('host', '0.0.0.0', 'What host to listen to. Defaults to '
                    'allowing remote access, set to 127.0.0.1 to serve only on '
                    'localhost.')
flags.DEFINE_integer('port', 6006, 'What port to serve TensorBoard on.')

FLAGS = flags.FLAGS

# How many elements to store per tag, by tag type
TENSORBOARD_SIZE_GUIDANCE = {
    event_accumulator.COMPRESSED_HISTOGRAMS: 500,
    event_accumulator.IMAGES: 4,
    event_accumulator.SCALARS: 10000,
    event_accumulator.HISTOGRAMS: 1,
}


def ParseEventFilesFlag(flag_value):
  """Parses the logdir flag into a map from paths to run group names.

  The events files flag format is a comma-separated list of path specifications.
  A path specification either looks like 'group_name:/path/to/directory' or
  '/path/to/directory'; in the latter case, the group is unnamed. Group names
  cannot start with a forward slash: /foo:bar/baz will be interpreted as a
  spec with no name and path '/foo:bar/baz'.

  Globs are not supported.

  Args:
    flag_value: A comma-separated list of run specifications.
  Returns:
    A dict mapping directory paths to names like {'/path/to/directory': 'name'}.
    Groups without an explicit name are named after their path. If flag_value
    is None, returns an empty dict, which is helpful for testing things that
    don't require any valid runs.
  """
  files = {}
  if flag_value is None:
    return files
  for specification in flag_value.split(','):
    # If the spec looks like /foo:bar/baz, then we assume it's a path with a
    # colon.
    if ':' in specification and specification[0] != '/':
      # We split at most once so run_name:/path:with/a/colon will work.
      run_name, path = specification.split(':', 1)
    else:
      run_name = None
      path = specification
    files[path] = run_name
  return files


class ThreadedHTTPServer(SocketServer.ThreadingMixIn,
                         BaseHTTPServer.HTTPServer):
  """A threaded HTTP server."""
  daemon = True


def main(unused_argv=None):
  # Change current working directory to tensorflow/'s parent directory.
  server_root = os.path.join(os.path.dirname(__file__),
                             os.pardir, os.pardir)
  os.chdir(server_root)

  if FLAGS.debug:
    logging.set_verbosity(logging.DEBUG)

  if not FLAGS.logdir:
    logging.error('A logdir must be specified. Run `tensorboard --help` for '
                  'details and examples.')
    return -1

  if FLAGS.debug:
    logging.info('Starting TensorBoard in directory %s' % os.getcwd())

  path_to_run = ParseEventFilesFlag(FLAGS.logdir)
  multiplexer = event_multiplexer.AutoloadingMultiplexer(
      path_to_run=path_to_run, interval_secs=60,
      size_guidance=TENSORBOARD_SIZE_GUIDANCE)

  multiplexer.AutoUpdate(interval=30)

  factory = functools.partial(tensorboard_handler.TensorboardHandler,
                              multiplexer)
  try:
    server = ThreadedHTTPServer((FLAGS.host, FLAGS.port), factory)
  except socket.error:
    logging.error('Tried to connect to port %d, but that address is in use.' %
                  FLAGS.port)
    return -2

  status_bar.SetupStatusBarInsideGoogle('TensorBoard', FLAGS.port)
  print 'Starting TensorBoard on port %d' % FLAGS.port
  print '(You can navigate to http://localhost:%d)' % FLAGS.port
  server.serve_forever()


if __name__ == '__main__':
  app.run()