Skip to content

Commit 77f0eac

Browse files
urmahpFelix Exner
authored andcommitted
Added loghandler, this enables the possibility for the driver to change the behavior when logging messages with this library.
1 parent 2002205 commit 77f0eac

File tree

7 files changed

+419
-19
lines changed

7 files changed

+419
-19
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ add_library(urcl SHARED
3939
src/ur/dashboard_client.cpp
4040
src/ur/tool_communication.cpp
4141
src/rtde/rtde_writer.cpp
42+
src/default_log_handler.cpp
43+
src/log.cpp
4244
)
4345
add_library(ur_client_library::urcl ALIAS urcl)
4446
target_compile_options(urcl PRIVATE -Wall -Wextra -Wno-unused-parameter)

README.md

Lines changed: 85 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ robotic manipulators.
3535
[boost](https://github.com/UniversalRobots/Universal_Robots_Client_Library/tree/boost) branch
3636
instead that requires the boost library.
3737
For the C++17 features, please use those minimum compiler versions:
38-
38+
3939
| Compiler | min. version |
4040
|-----------|--------------|
4141
| **GCC** | 7 |
4242
| **Clang** | 7 |
43-
43+
4444

4545
## Build instructions
4646
### Plain cmake
@@ -301,11 +301,87 @@ As this library was originally designed to be included into a ROS driver but als
301301
standalone library, it uses custom logging macros instead of direct `printf` or `std::cout`
302302
statements.
303303
304-
These logging macros will either be translated into `printf` statements or logging commands of
305-
[`console_bridge`](https://github.com/ros/console_bridge) if `console_bridge` is found on the system
306-
during the cmake run. In this case, the define `ROS_BUILD` will be set. When built inside a catkin
307-
workspace, logging commands are automatically translated into ROS logging commands.
304+
The macro based interface is by default using the [`DefaultLogHandler`](include/ur_client_library/default_log_handler.h)
305+
to print the logging messages as `printf` statements. It is possible to define your own log handler
306+
to change the behavior, [see create new log handler](#Create-new-log-handler) on how to.
307+
308+
### Change logging level
309+
Make sure to set the logging level in your application, as by default only messages of level
310+
WARNING or higher will be printed. See below for an example:
311+
```c++
312+
#include "ur_client_library/log.h"
313+
314+
int main(int argc, char* argv[])
315+
{
316+
urcl::setLogLevel(urcl::LogLevel::DEBUG);
317+
318+
URCL_LOG_DEBUG("Logging debug message");
319+
return 0;
320+
}
321+
```
322+
323+
### Create new log handler
324+
The logger comes with an interface [`LogHandler`](include/ur_client_library/log.h), which can be
325+
used to implement your own log handler for messages logged with this library. This can be done by
326+
inheriting from the `LogHandler class`.
327+
328+
If you want to create a new log handler in your application, you can use below example as
329+
inspiration:
330+
331+
```c++
332+
#include "ur_client_library/log.h"
333+
#include <iostream>
334+
335+
class MyLogHandler : public urcl::LogHandler
336+
{
337+
public:
338+
MyLogHandler() = default;
339+
340+
void log(const char* file, int line, urcl::LogLevel loglevel, const char* log) override
341+
{
342+
switch (loglevel)
343+
{
344+
case urcl::LogLevel::INFO:
345+
std::cout << "INFO " << file << " " << line << ": " << log << std::endl;
346+
break;
347+
case urcl::LogLevel::DEBUG:
348+
std::cout << "DEBUG " << file << " " << line << ": " << log << std::endl;
349+
break;
350+
case urcl::LogLevel::WARN:
351+
std::cout << "WARN " << file << " " << line << ": " << log << std::endl;
352+
break;
353+
case urcl::LogLevel::ERROR:
354+
std::cout << "ERROR " << file << " " << line << ": " << log << std::endl;
355+
break;
356+
case urcl::LogLevel::FATAL:
357+
std::cout << "ERROR " << file << " " << line << ": " << log << std::endl;
358+
break;
359+
default:
360+
break;
361+
}
362+
}
363+
};
364+
365+
int main(int argc, char* argv[])
366+
{
367+
urcl::setLogLevel(urcl::LogLevel::DEBUG);
368+
std::unique_ptr<MyLogHandler> log_handler(new MyLogHandler);
369+
urcl::registerLogHandler(std::move(log_handler));
370+
371+
URCL_LOG_DEBUG("logging debug message");
372+
URCL_LOG_INFO("logging info message");
373+
return 0;
374+
}
375+
```
376+
377+
### Console_bridge
378+
If [`console_bridge`](https://github.com/ros/console_bridge) is found on the system during the
379+
cmake run, logging commands will be done by `console_bridge`. In this case, the define `ROS_BUILD`
380+
will be set. When built inside a catkin workspace, logging commands are automatically translated
381+
into ROS logging commands.
382+
383+
If you compile this library against `console_bridge`, make sure to set the logging level in your
384+
application, as by default `console_bridge` will only print messages of level WARNING or higher.
385+
See [`examples/primary_pipeline.cpp`](examples/primary_pipeline.cpp) as an example.
308386
309-
Whenever you compile this library against `console_bridge`, make sure to set the logging level in
310-
your application, as by default `console_bridge` will only print messages of level WARNING or
311-
higher. See [`examples/primary_pipeline.cpp`](examples/primary_pipeline.cpp) as an example.
387+
The ROS logger will be moved to the ROS driver in a future release.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// -- BEGIN LICENSE BLOCK ----------------------------------------------
2+
// Copyright 2021 Universal Robots A/S
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
// All source code contained in and/or linked to in this message (the “Source Code”) is subject to the copyright of
17+
// Universal Robots A/S and/or its licensors. THE SOURCE CODE IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EXPRESS
18+
// OR IMPLIED, INCLUDING – BUT NOT LIMITED TO – WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
19+
// NONINFRINGEMENT. USE OF THE SOURCE CODE IS AT YOUR OWN RISK AND UNIVERSAL ROBOTS A/S AND ITS LICENSORS SHALL, TO THE
20+
// MAXIMUM EXTENT PERMITTED BY LAW, NOT BE LIABLE FOR ANY ERRORS OR MALICIOUS CODE IN THE SOURCE CODE, ANY THIRD-PARTY
21+
// CLAIMS, OR ANY OTHER CLAIMS AND DAMAGES, INCLUDING INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR PUNITIVE DAMAGES,
22+
// OR ANY LOSS OF PROFITS, EXPECTED SAVINGS, OR REVENUES, WHETHER INCURRED DIRECTLY OR INDIRECTLY, OR ANY LOSS OF DATA,
23+
// USE, GOODWILL, OR OTHER INTANGIBLE LOSSES, RESULTING FROM YOUR USE OF THE SOURCE CODE. You may make copies of the
24+
// Source Code for use in connection with a Universal Robots or UR+ product, provided that you include (i) an
25+
// appropriate copyright notice (“© [the year in which you received the Source Code or the Source Code was first
26+
// published, e.g. “2021”] Universal Robots A/S and/or its licensors”) along with the capitalized section of this notice
27+
// in all copies of the Source Code. By using the Source Code, you agree to the above terms. For more information,
28+
// please contact [email protected].
29+
// -- END LICENSE BLOCK ------------------------------------------------
30+
31+
#pragma once
32+
33+
#include "ur_client_library/log.h"
34+
35+
namespace urcl
36+
{
37+
/*!
38+
* \brief LogHandler object for default handling of logging messages.
39+
* This class is used when no other LogHandler is registered
40+
*/
41+
class DefaultLogHandler : public LogHandler
42+
{
43+
public:
44+
/*!
45+
* \brief Construct a new DefaultLogHandler object
46+
*/
47+
DefaultLogHandler();
48+
49+
/*!
50+
* \brief Function to log a message
51+
*
52+
* \param file The log message comes from this file
53+
* \param line The log message comes from this line
54+
* \param loglevel Indicates the severity of the log message
55+
* \param log Log message
56+
*/
57+
void log(const char* file, int line, LogLevel loglevel, const char* log) override;
58+
};
59+
60+
} // namespace urcl

include/ur_client_library/log.h

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#pragma once
2020
#include <inttypes.h>
21+
#include <memory>
2122

2223
#ifdef ROS_BUILD
2324
#include <console_bridge/console.h>
@@ -30,10 +31,75 @@
3031

3132
#else
3233

33-
#define URCL_LOG_DEBUG(format, ...) printf("[DEBUG]: " format "\n", ##__VA_ARGS__)
34-
#define URCL_LOG_WARN(format, ...) printf("[WARNING]: " format "\n", ##__VA_ARGS__)
35-
#define URCL_LOG_INFO(format, ...) printf("[INFO]: " format "\n", ##__VA_ARGS__)
36-
#define URCL_LOG_ERROR(format, ...) printf("[ERROR]: " format "\n", ##__VA_ARGS__)
37-
#define URCL_LOG_FATAL(format, ...) printf("[FATAL]: " format "\n", ##__VA_ARGS__)
34+
#define URCL_LOG_DEBUG(...) urcl::log(__FILE__, __LINE__, urcl::LogLevel::DEBUG, __VA_ARGS__)
35+
#define URCL_LOG_WARN(...) urcl::log(__FILE__, __LINE__, urcl::LogLevel::WARN, __VA_ARGS__)
36+
#define URCL_LOG_INFO(...) urcl::log(__FILE__, __LINE__, urcl::LogLevel::INFO, __VA_ARGS__)
37+
#define URCL_LOG_ERROR(...) urcl::log(__FILE__, __LINE__, urcl::LogLevel::ERROR, __VA_ARGS__)
38+
#define URCL_LOG_FATAL(...) urcl::log(__FILE__, __LINE__, urcl::LogLevel::FATAL, __VA_ARGS__)
3839

3940
#endif
41+
42+
namespace urcl
43+
{
44+
/*!
45+
* \brief Different log levels
46+
*/
47+
enum class LogLevel
48+
{
49+
DEBUG = 0,
50+
INFO,
51+
WARN,
52+
ERROR,
53+
FATAL,
54+
NONE
55+
};
56+
57+
/*!
58+
* \brief Inherit from this class to change the behavior when logging messages.
59+
*/
60+
class LogHandler
61+
{
62+
public:
63+
virtual ~LogHandler() = default;
64+
/*!
65+
* \brief Function to log a message
66+
*
67+
* \param file The log message comes from this file
68+
* \param line The log message comes from this line
69+
* \param loglevel Indicates the severity of the log message
70+
* \param log Log message
71+
*/
72+
virtual void log(const char* file, int line, LogLevel loglevel, const char* log) = 0;
73+
};
74+
75+
/*!
76+
* \brief Register a new LogHandler object, for handling log messages.
77+
*
78+
* \param loghandler Pointer to the new object
79+
*/
80+
void registerLogHandler(std::unique_ptr<LogHandler> loghandler);
81+
82+
/*!
83+
* \brief Unregister current log handler, this will enable default log handler.
84+
*/
85+
void unregisterLogHandler();
86+
87+
/*!
88+
* \brief Set log level this will disable messages with lower log level.
89+
*
90+
* \param level desired log level
91+
*/
92+
void setLogLevel(LogLevel level);
93+
94+
/*!
95+
* \brief Log a message, this is used internally by the macros to unpack the log message.
96+
* Use the macros instead of this function directly.
97+
*
98+
* \param file The log message comes from this file
99+
* \param line The log message comes from this line
100+
* \param level Severity of the log message
101+
* \param fmt Format string
102+
*/
103+
void log(const char* file, int line, LogLevel level, const char* fmt, ...);
104+
105+
} // namespace urcl

src/default_log_handler.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// -- BEGIN LICENSE BLOCK ----------------------------------------------
2+
// Copyright 2021 Universal Robots A/S
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
// All source code contained in and/or linked to in this message (the “Source Code”) is subject to the copyright of
17+
// Universal Robots A/S and/or its licensors. THE SOURCE CODE IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EXPRESS
18+
// OR IMPLIED, INCLUDING – BUT NOT LIMITED TO – WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
19+
// NONINFRINGEMENT. USE OF THE SOURCE CODE IS AT YOUR OWN RISK AND UNIVERSAL ROBOTS A/S AND ITS LICENSORS SHALL, TO THE
20+
// MAXIMUM EXTENT PERMITTED BY LAW, NOT BE LIABLE FOR ANY ERRORS OR MALICIOUS CODE IN THE SOURCE CODE, ANY THIRD-PARTY
21+
// CLAIMS, OR ANY OTHER CLAIMS AND DAMAGES, INCLUDING INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR PUNITIVE DAMAGES,
22+
// OR ANY LOSS OF PROFITS, EXPECTED SAVINGS, OR REVENUES, WHETHER INCURRED DIRECTLY OR INDIRECTLY, OR ANY LOSS OF DATA,
23+
// USE, GOODWILL, OR OTHER INTANGIBLE LOSSES, RESULTING FROM YOUR USE OF THE SOURCE CODE. You may make copies of the
24+
// Source Code for use in connection with a Universal Robots or UR+ product, provided that you include (i) an
25+
// appropriate copyright notice (“© [the year in which you received the Source Code or the Source Code was first
26+
// published, e.g. “2021”] Universal Robots A/S and/or its licensors”) along with the capitalized section of this notice
27+
// in all copies of the Source Code. By using the Source Code, you agree to the above terms. For more information,
28+
// please contact [email protected].
29+
// -- END LICENSE BLOCK ------------------------------------------------
30+
31+
#include "ur_client_library/default_log_handler.h"
32+
#include <stdio.h>
33+
34+
namespace urcl
35+
{
36+
DefaultLogHandler::DefaultLogHandler() = default;
37+
38+
void DefaultLogHandler::log(const char* file, int line, LogLevel loglevel, const char* log)
39+
{
40+
switch (loglevel)
41+
{
42+
case LogLevel::INFO:
43+
printf("%s%s %i: %s \n", "INFO ", file, line, log);
44+
break;
45+
case LogLevel::DEBUG:
46+
printf("%s%s %i: %s \n", "DEBUG ", file, line, log);
47+
break;
48+
case LogLevel::WARN:
49+
printf("%s%s %i: %s \n", "WARN ", file, line, log);
50+
break;
51+
case LogLevel::ERROR:
52+
printf("%s%s %i: %s \n", "ERROR ", file, line, log);
53+
break;
54+
case LogLevel::FATAL:
55+
printf("%s%s %i: %s \n", "FATAL ", file, line, log);
56+
break;
57+
default:
58+
break;
59+
}
60+
}
61+
62+
} // namespace urcl

0 commit comments

Comments
 (0)