Skip to content

Commit

Permalink
Merge pull request #13 from GobySoft/logger
Browse files Browse the repository at this point in the history
Logger
  • Loading branch information
tsaubergine authored Jan 4, 2018
2 parents 1e52d0c + 1cd6732 commit c7b75c6
Show file tree
Hide file tree
Showing 35 changed files with 911 additions and 220 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ cmake_policy(SET CMP0009 NEW)
project(goby)

if(CMAKE_VERSION VERSION_LESS 3.1)
add_definitions(-std=c++11)
add_definitions(-std=c++14)
else()
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()

Expand Down
2 changes: 1 addition & 1 deletion src/apps/middleware/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
add_subdirectory(gobyd)

add_subdirectory(logger)
2 changes: 1 addition & 1 deletion src/apps/middleware/gobyd/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ message GobyDaemonConfig
{
optional App3Config app = 1;
optional int32 router_threads = 2 [default = 10];
optional InterProcessPortalConfig interprocess_portal = 3;
optional InterProcessPortalConfig interprocess = 3;
}
8 changes: 4 additions & 4 deletions src/apps/middleware/gobyd/gobyd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ int main(int argc, char* argv[])
goby::Daemon::Daemon()
: router_context_(new zmq::context_t(app_cfg().router_threads())),
manager_context_(new zmq::context_t(1)),
router_(*router_context_, app_cfg().interprocess_portal()),
manager_(*manager_context_, app_cfg().interprocess_portal(), router_),
router_(*router_context_, app_cfg().interprocess()),
manager_(*manager_context_, app_cfg().interprocess(), router_),
router_thread_(new std::thread([&] { router_.run(); })),
manager_thread_(new std::thread([&] { manager_.run(); }))
{
if(!app_cfg().interprocess_portal().has_platform())
if(!app_cfg().interprocess().has_platform())
{
glog.is(WARN) && glog << "Using default platform name of " << app_cfg().interprocess_portal().platform() << std::endl;
glog.is(WARN) && glog << "Using default platform name of " << app_cfg().interprocess().platform() << std::endl;
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/apps/middleware/logger/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS config.proto)

add_executable(goby_logger logger.cpp ${PROTO_SRCS} ${PROTO_HDRS})
target_link_libraries(goby_logger goby_middleware)
16 changes: 16 additions & 0 deletions src/apps/middleware/logger/config.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import "goby/common/protobuf/app3.proto";
import "goby/middleware/protobuf/interprocess_config.proto";

package goby.protobuf;

message LoggerConfig
{
optional goby.protobuf.App3Config app = 1;
optional goby.protobuf.InterProcessPortalConfig interprocess = 2;

required string log_dir = 3;

optional string type_regex = 4 [default = ".*"];
optional string group_regex = 5 [default = ".*"];
}

107 changes: 107 additions & 0 deletions src/apps/middleware/logger/logger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>

#include "goby/middleware/single-thread-application.h"
#include "goby/middleware/log.h"
#include "goby/common/time.h"

#include "config.pb.h"

using goby::glog;
using namespace goby::common::logger;

void signal_handler(int sig);

namespace goby
{

class Logger : public goby::SingleThreadApplication<protobuf::LoggerConfig>
{
public:
Logger() :
goby::SingleThreadApplication<protobuf::LoggerConfig>(1*boost::units::si::hertz),
log_file_path_(std::string(cfg().log_dir() + "/" + cfg().interprocess().platform() + "_" + goby::common::goby_file_timestamp() + ".goby")),
log_(log_file_path_.c_str(), std::ofstream::binary)
{
if(!log_.is_open())
glog.is(DIE) && glog << "Failed to open log in directory: " << cfg().log_dir() << std::endl;

namespace sp = std::placeholders;
interprocess().subscribe_regex(std::bind(&Logger::log, this, sp::_1, sp::_2, sp::_3, sp::_4),
{goby::MarshallingScheme::ALL_SCHEMES},
cfg().type_regex(),
cfg().group_regex());
}

~Logger()
{
log_.close();
// set read only
chmod(log_file_path_.c_str(), S_IRUSR | S_IRGRP);
}

void log(const std::vector<unsigned char>& data, int scheme, const std::string& type, const Group& group);
void loop() override
{
if(do_quit) quit();
}


static std::atomic<bool> do_quit;

private:
std::string log_file_path_;
std::ofstream log_;
};
}

std::atomic<bool> goby::Logger::do_quit {false};


int main(int argc, char* argv[])
{
// block signals from all but this main thread
sigset_t new_mask;
sigfillset(&new_mask);
sigset_t old_mask;
pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);

std::thread t(std::bind(goby::run<goby::Logger>, argc, argv));

// unblock signals
sigset_t empty_mask;
sigemptyset(&empty_mask);
pthread_sigmask(SIG_SETMASK, &empty_mask, 0);

struct sigaction action;
action.sa_handler = &signal_handler;

// register the usual quitting signals
sigaction(SIGINT, &action, 0);
sigaction(SIGTERM, &action, 0);
sigaction(SIGQUIT, &action, 0);

// wait for the app to quit
t.join();

return 0;
}

void signal_handler(int sig)
{
goby::Logger::do_quit = true;
}


void goby::Logger::log(const std::vector<unsigned char>& data, int scheme, const std::string& type, const Group& group)
{
glog.is(DEBUG1) && glog << "Received " << data.size() << " bytes to log to [scheme, type, group] = [" << scheme << ", " << type << ", " << group << "]" << std::endl;

LogEntry entry(data, scheme, type, group);

// TODO: add logger hook
// plugin.log(entry);

entry.serialize(&log_);
}
19 changes: 9 additions & 10 deletions src/common/application_base3.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,11 @@

