# Consolidate ROS logging with Viam

Felix Reichenbach

Solutions Engineer

.png)

In the last [blog post](/content/post/ros-robots-mobile-pathway/index.html), we looked into how **Viam can be integrated with ROS 2** and how to **connect a Flutter app for remote control**. In this blog, I wanted to take a look at **monitoring and debugging ROS 2 logging** with the Viam cloud platform web UI.

The use case I had in my mind was when a **fleet is spread across many different places and networks** and you are looking for a **cloud-based single pane of glass** to see what’s going on with your robots. The Viam cloud platform has a built-in view for log data, so the goal was to figure out how easy it would be to bring **ROS logging messages** into it.

After a bit of research on how ROS 2 handles logging, I learned that there are basically **two options to access log messages**: there are the usual log files, but there are also **ROS topics providing holistic access to log data across your robots' components**.

While it would be easy and straightforward to upload any type of file via the [Viam Data Manager](https://docs.viam.com/services/data/) to the Viam cloud platform, it wouldn’t directly help me achieve my goal of **viewing a real-time continuous stream of log messages**. Also, I intended to use **Viam’s log viewer UI**, including its **filter and search features**, as log information can be overwhelming and those features definitely make the process of analyzing and debugging much easier.

Therefore, I decided to go down the road of using the **preexisting ROS 2 integration module** to get the logging data from the “/rosout” topic and **develop a little service**. This service will simply **take the ROS messages, map them to Viam messages, and log them through the Viam logger,** just like any other logging that happens within Viam. This allows me to use all of Viam's cloud platform features without any additional effort.

_Image: Viam ROS 2 Logger Architecture_

As has been mentioned in earlier blog posts, Viam uses the [concept of **modular resources**](/content/post/the-road-to-the-future-is-paved-with-viam/index.html). Resources in this context are either **components** or **services**. While components represent hardware devices, services are used for software functionality. You can **combine or bundle multiple resources into a so-called module**, which makes it easy to deploy, especially through our [recently released **Viam Registry**](/content/post/announcing-the-viam-modular-registry/index.html).

Since we had already created a ROS 2 Integration module in the previous [Integrate Your ROS 2 Robot with Viam blog](/content/post/integrate-your-ros2-robot-with-viam/index.html), all I had to do now was **add a service resource**.

**Creating a new service type is not complicated**, and consists of three steps:

- **Defining the service APIs** through protobuf
- Implementing the **abstract service class and APIs**
- Implementing and registering the actual **logger service model**

## Creating the ROS 2 logger service

For most of the other modular resources, especially components, Viam already provides a variety of **standard API types** and you don’t have to go through tedious processes such as writing protobuf files. However, for my logging service, there was **no suitable type available**, which gave me the opportunity to explore what needed to be done to add **completely new resource types to Viam**, including **building a new API**.

I didn’t want to overcomplicate things, so I decided to just **add a single API,** which allowed me to **retrieve the current service configuration**, the ROS topic in current use, and the log level.

```protobuf
syntax = "proto3";
package viamlabs.service.ros2_logger.v1;
import "google/api/annotations.proto";

service ROS2LoggerService {
    rpc Status (Request) returns (Response) {
        option (google.api.http) = {
            post: "/viamlabs/api/v1/service/ros2_logger/{name}/status"
        };
    }
}

message Request {
    string name = 1;
}

message Response {
    string ros_topic = 1;
    string log_level = 2;
}
```

Since I chose **Python**, this service definition then needed to be compiled into **gRPC Python classes**, which are used to **build out the API**. While you could use protoc, I chose [Buf](https://buf.build/docs/generate/usage/), which I find much simpler. Buf generates three Python files, containing **client and server class definitions and types** to be used for **implementing the APIs**.

It is recommended to use a separate “ [api.py](https://github.com/shawnbmccarthy/viam-ros2-module)” file to implement the APIs. In my specific logger service case, and probably most other cases, it contains three classes:

- **Abstract ROS2LoggerService - Specifies the service API subtype and the signature of the status api.**
- **ROS2LoggerRPCService**-The gRPC service server definition.
- **ROS2LoggerClient**-The gRPC service client definition.

Now that the service APIs are defined, it’s time for the actual **ROS 2 Logger service model implementation**. This is basically exactly the same as if you had **created a new model of an existing type** using one of the **Viam standard resource APIs**.

You can find the **code for the implementation** in the [ros2_logger.py](https://github.com/shawnbmccarthy/viam-ros2-module) file. It’s simply **a single class** with a couple of functions defining the ROS 2 Logger service.

I was almost done, but there was still one more thing left to do. Since the Viam concept is to **configure the back-end plumbing to free up developer time for actual robot functionality**, I had to register my new service type with **Viam's built-in registry**. If you are curious how to do this, go and have a look at the __init__.py file in the [ros2_logger folder](https://github.com/shawnbmccarthy/viam-ros2-module) and the [main.py file](https://github.com/shawnbmccarthy/viam-ros2-module).

## Testing the ROS 2 logger service

The code was now complete! Now I had to see if it worked. My Turtlebot 4 was already set up, with Viam installed. All I had to do then was to copy my module folder onto the robot, and add the module and service configuration. Since it's a custom service, I simply added it directly to the RAW JSON configuration and let the Viam RDK do the rest.

```json
{
    "attributes": {
        "ros_topic": "/rosout_agg",
        "log_level": "info"
    },
    "name": "mylogger",
    "type": "ros2_logger",
    "namespace": "viamlabs",
    "model": "viamlabs:ros2:ros2_logger"
}
```

If everything had been set up correctly, it would automatically instantiate a ROS 2 Logger service. Sure enough, _voila!,_ the first messages started to arrive:

While it's great to get a lot of information about the robots, at a certain point the **data volume can become problematic**, especially in **bigger fleets**. So I have added a configuration attribute called “log_level” which accepts “debug", "info", "warn", "error" and "critical" as values. This means that for normal operations, I can set the log_level to error, which means **only error-level and messages and above are sent to the cloud backend, reducing cost.** Once I have identified that there is an actual issue which needs further investigation, I can then go ahead and change the level to info or lower and **get many more details**. Just another little thing to make life with robots a bit easier!

Stay tuned for future blog posts where we will keep extending the ROS 2 integration. If you have any questions or feedback, or want to discuss our approach in more detail, feel free to reach out!
