diff --git a/tensorboard/uploader/exporter.py b/tensorboard/uploader/exporter.py index 99ece52060..3eb74aaffc 100644 --- a/tensorboard/uploader/exporter.py +++ b/tensorboard/uploader/exporter.py @@ -28,6 +28,7 @@ import six +from tensorboard.uploader.proto import experiment_pb2 from tensorboard.uploader.proto import export_service_pb2 from tensorboard.uploader import util from tensorboard.util import grpc_util @@ -130,7 +131,7 @@ def export(self, read_time=None): def _request_experiment_ids(self, read_time): """Yields all of the calling user's experiment IDs, as strings.""" for experiment in list_experiments(self._api, read_time=read_time): - if isinstance(experiment, export_service_pb2.Experiment): + if isinstance(experiment, experiment_pb2.Experiment): yield experiment.experiment_id elif isinstance(experiment, six.string_types): yield experiment @@ -177,13 +178,13 @@ def list_experiments(api_client, fieldmask=None, read_time=None): Args: api_client: A TensorBoardExporterService stub instance. - fieldmask: An optional `export_service_pb2.ExperimentMask` value. + fieldmask: An optional `experiment_pb2.ExperimentMask` value. read_time: A fixed timestamp from which to export data, as float seconds since epoch (like `time.time()`). Optional; defaults to the current time. Yields: - For each experiment owned by the user, an `export_service_pb2.Experiment` + For each experiment owned by the user, an `experiment_pb2.Experiment` value, or a simple string experiment ID for older servers. """ if read_time is None: diff --git a/tensorboard/uploader/exporter_test.py b/tensorboard/uploader/exporter_test.py index e490a67b3e..84caaaa7c6 100644 --- a/tensorboard/uploader/exporter_test.py +++ b/tensorboard/uploader/exporter_test.py @@ -33,6 +33,7 @@ import mock # pylint: disable=unused-import +from tensorboard.uploader.proto import experiment_pb2 from tensorboard.uploader.proto import export_service_pb2 from tensorboard.uploader.proto import export_service_pb2_grpc from tensorboard.uploader import exporter as exporter_lib @@ -393,10 +394,10 @@ def stream_experiments(request, **kwargs): expected = [ "123", "456", - export_service_pb2.Experiment(experiment_id="789"), - export_service_pb2.Experiment(experiment_id="012"), - export_service_pb2.Experiment(experiment_id="345"), - export_service_pb2.Experiment(experiment_id="678"), + experiment_pb2.Experiment(experiment_id="789"), + experiment_pb2.Experiment(experiment_id="012"), + experiment_pb2.Experiment(experiment_id="345"), + experiment_pb2.Experiment(experiment_id="678"), ] self.assertEqual(list(gen), expected) diff --git a/tensorboard/uploader/proto/BUILD b/tensorboard/uploader/proto/BUILD index cdc7212e1a..16e08b5171 100644 --- a/tensorboard/uploader/proto/BUILD +++ b/tensorboard/uploader/proto/BUILD @@ -11,6 +11,7 @@ tb_proto_library( name = "protos_all", srcs = [ "blob.proto", + "experiment.proto", "export_service.proto", "scalar.proto", "server_info.proto", @@ -18,7 +19,5 @@ tb_proto_library( "write_service.proto", ], has_services = True, - deps = [ - "//tensorboard/compat/proto:protos_all", - ], + deps = ["//tensorboard/compat/proto:protos_all"], ) diff --git a/tensorboard/uploader/proto/experiment.proto b/tensorboard/uploader/proto/experiment.proto new file mode 100644 index 0000000000..4fa926dd8a --- /dev/null +++ b/tensorboard/uploader/proto/experiment.proto @@ -0,0 +1,47 @@ +syntax = "proto3"; + +package tensorboard.service; + +import "google/protobuf/timestamp.proto"; + +// Resource message representing an Experiment. +message Experiment { + // Permanent ID of this experiment; e.g.: "AdYd1TgeTlaLWXx6I8JUbA". + // Output-only. + string experiment_id = 1; + // The time that the experiment was created. Output-only. + google.protobuf.Timestamp create_time = 2; + // The time that the experiment was last modified: i.e., the most recent time + // that scalars were added to the experiment. Output-only. + google.protobuf.Timestamp update_time = 3; + // The number of scalars in this experiment, across all time series. + // Output-only. + int64 num_scalars = 4; + // The number of distinct run names in this experiment. Output-only. + int64 num_runs = 5; + // The number of distinct tag names in this experiment. A tag name that + // appears in multiple runs will be counted only once. Output-only. + int64 num_tags = 6; + // User provided name of the experiment. + string name = 7; + // User provided description of the experiment, in markdown source format. + string description = 8; + // The number of bytes used for storage of tensors in this experiment, + // across all time series, including estimated overhead. Output-only. + int64 total_tensor_bytes = 9; +} + +// Field mask for `Experiment` used in get and update RPCs. The `experiment_id` +// field is always implicitly considered to be set. +message ExperimentMask { + reserved 1; + reserved "experiment_id"; + bool create_time = 2; + bool update_time = 3; + bool num_scalars = 4; + bool num_runs = 5; + bool num_tags = 6; + bool name = 7; + bool description = 8; + bool total_tensor_bytes = 9; +} diff --git a/tensorboard/uploader/proto/export_service.proto b/tensorboard/uploader/proto/export_service.proto index 22d5660908..313659f868 100644 --- a/tensorboard/uploader/proto/export_service.proto +++ b/tensorboard/uploader/proto/export_service.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package tensorboard.service; import "google/protobuf/timestamp.proto"; +import "tensorboard/uploader/proto/experiment.proto"; import "tensorboard/compat/proto/summary.proto"; import "tensorboard/compat/proto/tensor.proto"; @@ -75,48 +76,6 @@ message StreamExperimentsResponse { repeated Experiment experiments = 2; } -// Metadata about an experiment. This contains both user provided metadata -// along with internal book-keeping about the experiment. -// TODO(bileschi): Move this and ExperimentMask into their own file. -message Experiment { - // Permanent ID of this experiment; e.g.: "AdYd1TgeTlaLWXx6I8JUbA". - string experiment_id = 1; - // The time that the experiment was created. - google.protobuf.Timestamp create_time = 2; - // The time that the experiment was last modified: i.e., the most recent time - // that scalars were added to the experiment. - google.protobuf.Timestamp update_time = 3; - // The number of scalars in this experiment, across all time series. - int64 num_scalars = 4; - // The number of distinct run names in this experiment. - int64 num_runs = 5; - // The number of distinct tag names in this experiment. A tag name that - // appears in multiple runs will be counted only once. - int64 num_tags = 6; - // User provided name of the experiment. - string name = 7; - // User provided description of the experiment, in markdown source format. - string description = 8; - // The number of bytes used for storage of tensors in this experiment, - // across all time series, including estimated overhead. - int64 total_tensor_bytes = 9; -} - -// Field mask for `Experiment`. The `experiment_id` field is always implicitly -// considered to be set. -message ExperimentMask { - reserved 1; - reserved "experiment_id"; - bool create_time = 2; - bool update_time = 3; - bool num_scalars = 4; - bool num_runs = 5; - bool num_tags = 6; - bool name = 7; - bool description = 8; - bool total_tensor_bytes = 9; -} - // Request to stream scalars from all the runs and tags in an experiment. message StreamExperimentDataRequest { // The permanent ID of the experiment whose data need to be streamed. diff --git a/tensorboard/uploader/proto/write_service.proto b/tensorboard/uploader/proto/write_service.proto index 138839f8eb..325290f0dc 100644 --- a/tensorboard/uploader/proto/write_service.proto +++ b/tensorboard/uploader/proto/write_service.proto @@ -3,10 +3,7 @@ syntax = "proto3"; package tensorboard.service; import "google/protobuf/timestamp.proto"; -// TODO(bileschi): write_service.proto imports export_service.proto for the -// definition of Experiment and ExperimentMask. It would be better to excise -// those into one file that both services depend on. -import "tensorboard/uploader/proto/export_service.proto"; +import "tensorboard/uploader/proto/experiment.proto"; import "tensorboard/uploader/proto/scalar.proto"; import "tensorboard/uploader/proto/tensor.proto"; import "tensorboard/uploader/proto/blob.proto"; diff --git a/tensorboard/uploader/uploader_main.py b/tensorboard/uploader/uploader_main.py index 5ed906ea85..57c406837a 100644 --- a/tensorboard/uploader/uploader_main.py +++ b/tensorboard/uploader/uploader_main.py @@ -31,7 +31,7 @@ import six from tensorboard.uploader import dev_creds -from tensorboard.uploader.proto import export_service_pb2 +from tensorboard.uploader.proto import experiment_pb2 from tensorboard.uploader.proto import export_service_pb2_grpc from tensorboard.uploader.proto import write_service_pb2_grpc from tensorboard.uploader import auth @@ -390,7 +390,7 @@ def execute(self, server_info, channel): api_client = export_service_pb2_grpc.TensorBoardExporterServiceStub( channel ) - fieldmask = export_service_pb2.ExperimentMask( + fieldmask = experiment_pb2.ExperimentMask( create_time=True, update_time=True, num_scalars=True, @@ -401,7 +401,7 @@ def execute(self, server_info, channel): count = 0 for experiment in gen: count += 1 - if not isinstance(experiment, export_service_pb2.Experiment): + if not isinstance(experiment, experiment_pb2.Experiment): url = server_info_lib.experiment_url(server_info, experiment) print(url) continue