namespace goby
{
/// \brief Run a Goby application derived from MinimalApplicationBase.
/// blocks caller until MinimalApplicationBase::__run() returns
/// \param argc same as int main(int argc, char* argv)
/// \param argv same as int main(int argc, char* argv)
/// \return same as int main(int argc, char* argv)

/// \brief Run a Goby application
/// blocks caller until ```__run()``` returns
/// \param argc same as ```int main(int argc, char* argv)```
/// \param argv same as ```int main(int argc, char* argv)```
/// \return same as ```int main(int argc, char* argv)```
template<typename App>
int run(int argc, char* argv[]);

Expand All @@ -55,7 +54,7 @@ namespace goby
class ApplicationBase3
{
public:
ApplicationBase3();
ApplicationBase3(bool check_required_configuration = true);
virtual ~ApplicationBase3() { }

protected:
Expand All @@ -66,7 +65,7 @@ namespace goby
virtual void quit() { alive_ = false; }

/// \brief Accesses configuration object passed at launch
const Config& app_cfg() { return cfg_; }
Config& app_cfg() { return cfg_; }

const std::chrono::system_clock::time_point& start_time() const
{ return start_time_; }
Expand Down Expand Up @@ -108,7 +107,7 @@ template<typename Config>
char** goby::common::ApplicationBase3<Config>::argv_ = 0;

template<typename Config>
goby::common::ApplicationBase3<Config>::ApplicationBase3()
goby::common::ApplicationBase3<Config>::ApplicationBase3(bool check_required_configuration)
: alive_(true)
{
using goby::glog;
Expand All @@ -122,7 +121,7 @@ goby::common::ApplicationBase3<Config>::ApplicationBase3()
try
{
std::string application_name;
common::ConfigReader::read_cfg(argc_, argv_, &cfg_, &application_name, &od, &var_map);
common::ConfigReader::read_cfg(argc_, argv_, &cfg_, &application_name, &od, &var_map, check_required_configuration);

__set_application_name(application_name);
// incorporate some parts of the AppBaseConfig that are common
Expand Down
5 changes: 3 additions & 2 deletions src/common/configuration_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ void goby::common::ConfigReader::read_cfg(int argc,
google::protobuf::Message* message,
std::string* application_name,
boost::program_options::options_description* od_all,
boost::program_options::variables_map* var_map)
boost::program_options::variables_map* var_map,
bool check_required_configuration /*= true*/)
{
if(!argv) return;

Expand Down Expand Up @@ -170,7 +171,7 @@ void goby::common::ConfigReader::read_cfg(int argc,
}

// now the proto message must have all required fields
if(!message->IsInitialized())
if(check_required_configuration && !message->IsInitialized())
{
std::vector< std::string > errors;
message->FindInitializationErrors(&errors);
Expand Down
3 changes: 2 additions & 1 deletion src/common/configuration_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ namespace goby
google::protobuf::Message* message,
std::string* application_name,
boost::program_options::options_description* od_all,
boost::program_options::variables_map* var_map);
boost::program_options::variables_map* var_map,
bool check_required_configuration = true);

static void get_protobuf_program_options(
boost::program_options::options_description& po_desc,
Expand Down
1 change: 1 addition & 0 deletions src/middleware/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(SRC
transport-interprocess-zeromq.cpp
transport-intervehicle.cpp
transport-interfaces.cpp
log.cpp
${PROTO_SRCS} ${PROTO_HDRS}
)

Expand Down
17 changes: 9 additions & 8 deletions src/middleware/group.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ namespace goby
public:
constexpr Group(const char* c = "") : c_(c) { }
constexpr Group(int i) : i_(i) { }
constexpr operator int() const { return i_; }

constexpr int numeric() const { return i_; }
constexpr const char* c_str() const { return c_; }


operator std::string() const
{
if(c_ != nullptr) return std::string(c_);
Expand All @@ -35,7 +35,7 @@ namespace goby
template<const Group& group>
void check_validity()
{
static_assert((int(group) != 0) || (group.c_str()[0] != '\0'), "goby::Group must have non-zero length string or non-zero integer value.");
static_assert((group.numeric() != 0) || (group.c_str()[0] != '\0'), "goby::Group must have non-zero length string or non-zero integer value.");
}

inline void check_validity_runtime(const Group& group)
Expand All @@ -51,11 +51,12 @@ namespace goby
{
public:
DynamicGroup(const std::string& s) : s_(new std::string(s))
{
Group::set_c_str(s_->c_str());
}
DynamicGroup(int i) : Group(i) { }
{
Group::set_c_str(s_->c_str());
}

DynamicGroup(int i) : Group(i) { }

private:
std::unique_ptr<const std::string> s_;
};
Expand Down
7 changes: 7 additions & 0 deletions src/middleware/log.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "log.h"

boost::bimap<std::string, goby::uint<goby::LogEntry::group_bytes_>::type> goby::LogEntry::groups_;
boost::bimap<std::string, goby::uint<goby::LogEntry::type_bytes_>::type> goby::LogEntry::types_;

goby::uint<goby::LogEntry::group_bytes_>::type goby::LogEntry::group_index_(1);
goby::uint<goby::LogEntry::type_bytes_>::type goby::LogEntry::type_index_(1);
Loading

0 comments on commit c7b75c6

Please sign in to comment.