# How to log Time Series Data

This guide describes how to configure an AuterionOS app to store time series data in flight logs. It assumes you have the following file structure for your app.

```markdown
├── auterion-app.yml
├── Dockerfile
├── msgs_ws/
│   └── src/
│       ├── custom_namespace_msgs/
│       │   └── msg/
│               └── CustomTopic.msg
├── README.md
├── ros_ws/
│   └── src/
│       └── my_application/
│           └── src/
│               └── main.cpp
```

{% hint style="info" %}
Check the app example `ros2-logging-cpp` for the full code.
{% endhint %}

## Enable logging in the auterion-app.yml file

The first step is to add the `logging` key to the **auterion-app.yml** file. This should come after the `services` key.

Three keys can be nested below `logging`:

1. `msg-paths`
2. `subscriptions` - used for simple configuration.
3. `profiles` - used for advanced configuration.

```yaml
auterion-api-version: 3
services:
  test-app:
    ...

logging:
  msg-paths:
    ...
  subscriptions:
    ...
  profiles:
    ...
```

### The 'msg-paths' key

The `msg-paths` key defines one or more file paths to the *type definitions* of any messages to be logged.

This example app publishes messages over ROS 2 to log custom app data. It must include the path to the ROS 2 message package, which is relative with respect to the app source structure, as shown below.

```yaml
logging:
  # Paths to message definitions of logged topics
  msg-paths: [msgs_ws/src/custom_namespace_msgs] 
```

The message definitions specified in `msg-paths` can be found under `/data/app-config/logging/msgs` after the app is installed on AOS on the host filesystem of the device.

{% hint style="info" %}
Messages must not contain dynamically sized fields, like arrays or strings. Fixed-size arrays are ok
{% endhint %}

{% hint style="warning" %}
Do not use messages from standard ROS (e.g. `std_msgs`), as many of them contain dynamically sized fields (including all messages that use `std_msgs/Header`)
{% endhint %}

## Selecting the data to log

By default, app data is logged from when the vehicle arms until it disarms. The `subscriptions` key is used to specify which data is logged.

For apps with more advanced logging requirements, the `profiles` key gives more flexibility about the conditions in which data is logged (reserved for future use).

### Basic configuration: the 'subscriptions' key

The `subscriptions` key specifies a list of *messages or topics* to be logged. Each subscription entry must contain a key specifying the topic name and either

* a simple string specifying the message type, or
* a detailed object with additional properties, such as logging rates.

This example app will have some simple and some detailed subscriptions.

```yaml
logging:
  subscriptions:
    # Simple subscriptions
    /custom_topic: custom_msgs/CustomTopic
    /fmu/in/vehicle_visual_odometry: px4_msgs/VehicleOdometry
    # Detailed subscription
    /test_topic:
      type: custom_msgs/CustomTopic  # the message type
      max_rate_hz: 2                 # log this topic at 2Hz or less (downsample)
```

### Advanced configuration: the 'profiles' key

{% hint style="info" %}
This is currently not enabled
{% endhint %}

The `profiles` key allows for the customisation of which data is logged and under which conditions. Recall that the default behaviour is to log only while armed.

Two profiles can be configured:

1. `default` overrides or extends the default logging behaviour, and
2. `verbose` allows for logging additional data and/or logging in different conditions.

The available run conditions are: `always`, `never`, `while-armed` and `while-disarmed`.

When the run conditions are met, each profile generates its own ULog file in a defined directory, with its own logging rate and set of logged messages.

{% hint style="warning" %}
The `default` profile is streamed to Auterion Suite.

The logging rate of this profile must be kept low, in the order of a few KB/s.
{% endhint %}

<table><thead><tr><th width="185">Profile</th><th width="267">default</th><th>verbose</th></tr></thead><tbody><tr><td>Default condition</td><td><code>while-armed</code></td><td><code>never</code></td></tr><tr><td>Log directory</td><td><code>/data/log/flight-stack</code></td><td><code>/data/log/flight-stack-verbose</code></td></tr><tr><td>Streamed to Suite</td><td>Yes</td><td>No</td></tr><tr><td>Constrained log rate</td><td>Yes</td><td>No</td></tr></tbody></table>

The logging profiles are customised with a list of different conditions under the `when` key. Each entry in this list must have two keys:

1. `condition`: specifying when that particular configuration applies, and
2. `subscriptions`: the list of messages to be logged in that condition. The contents of this key have the same format as described in the [basic configuration](#basic-configuration-the-subscriptions-key) above.

Profile extensions will be placed in `/data/app-config/logging/profiles`.

Examples of different logging profiles are given below.

#### Example 1: Add a verbose log profile

The `verbose` profile is enabled and set to always log a custom topic at 1Hz.

```yaml
logging:
  profiles:
    verbose:
      when:
        - condition: 'always'
          subscriptions:
            # Subscriptions specific to the 'always' condition.
            /custom_topic:
              type: custom_msgs/CustomTopic
              max_rate_hz: 1
```

#### Example 2: Add a verbose profile with multiple conditions

The `verbose` profile is enabled and set to always log a custom topic at *1Hz while disarmed* and *20Hz while armed*. It additionally logs a visual odometry topic, but only while armed.

```yaml
logging:
  profiles:
    verbose:
      when:
        - condition: 'while-disarmed'
          subscriptions:
            # Subscriptions specific to the 'while-disarmed' condition.
            /custom_topic:
              type: custom_msgs/CustomTopic
              max_rate_hz: 1
        - condition: 'while-armed'
          subscriptions:
            # Subscriptions specific to the 'while-armed' condition.
            /custom_topic:
              type: custom_msgs/CustomTopic
              max_rate_hz: 20
            /fmu/in/vehicle_visual_odometry: px4_msgs/VehicleOdometry
```

#### Example 3: Override the default log profile

In the basic configuration example above, the custom and visual odometry topics were logged at full rate while armed.

In this example, that `default` profile is overridden and set to *additionally* log the custom and visual odometry messages at 1Hz while disarmed.

```yaml
logging:
  profiles:
    verbose:
      when:
        # Log the data with full rate when armed
        - condition: 'while-armed'
          subscriptions:
            /custom_topic: custom_msgs/CustomTopic
        # While disarmed, log the data at a lower rate
        - condition: 'while-disarmed'
          subscriptions:
            /custom_topic:
              type: custom_msgs/CustomTopic
              max_rate_hz: 1
```

## **Testing**

To test if it worked, after installing the app, ssh into the device. Arm the vehicle (make sure it is safe!), and monitor the log files:

```
watch 'ls -l /data/log/flight-stack | tail'
```

The last file should increase in size.

You can then check if the log contains the topic via `ulog_info /data/log/flight-stack/<file.ulg>`

## **Monitoring and Troubleshooting**

To monitor the logging activity and troubleshoot potential issues on the device, use:

```bash
journalctl -u data-logger -b -f
```

If the message is logged successfully, running `journalctl -u data-logger -b -f` should contain: `[dds_source.cpp:111] [dds] Subscriber matched update.`

## **Key Limitations**

* **Maximum Topic Size:** 65536 bytes. Ensure that messages do not exceed this size to prevent logging failures.
* **No Support for Dynamically-Sized Messages:** Static message definitions are required due to current logging limitations.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.auterion.com/app-development/app-framework/logging/logging-ros2-messages.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
