.. _bag-record: .. _tool-record: ============ bag record ============ .. program:: bag record Synopsis ======== :samp:`bag record {[OPTIONS]} -o {OUTPUT} {[URI1]} {[URI2 ...]}` Description =========== The :program:`bag record` program can be used to capture certain :ref:`RSB ` :term:`events ` in a running system and store them into a :term:`log file` for later analysis, further processing or replay. .. seealso:: :ref:`rsb:common-options` The usual RSB-related commandline options are accepted. :ref:`rsb:idl-options` The usual IDL-related commandline options are accepted. .. option:: --output-file OUTPUT, -o OUTPUT Write captured :term:`events ` to :term:`log file` :samp:`{OUTPUT}`. The file format is determined based on the file type (which is determined based on the file extension). Examples of supported formats and corresponding file extensions are * ``.tide``: TIDELog * ``.eaf``: Elan .. tip:: The output of :option:`common --help-for` ``all`` includes a list of supported file formats. .. option:: --force Should :samp:`{OUTPUT}` be overwritten in case it already exists? .. option:: --index-timestamp NAME Use the timestamp named :samp:`{NAME}` to index :term:`events ` in the created :term:`log file`. The default timestamp is "send". .. option:: --channel-allocation SPEC, -a SPEC Allocate :term:`channels ` for received :term:`events ` in the output :term:`log file` according to the strategy designated by :samp:`{SPEC}` which has to be of the form:: KIND KEY1 VALUE1 KEY2 VALUE2 ... where keys and values depend on :samp:`{KIND}` and are optional in most cases. The default channel allocation strategy is ``scope-and-type``. The following strategies are currently supported: ``scope-and-type`` This strategy allocates a separate :term:`channel` for each combination of :term:`scope` and :term:`wire schema` as :term:`events ` are received: the :term:`channel` allocation for a given combination is performed when the first :term:`event` exhibiting that combination is received. :term:`Channel` names produced by this strategy are of the form :samp:`{SCOPE}:{TYPE}` where :samp:`{SCOPE}` is the :term:`scope` string of the :term:`events ` :term:`scope` and :samp:`{TYPE}` is the :term:`wire schema` string, i.e. a string designating the type of the :term:`event payload` (See :ref:`types`). For example, an :term:`event` on :term:`scope` ``/foo/bar/`` with a protocol buffer :term:`payload` and :term:`wire schema` ``.rst.vision.Image`` would be stored in a :term:`channel` called ``/foo/bar/:.rst.vision.Image``. Examples: .. code-block:: sh -a scope-and-type .. tip:: Use the :option:`common --help-for` ``channel-strategies`` or :option:`common --help-for` ``all`` options to display the full help text, including available strategies and their respective parameters, for this item. .. option:: --flush-strategy SPEC Flush buffers (e.g. event and indices) according strategy designated by :samp:`{SPEC}` which has to be of one of the forms:: KIND KEY1 VALUE1 KEY2 VALUE2 ... OR (SPEC) (SPEC) ... AND (SPEC) (SPEC) ... NOT (SPEC) where keys and values depend on :samp:`{KIND}` and are optional in most cases. The default flushing strategy is ``property-limit :property :length/bytes :limit 33554432`` which corresponds to flushing buffers once they reach a size of 32 MB. Examples: .. code-block:: sh --flush-strategy 'property-limit :property :length/bytes :limit 16777216' Flush buffers once they reach a size of 16 MB. .. code-block:: sh --flush-strategy 'property-limit :property :length/entries :limit 100' Flush buffers once they reach 100 entries. .. code-block:: sh --flush-strategy 'property-limit :property :time-to-last-write :limit 5' Flush buffers when the most recent write was 5 or more seconds ago. .. code-block:: sh --flush-strategy 'or (:property-limit :property :time-to-last-write :limit 5) (:property-limit :property :length/bytes :limit 33554432)' Flush buffers when they reach a size of 32 MB or the most recent write was 5 or more seconds ago. .. tip:: Use the :option:`common --help-for` ``flush-strategies`` or :option:`common --help-for` ``all`` options to display the full help text, including available strategies and their respective parameters, for this item. .. option:: --control-uri URI, -c URI Expose an RPC interface for remote-controlling the recording process under :samp:`{URI}`. See `Remote Control`_ for details. .. important:: Supplying this option causes :program:`bag record` to start in a suspended state. The recording has to be started using the :js:func:`start`. .. option:: --introspection-survey BOOLEAN Perform an :term:`introspection` survey at the beginning of the :ref:`recording` to ensure it contains a complete snapshot of the system structure from which incremental changes can be tracked. Recording Events ================ Some general remarks regarding recording of :ref:`RSB ` :term:`events ` using :program:`bag record`: * The specified output file into which :term:`events ` should be recorded, should not already exist * If an empty file of the given name exists, it will be used for recording * If a non-empty file of the given name exists, it will be extended as long as it does not already contain any of the channels being recorded * The recording process can be terminated gracefully by sending one of ``SIGINT`` and ``SIGTERM`` to the :program:`bag record` process .. tip:: For details regarding the URI syntax involved in :term:`transport` and :term:`channel` specifications, see :ref:`uri-schema`. .. _bag-record-remote-control: Remote Control ============== :program:`bag record` can expose an `RPC`_ interface that allows starting and stopping the recording, opening and closing output :term:`log files ` and terminating the recording process. This feature is enabled using the :option:`--control-uri` commandline option. An URI has to be supplied as an argument of the option to configure the :term:`scope` and :term:`transport` through which the RPC interface should be exposed. The remote interface consists of two parts: 1. an :term:`event`\ -based interface for change notification 2. a request-reply interface for manipulating the recording. :term:`Event`\ -based part: State changes are communicated using an :term:`event`\ -based interface below the :term:`scope` :samp:`{CONTROL-SCOPE}/state` with the following :term:`subscopes `: :samp:`{CONTROL-SCOPE}/state/ready` : ``void`` An :term:`event` without :term:`payload` is published on this :term:`scope` when the recording and its remote interface become available. :samp:`{CONTROL-SCOPE}/state/terminated` : ``void`` An :term:`event` without :term:`payload` is published on this :term:`scope` when the remote interface terminates. :samp:`{CONTROL-SCOPE}/state/open` : ``string`` An :term:`event` carrying the name of the currently opened :term:`log file` as its :term:`payload` is published on this :term:`scope` when a :term:`log file` is newly opened or a recording is stopped. :samp:`{CONTROL-SCOPE}/state/started` : ``string`` An :term:`event` carrying the name of the currently opened :term:`log file` as its :term:`payload` is published on this :term:`scope` when a recording is started. The following state transitions can occur: .. digraph:: server_states rankdir=LR fontname=Arial fontsize=11 node [fontsize=11,fontname=Arial] edge [fontsize=11,fontname=Arial] start [shape = point] start -> ready ready -> open ready -> terminated open -> ready open -> started started -> open The :ref:`request/reply ` part consists of the following methods: .. js:function:: isstarted() :returns: ``true`` or ``false``. Return ``true`` if a :term:`log file` has been opened for recording and recording is currently in progress and ``false`` otherwise. .. js:function:: start() Restart recording - initially or after it has been stopped. Only applicable if a :term:`log file` has been opened. .. js:function:: stop() Stop recording allowing it to be restarted later. Only applicable if a :term:`log file` has been opened. .. js:function:: isopen() :returns: ``false`` or path of open :term:`log file`. If a :term:`log file` has been opened for recording, return its path as a string. Otherwise return ``false``. .. js:function:: open(filename) :param string filename: name of the :term:`log file` into which the recording should write. Open :samp:`{filename}` and prepare recording :term:`events `. However, do not actually start recording until ``start`` is called. Only applicable if no :term:`log file` is currently open. .. js:function:: ensuredirectoryandopen(filename) :param string filename: name of the :term:`log file` into which the recording should write. Like :js:func:`open` but create the directories on the path to the specified file, if necessary. .. js:function:: close() Close the current :term:`log file`. Only applicable if a :term:`log file` has been opened. .. js:function:: terminate() Terminate the recording process and the program. Examples ======== * .. code-block:: sh $ bag record -o /tmp/nao.tide 'spread:/nao/vision/top?name=4803' 'spread:/nao/audio/all?name=4803' 'spread:/nao/proprioception?name=4803' The resulting :term:`log file` will (unless a different :term:`channel` allocation is specified) contain one :term:`channel` for each of the three :ref:`RSB ` :term:`scopes `. * .. code-block:: sh $ bag record -c 'spread:/control' -o /tmp/everything.tide spread: The above command starts a :program:`bag record` process configured to record :term:`events ` into the :term:`log file` :file:`/tmp/everything.tide`. Since the :option:`--control-uri` commandline option has been used, :program:`bag record` does not record immediately after starting, but wait for instructions via `RPC`_ . Therefore, without terminating the above :program:`bag record` process, the :ref:`call ` program can be used to issue commands: .. code-block:: sh $ call 'spread:/control/start()' # start recording [...] $ call 'spread:/control/stop()' # stop recording $ call 'spread:/control/terminate()' # terminate bag record * .. code-block:: sh $ bag record --output-file /tmp/nao.tide --on-error continue --flush-strategy '(:property-limit :property :time-to-last-write :limit 1)' 'socket:/camera1' The above example demonstrates non-default error and flushing behavior: :program:`bag record` is instructed to continue in case of errors and flush buffers every second. Something like this could make sense when the recorded data is hard to produce.