Skip to content

Commit

Permalink
Added loghandler, this enables the possibility for the driver to chan…
Browse files Browse the repository at this point in the history
…ge the behavior when logging messages with this library.
  • Loading branch information
urmahp authored and fmauch committed Mar 10, 2021
1 parent 2002205 commit 77f0eac
Show file tree
Hide file tree
Showing 7 changed files with 419 additions and 19 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ add_library(urcl SHARED
src/ur/dashboard_client.cpp
src/ur/tool_communication.cpp
src/rtde/rtde_writer.cpp
src/default_log_handler.cpp
src/log.cpp
)
add_library(ur_client_library::urcl ALIAS urcl)
target_compile_options(urcl PRIVATE -Wall -Wextra -Wno-unused-parameter)
Expand Down
94 changes: 85 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ robotic manipulators.
[boost](https://github.com/UniversalRobots/Universal_Robots_Client_Library/tree/boost) branch
instead that requires the boost library.
For the C++17 features, please use those minimum compiler versions:

| Compiler | min. version |
|-----------|--------------|
| **GCC** | 7 |
| **Clang** | 7 |


## Build instructions
### Plain cmake
Expand Down Expand Up @@ -301,11 +301,87 @@ As this library was originally designed to be included into a ROS driver but als
standalone library, it uses custom logging macros instead of direct `printf` or `std::cout`
statements.
These logging macros will either be translated into `printf` statements or logging commands of
[`console_bridge`](https://github.com/ros/console_bridge) if `console_bridge` is found on the system
during the cmake run. In this case, the define `ROS_BUILD` will be set. When built inside a catkin
workspace, logging commands are automatically translated into ROS logging commands.
The macro based interface is by default using the [`DefaultLogHandler`](include/ur_client_library/default_log_handler.h)
to print the logging messages as `printf` statements. It is possible to define your own log handler
to change the behavior, [see create new log handler](#Create-new-log-handler) on how to.
### Change logging level
Make sure to set the logging level in your application, as by default only messages of level
WARNING or higher will be printed. See below for an example:
```c++
#include "ur_client_library/log.h"
int main(int argc, char* argv[])
{
urcl::setLogLevel(urcl::LogLevel::DEBUG);
URCL_LOG_DEBUG("Logging debug message");
return 0;
}
```

### Create new log handler
The logger comes with an interface [`LogHandler`](include/ur_client_library/log.h), which can be
used to implement your own log handler for messages logged with this library. This can be done by
inheriting from the `LogHandler class`.

If you want to create a new log handler in your application, you can use below example as
inspiration:

```c++
#include "ur_client_library/log.h"
#include <iostream>

class MyLogHandler : public urcl::LogHandler
{
public:
MyLogHandler() = default;

void log(const char* file, int line, urcl::LogLevel loglevel, const char* log) override
{
switch (loglevel)
{
case urcl::LogLevel::INFO:
std::cout << "INFO " << file << " " << line << ": " << log << std::endl;
break;
case urcl::LogLevel::DEBUG:
std::cout << "DEBUG " << file << " " << line << ": " << log << std::endl;
break;
case urcl::LogLevel::WARN:
std::cout << "WARN " << file << " " << line << ": " << log << std::endl;
break;
case urcl::LogLevel::ERROR:
std::cout << "ERROR " << file << " " << line << ": " << log << std::endl;
break;
case urcl::LogLevel::FATAL:
std::cout << "ERROR " << file << " " << line << ": " << log << std::endl;
break;
default:
break;
}
}
};

int main(int argc, char* argv[])
{
urcl::setLogLevel(urcl::LogLevel::DEBUG);
std::unique_ptr<MyLogHandler> log_handler(new MyLogHandler);
urcl::registerLogHandler(std::move(log_handler));

URCL_LOG_DEBUG("logging debug message");
URCL_LOG_INFO("logging info message");
return 0;
}
```
### Console_bridge
If [`console_bridge`](https://github.com/ros/console_bridge) is found on the system during the
cmake run, logging commands will be done by `console_bridge`. In this case, the define `ROS_BUILD`
will be set. When built inside a catkin workspace, logging commands are automatically translated
into ROS logging commands.
If you compile this library against `console_bridge`, make sure to set the logging level in your
application, as by default `console_bridge` will only print messages of level WARNING or higher.
See [`examples/primary_pipeline.cpp`](examples/primary_pipeline.cpp) as an example.
Whenever you compile this library against `console_bridge`, make sure to set the logging level in
your application, as by default `console_bridge` will only print messages of level WARNING or
higher. See [`examples/primary_pipeline.cpp`](examples/primary_pipeline.cpp) as an example.
The ROS logger will be moved to the ROS driver in a future release.
60 changes: 60 additions & 0 deletions include/ur_client_library/default_log_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// -- BEGIN LICENSE BLOCK ----------------------------------------------
// Copyright 2021 Universal Robots A/S
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// All source code contained in and/or linked to in this message (the “Source Code”) is subject to the copyright of
// Universal Robots A/S and/or its licensors. THE SOURCE CODE IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING – BUT NOT LIMITED TO – WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
// NONINFRINGEMENT. USE OF THE SOURCE CODE IS AT YOUR OWN RISK AND UNIVERSAL ROBOTS A/S AND ITS LICENSORS SHALL, TO THE
// MAXIMUM EXTENT PERMITTED BY LAW, NOT BE LIABLE FOR ANY ERRORS OR MALICIOUS CODE IN THE SOURCE CODE, ANY THIRD-PARTY
// CLAIMS, OR ANY OTHER CLAIMS AND DAMAGES, INCLUDING INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR PUNITIVE DAMAGES,
// OR ANY LOSS OF PROFITS, EXPECTED SAVINGS, OR REVENUES, WHETHER INCURRED DIRECTLY OR INDIRECTLY, OR ANY LOSS OF DATA,
// USE, GOODWILL, OR OTHER INTANGIBLE LOSSES, RESULTING FROM YOUR USE OF THE SOURCE CODE. You may make copies of the
// Source Code for use in connection with a Universal Robots or UR+ product, provided that you include (i) an
// appropriate copyright notice (“© [the year in which you received the Source Code or the Source Code was first
// published, e.g. “2021”] Universal Robots A/S and/or its licensors”) along with the capitalized section of this notice
// in all copies of the Source Code. By using the Source Code, you agree to the above terms. For more information,
// please contact legal@universal-robots.com.
// -- END LICENSE BLOCK ------------------------------------------------

#pragma once

#include "ur_client_library/log.h"

namespace urcl
{
/*!
* \brief LogHandler object for default handling of logging messages.
* This class is used when no other LogHandler is registered
*/
class DefaultLogHandler : public LogHandler
{
public:
/*!
* \brief Construct a new DefaultLogHandler object
*/
DefaultLogHandler();

/*!
* \brief Function to log a message
*
* \param file The log message comes from this file
* \param line The log message comes from this line
* \param loglevel Indicates the severity of the log message
* \param log Log message
*/
void log(const char* file, int line, LogLevel loglevel, const char* log) override;
};

} // namespace urcl
76 changes: 71 additions & 5 deletions include/ur_client_library/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#pragma once
#include <inttypes.h>
#include <memory>

#ifdef ROS_BUILD
#include <console_bridge/console.h>
Expand All @@ -30,10 +31,75 @@

#else

#define URCL_LOG_DEBUG(format, ...) printf("[DEBUG]: " format "\n", ##__VA_ARGS__)
#define URCL_LOG_WARN(format, ...) printf("[WARNING]: " format "\n", ##__VA_ARGS__)
#define URCL_LOG_INFO(format, ...) printf("[INFO]: " format "\n", ##__VA_ARGS__)
#define URCL_LOG_ERROR(format, ...) printf("[ERROR]: " format "\n", ##__VA_ARGS__)
#define URCL_LOG_FATAL(format, ...) printf("[FATAL]: " format "\n", ##__VA_ARGS__)
#define URCL_LOG_DEBUG(...) urcl::log(__FILE__, __LINE__, urcl::LogLevel::DEBUG, __VA_ARGS__)
#define URCL_LOG_WARN(...) urcl::log(__FILE__, __LINE__, urcl::LogLevel::WARN, __VA_ARGS__)
#define URCL_LOG_INFO(...) urcl::log(__FILE__, __LINE__, urcl::LogLevel::INFO, __VA_ARGS__)
#define URCL_LOG_ERROR(...) urcl::log(__FILE__, __LINE__, urcl::LogLevel::ERROR, __VA_ARGS__)
#define URCL_LOG_FATAL(...) urcl::log(__FILE__, __LINE__, urcl::LogLevel::FATAL, __VA_ARGS__)

#endif

namespace urcl
{
/*!
* \brief Different log levels
*/
enum class LogLevel
{
DEBUG = 0,
INFO,
WARN,
ERROR,
FATAL,
NONE
};

/*!
* \brief Inherit from this class to change the behavior when logging messages.
*/
class LogHandler
{
public:
virtual ~LogHandler() = default;
/*!
* \brief Function to log a message
*
* \param file The log message comes from this file
* \param line The log message comes from this line
* \param loglevel Indicates the severity of the log message
* \param log Log message
*/
virtual void log(const char* file, int line, LogLevel loglevel, const char* log) = 0;
};

/*!
* \brief Register a new LogHandler object, for handling log messages.
*
* \param loghandler Pointer to the new object
*/
void registerLogHandler(std::unique_ptr<LogHandler> loghandler);

/*!
* \brief Unregister current log handler, this will enable default log handler.
*/
void unregisterLogHandler();

/*!
* \brief Set log level this will disable messages with lower log level.
*
* \param level desired log level
*/
void setLogLevel(LogLevel level);

/*!
* \brief Log a message, this is used internally by the macros to unpack the log message.
* Use the macros instead of this function directly.
*
* \param file The log message comes from this file
* \param line The log message comes from this line
* \param level Severity of the log message
* \param fmt Format string
*/
void log(const char* file, int line, LogLevel level, const char* fmt, ...);

} // namespace urcl
62 changes: 62 additions & 0 deletions src/default_log_handler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// -- BEGIN LICENSE BLOCK ----------------------------------------------
// Copyright 2021 Universal Robots A/S
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// All source code contained in and/or linked to in this message (the “Source Code”) is subject to the copyright of
// Universal Robots A/S and/or its licensors. THE SOURCE CODE IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING – BUT NOT LIMITED TO – WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
// NONINFRINGEMENT. USE OF THE SOURCE CODE IS AT YOUR OWN RISK AND UNIVERSAL ROBOTS A/S AND ITS LICENSORS SHALL, TO THE
// MAXIMUM EXTENT PERMITTED BY LAW, NOT BE LIABLE FOR ANY ERRORS OR MALICIOUS CODE IN THE SOURCE CODE, ANY THIRD-PARTY
// CLAIMS, OR ANY OTHER CLAIMS AND DAMAGES, INCLUDING INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR PUNITIVE DAMAGES,
// OR ANY LOSS OF PROFITS, EXPECTED SAVINGS, OR REVENUES, WHETHER INCURRED DIRECTLY OR INDIRECTLY, OR ANY LOSS OF DATA,
// USE, GOODWILL, OR OTHER INTANGIBLE LOSSES, RESULTING FROM YOUR USE OF THE SOURCE CODE. You may make copies of the
// Source Code for use in connection with a Universal Robots or UR+ product, provided that you include (i) an
// appropriate copyright notice (“© [the year in which you received the Source Code or the Source Code was first
// published, e.g. “2021”] Universal Robots A/S and/or its licensors”) along with the capitalized section of this notice
// in all copies of the Source Code. By using the Source Code, you agree to the above terms. For more information,
// please contact legal@universal-robots.com.
// -- END LICENSE BLOCK ------------------------------------------------

#include "ur_client_library/default_log_handler.h"
#include <stdio.h>

namespace urcl
{
DefaultLogHandler::DefaultLogHandler() = default;

void DefaultLogHandler::log(const char* file, int line, LogLevel loglevel, const char* log)
{
switch (loglevel)
{
case LogLevel::INFO:
printf("%s%s %i: %s \n", "INFO ", file, line, log);
break;
case LogLevel::DEBUG:
printf("%s%s %i: %s \n", "DEBUG ", file, line, log);
break;
case LogLevel::WARN:
printf("%s%s %i: %s \n", "WARN ", file, line, log);
break;
case LogLevel::ERROR:
printf("%s%s %i: %s \n", "ERROR ", file, line, log);
break;
case LogLevel::FATAL:
printf("%s%s %i: %s \n", "FATAL ", file, line, log);
break;
default:
break;
}
}

} // namespace urcl
Loading

0 comments on commit 77f0eac

Please sign in to comment.