Skip to content

Commit

Permalink
feat: add a logging interface, dependency injectable loggers (#233)
Browse files Browse the repository at this point in the history
* feat(loggers): add a new generic dependency-injectable logger class

Signed-off-by: Max SCHMELLER <[email protected]>

* feat(loggers): add a console logger implementation

Signed-off-by: Max SCHMELLER <[email protected]>

* feat(loggers): add an rclcpp logger implementation

Signed-off-by: Max SCHMELLER <[email protected]>

* chore(logger): remove useless rule-of-five boilerplate

Signed-off-by: Max SCHMELLER <[email protected]>

---------

Signed-off-by: Max SCHMELLER <[email protected]>
  • Loading branch information
mojomex authored Nov 25, 2024
1 parent 658aab1 commit 77b4c6c
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 0 deletions.
55 changes: 55 additions & 0 deletions nebula_common/include/nebula_common/loggers/console_logger.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2024 TIER IV, Inc.
//
// 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.

#pragma once

#include "nebula_common/loggers/logger.hpp"

#include <cstdio>
#include <iostream>
#include <memory>
#include <ostream>
#include <string>
#include <utility>

namespace nebula::drivers::loggers
{

class ConsoleLogger : public Logger
{
public:
explicit ConsoleLogger(std::string name) : name_(std::move(name)) {}

void debug(const std::string & message) override { print_tagged(std::cout, "DEBUG", message); }
void info(const std::string & message) override { print_tagged(std::cout, "INFO", message); }
void warn(const std::string & message) override { print_tagged(std::cerr, "WARN", message); }
void error(const std::string & message) override { print_tagged(std::cerr, "ERROR", message); }

std::shared_ptr<Logger> child(const std::string & name) override
{
return std::make_shared<ConsoleLogger>(name_ + "." + name);
}

private:
std::string name_;

void print_tagged(std::ostream & os, const std::string & severity, const std::string & message)
{
// In multithreaded logging, building the string first (... + ...) and then shifting to the
// stream will ensure that no other logger outputs between string fragments
os << ("[" + name_ + "][" + severity + "] " + message) << std::endl;
}
};

} // namespace nebula::drivers::loggers
44 changes: 44 additions & 0 deletions nebula_common/include/nebula_common/loggers/logger.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2024 TIER IV, Inc.
//
// 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.

#pragma once

#include <memory>
#include <sstream>
#include <string>

#define NEBULA_LOG_STREAM(log_func, stream_args) \
{ \
std::stringstream ss{}; \
ss << stream_args; \
log_func(ss.str()); \
}

namespace nebula::drivers::loggers
{

class Logger
{
public:
virtual ~Logger() = default;

virtual void debug(const std::string & message) = 0;
virtual void info(const std::string & message) = 0;
virtual void warn(const std::string & message) = 0;
virtual void error(const std::string & message) = 0;

virtual std::shared_ptr<Logger> child(const std::string & name) = 0;
};

} // namespace nebula::drivers::loggers
59 changes: 59 additions & 0 deletions nebula_ros/include/nebula_ros/common/rclcpp_logger.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2024 TIER IV, Inc.
//
// 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.

#pragma once

#include <nebula_common/loggers/logger.hpp>
#include <rclcpp/logger.hpp>
#include <rclcpp/logging.hpp>

#include <memory>
#include <string>

namespace nebula::drivers::loggers
{

class RclcppLogger : public Logger
{
public:
explicit RclcppLogger(const std::string & name) : underlying_logger_(rclcpp::get_logger(name)) {}
explicit RclcppLogger(const rclcpp::Logger & underlying) : underlying_logger_(underlying) {}

void debug(const std::string & message) override
{
RCLCPP_DEBUG_STREAM(underlying_logger_, message);
}
void info(const std::string & message) override
{
RCLCPP_INFO_STREAM(underlying_logger_, message);
}
void warn(const std::string & message) override
{
RCLCPP_WARN_STREAM(underlying_logger_, message);
}
void error(const std::string & message) override
{
RCLCPP_ERROR_STREAM(underlying_logger_, message);
}

std::shared_ptr<Logger> child(const std::string & name) override
{
return std::make_shared<RclcppLogger>(underlying_logger_.get_child(name));
}

private:
rclcpp::Logger underlying_logger_;
};

} // namespace nebula::drivers::loggers

0 comments on commit 77b4c6c

Please sign in to comment.