diff --git a/Makefile.in b/Makefile.in index 39c6a46da..23c680d75 100644 --- a/Makefile.in +++ b/Makefile.in @@ -64,6 +64,7 @@ all clean: $(MAKE) -C test/examples/9-Domains $@ $(MAKE) -C test/examples/10-Archiving $@ $(MAKE) -C test/examples/13-Relay $@ + $(MAKE) -C test/examples/15-SpdlogDynamicConfiguration $@ # Perform each of the following in their own if block, otherwise a failure in the below make commands # won't cause the overall build to fail. @@ -131,6 +132,7 @@ test-prep: chmod 755 test/examples/13-Relay/run.sh chmod 755 test/examples/14-AnomalyDetection/train.sh chmod 755 test/examples/14-AnomalyDetection/detect.sh + chmod 755 test/examples/15-SpdlogDynamicConfiguration/run.sh test: distributable test-prep components ./test/testall.sh diff --git a/configure b/configure index 663b21dc9..8ef12edd2 100755 --- a/configure +++ b/configure @@ -6227,7 +6227,7 @@ fi CPPFLAGS="$CPPFLAGS -Wall" -ac_config_files="$ac_config_files Makefile src/api/MATLAB/Makefile src/api/cpp/Makefile src/components/cpp/Makefile src/components/cpp/Archiver/Makefile src/components/cpp/ConfigServer/Makefile src/components/cpp/LogRecorder/Makefile src/components/cpp/Playback/Makefile src/components/cpp/Relay/Makefile src/components/cpp/ServiceDirectory/Makefile src/keyvalue_parser/Makefile test/components/cpp/Makefile test/components/cpp/ServiceDirectory/Makefile test/components/cpp/ServiceDirectoryReregister/Makefile src/api/java/cpp_makefile src/api/java/java_makefile src/api/python/cpp_makefile src/api/python/Makefile test/api/cpp/Makefile test/api/java/Makefile test/api/python/Makefile test/components/cpp/ServiceDirectory/test.sh test/components/cpp/ServiceDirectoryReregister/test.sh test/api/cpp/test.sh test/api/java/test.sh test/api/python/test.sh test/examples/1-BasicDataProduct/Makefile test/examples/1-BasicDataProduct/run.sh test/examples/2-ProtobufDataProduct/Makefile test/examples/2-ProtobufDataProduct/run.sh test/examples/3-MultipleDataProduct/Makefile test/examples/3-MultipleDataProduct/run.sh test/examples/4-BasicService/Makefile test/examples/4-BasicService/run.sh test/examples/5-MiscFunctionality/Makefile test/examples/5-MiscFunctionality/run.sh test/examples/6-JavaProtobufDataProduct/Makefile test/examples/6-JavaProtobufDataProduct/run.sh test/examples/7-JavaBasicService/Makefile test/examples/7-JavaBasicService/run.sh test/examples/8-ConfigFile/Makefile test/examples/8-ConfigFile/run.sh test/examples/9-Domains/Makefile test/examples/9-Domains/run.sh test/examples/10-Archiving/Makefile test/examples/10-Archiving/run.sh test/examples/11-PythonPubSub/run.sh test/examples/11-PythonPubSub/Makefile test/examples/12-PythonBasicService/run.sh test/examples/12-PythonBasicService/Makefile test/examples/13-Relay/Makefile test/examples/13-Relay/run.sh test/examples/14-AnomalyDetection/train.sh test/examples/14-AnomalyDetection/detect.sh " +ac_config_files="$ac_config_files Makefile src/api/MATLAB/Makefile src/api/cpp/Makefile src/components/cpp/Makefile src/components/cpp/Archiver/Makefile src/components/cpp/ConfigServer/Makefile src/components/cpp/LogRecorder/Makefile src/components/cpp/Playback/Makefile src/components/cpp/Relay/Makefile src/components/cpp/ServiceDirectory/Makefile src/keyvalue_parser/Makefile test/components/cpp/Makefile test/components/cpp/ServiceDirectory/Makefile test/components/cpp/ServiceDirectoryReregister/Makefile src/api/java/cpp_makefile src/api/java/java_makefile src/api/python/cpp_makefile src/api/python/Makefile test/api/cpp/Makefile test/api/java/Makefile test/api/python/Makefile test/components/cpp/ServiceDirectory/test.sh test/components/cpp/ServiceDirectoryReregister/test.sh test/api/cpp/test.sh test/api/java/test.sh test/api/python/test.sh test/examples/1-BasicDataProduct/Makefile test/examples/1-BasicDataProduct/run.sh test/examples/2-ProtobufDataProduct/Makefile test/examples/2-ProtobufDataProduct/run.sh test/examples/3-MultipleDataProduct/Makefile test/examples/3-MultipleDataProduct/run.sh test/examples/4-BasicService/Makefile test/examples/4-BasicService/run.sh test/examples/5-MiscFunctionality/Makefile test/examples/5-MiscFunctionality/run.sh test/examples/6-JavaProtobufDataProduct/Makefile test/examples/6-JavaProtobufDataProduct/run.sh test/examples/7-JavaBasicService/Makefile test/examples/7-JavaBasicService/run.sh test/examples/8-ConfigFile/Makefile test/examples/8-ConfigFile/run.sh test/examples/9-Domains/Makefile test/examples/9-Domains/run.sh test/examples/10-Archiving/Makefile test/examples/10-Archiving/run.sh test/examples/11-PythonPubSub/run.sh test/examples/11-PythonPubSub/Makefile test/examples/12-PythonBasicService/run.sh test/examples/12-PythonBasicService/Makefile test/examples/13-Relay/Makefile test/examples/13-Relay/run.sh test/examples/14-AnomalyDetection/train.sh test/examples/14-AnomalyDetection/detect.sh test/examples/15-SpdlogDynamicConfiguration/Makefile test/examples/15-SpdlogDynamicConfiguration/run.sh " cat >confcache <<\_ACEOF diff --git a/configure.ac b/configure.ac index fa6c9dd2b..6d4c95c3b 100644 --- a/configure.ac +++ b/configure.ac @@ -293,8 +293,10 @@ AC_CONFIG_FILES([Makefile test/examples/12-PythonBasicService/Makefile test/examples/13-Relay/Makefile test/examples/13-Relay/run.sh - test/examples/14-AnomalyDetection/train.sh - test/examples/14-AnomalyDetection/detect.sh]) + test/examples/14-AnomalyDetection/train.sh + test/examples/14-AnomalyDetection/detect.sh + test/examples/15-SpdlogDynamicConfiguration/Makefile + test/examples/15-SpdlogDynamicConfiguration/run.sh]) AC_OUTPUT diff --git a/src/api/cpp/CommUtil.h b/src/api/cpp/CommUtil.h index 2c80b79b8..9296284aa 100755 --- a/src/api/cpp/CommUtil.h +++ b/src/api/cpp/CommUtil.h @@ -60,6 +60,7 @@ namespace gravity const std::string METRICS_DATA_DPID = "GravityMetricsData"; const std::string GRAVITY_SETTINGS_DPID = "GRAVITY_SETTINGS"; const std::string GRAVITY_LOGGER_DPID = "GRAVITY_LOGGER"; + const std::string SPD_LOG_CONFIG_DPID = "GravitySpdLogConfig"; } /** diff --git a/src/api/cpp/GravityNode.cpp b/src/api/cpp/GravityNode.cpp index 1ada4b286..aed8784f0 100755 --- a/src/api/cpp/GravityNode.cpp +++ b/src/api/cpp/GravityNode.cpp @@ -577,61 +577,41 @@ void GravityNode::configSpdLoggers() auto app_console_level = spdlog::level::from_str(StringToLowerCase(getStringParam("AppConsoleLogLevel", "off"))); auto app_publish_level = spdlog::level::from_str(StringToLowerCase(getStringParam("AppNetworkLogLevel", "off"))); - bool has_gravity_file_logger = gravity_file_level != SPDLOG_LEVEL_OFF; - bool has_app_file_logger = app_file_level != SPDLOG_LEVEL_OFF; - bool has_app_console_logger = app_console_level != SPDLOG_LEVEL_OFF; - bool has_app_publish_logger = app_publish_level != SPDLOG_LEVEL_OFF; - - bool has_app_logger = has_app_file_logger || has_app_console_logger || has_app_publish_logger; - // Create lists to hold sinks std::list> app_sink_list = {}; std::list> gravity_sink_list = {}; - // Always create console loggers + // Always create all loggers, some may be set to off auto shared_console_sink = make_shared(); + auto console_proxy_for_gravity = std::make_shared(); console_proxy_for_gravity->add_sink(shared_console_sink); console_proxy_for_gravity->set_level(gravity_console_level); gravity_sink_list.push_back(console_proxy_for_gravity); + auto console_proxy_for_app = std::make_shared(); console_proxy_for_app->add_sink(shared_console_sink); console_proxy_for_app->set_level(app_console_level); app_sink_list.push_back(console_proxy_for_app); - // Configure file logger (if specified) - if (has_gravity_file_logger || has_app_file_logger) - { - string filename = getStringParam("LogDirectory", ".") + file_separator + componentID + ".log"; - auto sharedFileSink = std::make_shared(filename); - - if (has_gravity_file_logger) - { - auto file_proxy_for_gravity = std::make_shared(); - file_proxy_for_gravity->add_sink(sharedFileSink); - file_proxy_for_gravity->set_level(gravity_file_level); - gravity_sink_list.push_back(file_proxy_for_gravity); - } + string filename = getStringParam("LogDirectory", ".") + file_separator + componentID + ".log"; + auto sharedFileSink = std::make_shared(filename); + + auto file_proxy_for_gravity = std::make_shared(); + file_proxy_for_gravity->add_sink(sharedFileSink); + file_proxy_for_gravity->set_level(gravity_file_level); + gravity_sink_list.push_back(file_proxy_for_gravity); - if (has_app_file_logger) - { - auto file_proxy_for_app = std::make_shared(); - file_proxy_for_app->add_sink(sharedFileSink); - file_proxy_for_app->set_level(app_file_level); - app_sink_list.push_back(file_proxy_for_app); - } + auto file_proxy_for_app = std::make_shared(); + file_proxy_for_app->add_sink(sharedFileSink); + file_proxy_for_app->set_level(app_file_level); + app_sink_list.push_back(file_proxy_for_app); - } - - // Configure publish logger - if (has_app_publish_logger) - { - auto publishSink = std::make_shared>(this); - auto publish_proxy_for_app = std::make_shared(); - publish_proxy_for_app->add_sink(publishSink); - publish_proxy_for_app->set_level(app_publish_level); - app_sink_list.push_back(publish_proxy_for_app); - } + auto publishSink = std::make_shared>(this); + auto publish_proxy_for_app = std::make_shared(); + publish_proxy_for_app->add_sink(publishSink); + publish_proxy_for_app->set_level(app_publish_level); + app_sink_list.push_back(publish_proxy_for_app); // Configure GravityLogger. logger = std::make_shared("GravityLogger"); @@ -654,12 +634,9 @@ void GravityNode::configSpdLoggers() app_logger->flush_on(spdlog::level::trace); // logger will flush on all messages app_logger->set_pattern("[%Y-%m-%d %T.%f " + componentID + "-%l] %v"); spdlog::register_logger(app_logger); - - if (has_app_logger) - { - // Set the ApplicaitonLogger as the default - spdlog::set_default_logger(app_logger); - } + + // Set the ApplicationLogger as the default + spdlog::set_default_logger(app_logger); } GravityReturnCode GravityNode::init() @@ -1022,6 +999,16 @@ GravityReturnCode GravityNode::init(std::string componentID) logger->warn("Gravity.ini specifies both Domain and URL. Using URL."); } + if(componentID != "ServiceDirectory") + { + // Register subscriber to allow for dynamic logging changes + GravityReturnCode ret = registerSpdlogDynamicConfiguration(); + if (ret!=GravityReturnCodes::SUCCESS) + { + logger->error(" {}'s Dynamic SpdLog Subscriber not registered ( code: {})", componentID, ret); + } + } + initLock.Unlock(); return ret; @@ -1615,7 +1602,6 @@ GravityReturnCode GravityNode::ServiceDirectoryDataProductLookup(std::string dat // Send request to service directory GravityReturnCode ret = sendRequestToServiceDirectory(request, response); - if (ret == GravityReturnCodes::SUCCESS) { ComponentDataLookupResponsePB pb; @@ -1691,7 +1677,8 @@ GravityReturnCode GravityNode::subscribeInternal(string dataProductID, const Gra GravityReturnCode ret; ret = ServiceDirectoryDataProductLookup(dataProductID, publisherInfoPBs, domain); - if(ret != GravityReturnCodes::SUCCESS) { + if(ret != GravityReturnCodes::SUCCESS) + { return ret; } @@ -2518,6 +2505,13 @@ GravityReturnCode GravityNode::unregisterHeartbeatListener(string componentID, s return GravityReturnCodes::SUCCESS; } +GravityReturnCode GravityNode::registerSpdlogDynamicConfiguration() +{ + // Set up the subscriber for any reconfiguration messages + spdLogConfigSub.init(componentID); + return this->subscribe(gravity::constants::SPD_LOG_CONFIG_DPID, spdLogConfigSub); +} + GravityReturnCode GravityNode::registerRelay(string dataProductID, const GravitySubscriber& subscriber, bool localOnly, GravityTransportType transportType) { return registerRelay(dataProductID, subscriber, localOnly, transportType, false); diff --git a/src/api/cpp/GravityNode.h b/src/api/cpp/GravityNode.h index dc99a5724..fdbb87792 100755 --- a/src/api/cpp/GravityNode.h +++ b/src/api/cpp/GravityNode.h @@ -32,6 +32,7 @@ #include "GravitySemaphore.h" #include "GravityServiceProvider.h" #include "GravitySubscriptionMonitor.h" +#include "GravitySpdLogConfigSubscriber.h" #include "Utility.h" #include "CommUtil.h" //#include "PublishSink.h" @@ -211,6 +212,8 @@ class GravityNode bool defaultCacheLastSentDataprodut; bool defaultReceiveLastSentDataproduct; + + SpdLogConfigSubscriber spdLogConfigSub; std::thread subscriptionManagerThread; @@ -500,6 +503,13 @@ class GravityNode */ GRAVITY_API GravityReturnCode unregisterHeartbeatListener(std::string componentID, std::string domain = ""); + + /** + * Registers a subscriber to receive messages about dynamic spdlog changes + * \return success flag + */ + GRAVITY_API GravityReturnCode registerSpdlogDynamicConfiguration(); + /** * Register a Relay that will act as a pass-through for the given dataProductID. It will be a publisher and subscriber * for the given dataProductID, but other components will only subscribe to this data if they are on the same host (localOnly == true), or diff --git a/src/api/cpp/GravitySpdLogConfigSubscriber.cpp b/src/api/cpp/GravitySpdLogConfigSubscriber.cpp new file mode 100644 index 000000000..245f4b64c --- /dev/null +++ b/src/api/cpp/GravitySpdLogConfigSubscriber.cpp @@ -0,0 +1,50 @@ +#include +#include +#include +#include "GravitySpdLogConfigSubscriber.h" +#include "spdlog/spdlog.h" +#include "protobuf/GravitySpdLogConfigPB.pb.h" + + +namespace gravity { + SpdLogConfigSubscriber::SpdLogConfigSubscriber(){} + + void SpdLogConfigSubscriber::init(std::string compID) + { + componentID = compID; + } + + void SpdLogConfigSubscriber::subscriptionFilled(const std::vector< std::shared_ptr >& dataProducts) + { + for(std::vector< std::shared_ptr >::const_iterator i = dataProducts.begin(); i != dataProducts.end(); i++) + { + //Get the protobuf object from the message + GravitySpdLogConfigPB spdLogConfigPB; + (*i)->populateMessage(spdLogConfigPB); + // Reconfigure the loggers based on this + reconfigSpdLoggers(spdLogConfigPB); + } + } + + // Determines if correct ID and reconfigures accordingly + void SpdLogConfigSubscriber::reconfigSpdLoggers(GravitySpdLogConfigPB spdLogConfigPB) + { + // Check if it is one of the specfied components, return if not + if (spdLogConfigPB.has_component_id() && spdLogConfigPB.component_id() != componentID) + { + return; + } + if (spdLogConfigPB.logger_id() == GravitySpdLogConfigPB_LoggerType_GravityConsoleLogger || spdLogConfigPB.logger_id() == GravitySpdLogConfigPB_LoggerType_GravityFileLogger) + { + auto log = spdlog::get("GravityLogger"); + log->sinks()[spdLogConfigPB.logger_id()]-> set_level((spdlog::level::level_enum)(spdLogConfigPB.logger_level())); + + } + else + { + auto log = spdlog::get("GravityApplicationLogger"); + log->sinks()[spdLogConfigPB.logger_id() - 2]-> set_level((spdlog::level::level_enum)(spdLogConfigPB.logger_level())); + + } + } +} \ No newline at end of file diff --git a/src/api/cpp/GravitySpdLogConfigSubscriber.h b/src/api/cpp/GravitySpdLogConfigSubscriber.h new file mode 100644 index 000000000..854602d6d --- /dev/null +++ b/src/api/cpp/GravitySpdLogConfigSubscriber.h @@ -0,0 +1,19 @@ +#include +#include "Utility.h" +#include "GravitySubscriber.h" +#include "protobuf/GravitySpdLogConfigPB.pb.h" + +namespace gravity { + //Declare class for receiving published messages about the log. + class SpdLogConfigSubscriber: public GravitySubscriber + { + private: + std::string componentID; + void reconfigSpdLoggers(GravitySpdLogConfigPB spdLogConfigPB); + public: + SpdLogConfigSubscriber(); + void init(std::string compID); + void subscriptionFilled(const std::vector< std::shared_ptr >& dataProducts); + + }; +} \ No newline at end of file diff --git a/src/api/protobufs/GravitySpdLogConfigPB.proto b/src/api/protobufs/GravitySpdLogConfigPB.proto new file mode 100755 index 000000000..afcd0bd1b --- /dev/null +++ b/src/api/protobufs/GravitySpdLogConfigPB.proto @@ -0,0 +1,49 @@ +/** (C) Copyright 2013, Applied Physical Sciences Corp., A General Dynamics Company + ** + ** Gravity is free software; you can redistribute it and/or modify + ** it under the terms of the GNU Lesser General Public License as published by + ** the Free Software Foundation; either version 3 of the License, or + ** (at your option) any later version. + ** + ** This program is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU Lesser General Public License for more details. + ** + ** You should have received a copy of the GNU Lesser General Public + ** License along with this program; + ** If not, see . + ** + */ + +syntax = "proto2"; +option optimize_for = SPEED; +option java_outer_classname = "ComponentDataLookupResponseContainer"; +option java_package = "com.aphysci.gravity.protobuf"; + +package gravity; +message GravitySpdLogConfigPB +{ + optional string component_id = 1; + enum LoggerLevel + { + trace = 0; + debug = 1; + info = 2; + warn = 3; + error = 4; + critical = 5; + off = 6; + } + optional LoggerLevel logger_level = 2; + enum LoggerType + { + GravityConsoleLogger = 0; + GravityFileLogger = 1; + ApplicationConsoleLogger = 2; + ApplicationFileLogger = 3; + ApplicationNetworkLogger = 4; + + } + optional LoggerType logger_id = 3; +} \ No newline at end of file diff --git a/test/examples/15-SpdlogDynamicConfiguration/CMakeLists.txt b/test/examples/15-SpdlogDynamicConfiguration/CMakeLists.txt new file mode 100644 index 000000000..1c154ae57 --- /dev/null +++ b/test/examples/15-SpdlogDynamicConfiguration/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.17) +include(GravitySupport) +project(SpdlogDynamicConfiguration) + +find_package(PThreadsWin32 REQUIRED) +gravity_find_protobuf(ON) +gravity_find_zeromq(ON) +gravity_find_spdlog(ON) +find_package(GravityKeyValueParser REQUIRED) +find_package(Gravity REQUIRED) + +set(CMAKE_DEBUG_POSTFIX _d) +add_executable(SpdlogDynamicConfiguration SpdlogDynamicConfiguration.cpp) +set_target_properties(SpdlogDynamicConfiguration PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) +target_link_libraries(SpdlogDynamicConfiguration gravity) +install(TARGETS SpdlogDynamicConfiguration DESTINATION bin) \ No newline at end of file diff --git a/test/examples/15-SpdlogDynamicConfiguration/Gravity.ini b/test/examples/15-SpdlogDynamicConfiguration/Gravity.ini new file mode 100644 index 000000000..eb4d15f66 --- /dev/null +++ b/test/examples/15-SpdlogDynamicConfiguration/Gravity.ini @@ -0,0 +1,11 @@ +[general] +NoConfigServer=true +Domain=GravityTest +ServiceDirectoryBroadcastTimeout=15 +GravityFileLogLevel=off +GravityConsoleLogLevel=off +AppFileLogLevel=off +AppConsoleLogLevel=off +AppNetworkLogLevel=off +[ServiceDirectory] +BroadcastEnabled=true diff --git a/test/examples/15-SpdlogDynamicConfiguration/Makefile.in b/test/examples/15-SpdlogDynamicConfiguration/Makefile.in new file mode 100644 index 000000000..aad42f40f --- /dev/null +++ b/test/examples/15-SpdlogDynamicConfiguration/Makefile.in @@ -0,0 +1,97 @@ +#** (C) Copyright 2013, Applied Physical Sciences Corp., A General Dynamics Company +#** +#** Gravity is free software; you can redistribute it and/or modify +#** it under the terms of the GNU Lesser General Public License as published by +#** the Free Software Foundation; either version 3 of the License, or +#** (at your option) any later version. +#** +#** This program is distributed in the hope that it will be useful, +#** but WITHOUT ANY WARRANTY; without even the implied warranty of +#** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#** GNU Lesser General Public License for more details. +#** +#** You should have received a copy of the GNU Lesser General Public +#** License along with this program; +#** If not, see . +#** + +# @configure_input@ + +# Package-related substitution variables +package = @PACKAGE_NAME@ +version = @PACKAGE_VERSION@ +tarname = @PACKAGE_TARNAME@ + +# Prefix-related substitution variables +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ + +# Tool-related substitution variables +CC = @CC@ +CXX = @CXX@ +DEFS = @DEFS@ +LIBS = @LIBS@ +AC_CFLAGS = @CFLAGS@ +AC_CPPFLAGS = @CPPFLAGS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM= @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +AC_LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +YACC = @YACC@ + +# VPATH-related substitution variables +top_builddir = @top_builddir@ +builddir = @builddir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC=$(CXX) +GRAVLIB_DIR=../../../src/api/cpp/ +COMPONENT_DIR=../../../src/components/cpp +SERVICEDIRECTORY_LOCATION=$(COMPONENT_DIR)/ServiceDirectory + +#OS Specific +SYSTEM:=$(strip $(shell uname -s)) +#SYSTEM:=LINUX +#SYSTEM=MINGW32_NT-6.1 +#WARNING: DON'T PUT SPACES OR QUOTES IN COMPARISON STRING!!! +ifneq (,$(findstring MINGW32_NT,$(SYSTEM))) + OS_SPECIFIC_LIBS = -Wl,-Bdynamic -lzmq -lwsock32 -lpthread + OS_EXE_EXT=.exe +windows: all; +else ifneq (,$(findstring Linux,$(SYSTEM))) +ifneq (,$(findstring lsodium,$(LIBS))) + OS_SPECIFIC_LIBS = -lzmq -lsodium -Wl,-Bdynamic -lrt -lpthread +else + OS_SPECIFIC_LIBS = -lzmq -Wl,-Bdynamic -lrt -lpthread +endif + OS_EXE_EXT= +linux: all; +else +ostype: ; @echo "ERROR UNKNOWN OS: " $(SYSTEM); +endif + +INCLUDES=-I$(GRAVLIB_DIR) $(AC_CPPFLAGS) +CFLAGS=-std=c++11 -L$(GRAVLIB_DIR) -L../../../src/keyvalue_parser/ $(AC_LDFLAGS) $(AC_CFLAGS) +LIBS=-lgravity -lkeyvalue_parser -lprotobuf $(OS_SPECIFIC_LIBS) + +all: SpdlogDynamicConfiguration$(OS_EXE_EXT) + +#Compile each cpp file to a separate executable. +SpdlogDynamicConfiguration$(OS_EXE_EXT):SpdlogDynamicConfiguration.cpp + $(CC) -o $@ $< $(INCLUDES) $(CFLAGS) $(LIBS) + +components: ServiceDirectory$(OS_EXE_EXT) + +ServiceDirectory$(OS_EXE_EXT): + @cd $(SERVICEDIRECTORY_LOCATION); \ + make + +clean: + @rm -rf *.o *.exe SpdlogDynamicConfiguration + +run: components SpdlogDynamicConfiguration$(OS_EXE_EXT) + ./run.sh \ No newline at end of file diff --git a/test/examples/15-SpdlogDynamicConfiguration/SpdlogDynamicConfiguration.cpp b/test/examples/15-SpdlogDynamicConfiguration/SpdlogDynamicConfiguration.cpp new file mode 100644 index 000000000..a3bfc5ad5 --- /dev/null +++ b/test/examples/15-SpdlogDynamicConfiguration/SpdlogDynamicConfiguration.cpp @@ -0,0 +1,139 @@ +#include +#include +#include +#include "protobuf/GravitySpdLogConfigPB.pb.h" +#include "protobuf/GravityLogMessagePB.pb.h" + +using namespace std; +using namespace gravity; + +#ifdef WIN32 +#include +#define sleep Sleep +#else +#include +#endif + +class ApplicationLogSubscriber : public GravitySubscriber { +public: + virtual void subscriptionFilled(const std::vector< std::shared_ptr >& dataProducts); +}; + +void logAllAppLevels() +{ + // Wait to ensure it has been sent and received + sleep(2000); + spdlog::trace("App"); + spdlog::debug("App"); + spdlog::info("App"); + spdlog::warn("App"); + spdlog::error("App"); + spdlog::critical("App"); +} + +void sendConfigMessage(GravityNode &gn, std::string compID, GravitySpdLogConfigPB_LoggerType lt, GravitySpdLogConfigPB_LoggerLevel ll) +{ + //Create a data product to send across the network + GravityDataProduct gravityConfigDP(gravity::constants::SPD_LOG_CONFIG_DPID); + + //Initialize our message + GravitySpdLogConfigPB spdLogConfigPB; + if(compID != "") + { + spdLogConfigPB.set_component_id(compID); + } + + spdLogConfigPB.set_logger_id(lt); + spdLogConfigPB.set_logger_level(ll); + gravityConfigDP.setData(spdLogConfigPB); + + //Publish the data product. + if (gn.publish(gravityConfigDP) != GravityReturnCodes::SUCCESS) + { + spdlog::error("Could not publish data product with id {}", gravity::constants::SPD_LOG_CONFIG_DPID); + + } +} + +int main() +{ + GravityNode gn; + + //Initialize gravity, giving this node a componentID. + if (gn.init("SimpleGravityComponentID") != GravityReturnCodes::SUCCESS) + { + spdlog::critical("Could not initialize GravityNode"); + exit(1); + } + + //Register a data product + if (gn.registerDataProduct(gravity::constants::SPD_LOG_CONFIG_DPID, GravityTransportTypes::TCP) != GravityReturnCodes::SUCCESS) + { + spdlog::critical("Could not register data product with id {}", gravity::constants::SPD_LOG_CONFIG_DPID); + exit(1); + } + + // Set up a subscriber to the Application Publisher Logger + ApplicationLogSubscriber simpleSubscriber; + gn.subscribe(gravity::constants::GRAVITY_LOGGER_DPID, simpleSubscriber); + + std::cout<<"Begin testing GravityLogger\n"; + + // Change SimpleGravityComponentID's File to trace level + // for gravity and trace level for the console + sendConfigMessage(gn,"", GravitySpdLogConfigPB_LoggerType_GravityFileLogger, GravitySpdLogConfigPB_LoggerLevel_trace); + sendConfigMessage(gn,"SimpleGravityComponentID", GravitySpdLogConfigPB_LoggerType_GravityConsoleLogger, GravitySpdLogConfigPB_LoggerLevel_trace); + + logAllAppLevels(); // nothing prints + + // Turns off file and console for GravityLogger + // for SimpleGravityComponentID and ServiceDirectory + sendConfigMessage(gn, "SimpleGravityComponentID", GravitySpdLogConfigPB_LoggerType_GravityConsoleLogger, GravitySpdLogConfigPB_LoggerLevel_off); + sendConfigMessage(gn, "", GravitySpdLogConfigPB_LoggerType_GravityFileLogger, GravitySpdLogConfigPB_LoggerLevel_off); + + std::cout << "End testing GravityLogger\n"; + + // Nothing changes as NotARealID does not work + sendConfigMessage(gn, "NotARealID", GravitySpdLogConfigPB_LoggerType_ApplicationFileLogger, GravitySpdLogConfigPB_LoggerLevel_error); + logAllAppLevels(); + + + std::cout << "Begin testing ApplicationLogger\n"; + + // Change SimpleGravityComponentID's network to critical level + // for ApplicationLogger and any subscribed components' console to info level + // and file to warn level + sendConfigMessage(gn, "SimpleGravityComponentID", GravitySpdLogConfigPB_LoggerType_ApplicationNetworkLogger, GravitySpdLogConfigPB_LoggerLevel_critical); + sendConfigMessage(gn, "", GravitySpdLogConfigPB_LoggerType_ApplicationConsoleLogger, GravitySpdLogConfigPB_LoggerLevel_info); + sendConfigMessage(gn, "", GravitySpdLogConfigPB_LoggerType_ApplicationFileLogger, GravitySpdLogConfigPB_LoggerLevel_warn); + logAllAppLevels(); + + // Change all logger's changed back to off + sendConfigMessage(gn, "SimpleGravityComponentID1", GravitySpdLogConfigPB_LoggerType_ApplicationNetworkLogger, GravitySpdLogConfigPB_LoggerLevel_off); + sendConfigMessage(gn, "", GravitySpdLogConfigPB_LoggerType_ApplicationConsoleLogger, GravitySpdLogConfigPB_LoggerLevel_off); + sendConfigMessage(gn, "", GravitySpdLogConfigPB_LoggerType_ApplicationFileLogger, GravitySpdLogConfigPB_LoggerLevel_off); + + logAllAppLevels(); + + std::cout<<"End testing ApplicationLogger\n"; + + gn.unsubscribe(gravity::constants::GRAVITY_LOGGER_DPID, simpleSubscriber); +} + +void ApplicationLogSubscriber::subscriptionFilled(const std::vector< std::shared_ptr >& dataProducts) +{ + for(std::vector< std::shared_ptr >::const_iterator i = dataProducts.begin(); + i != dataProducts.end(); i++) + { + //Get the protobuf object from the message + GravityLogMessagePB logMessage; + (*i)->populateMessage(logMessage); + + std::string message = logMessage.message(); + // Use a substring to cut off the time and level info (metadata) included in log string + if(message.substr(message.length()-4,3) == "App" && logMessage.level() == "critical") + { + std::cout << "The correct level and message were published for Application Network Logger\n"; + } + } +} \ No newline at end of file diff --git a/test/examples/15-SpdlogDynamicConfiguration/run.sh.in b/test/examples/15-SpdlogDynamicConfiguration/run.sh.in new file mode 100644 index 000000000..eae064be8 --- /dev/null +++ b/test/examples/15-SpdlogDynamicConfiguration/run.sh.in @@ -0,0 +1,50 @@ +#!/bin/bash +#** (C) Copyright 2013, Applied Physical Sciences Corp., A General Dynamics Company +#** +#** Gravity is free software; you can redistribute it and/or modify +#** it under the terms of the GNU Lesser General Public License as published by +#** the Free Software Foundation; either version 3 of the License, or +#** (at your option) any later version. +#** +#** This program is distributed in the hope that it will be useful, +#** but WITHOUT ANY WARRANTY; without even the implied warranty of +#** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#** GNU Lesser General Public License for more details. +#** +#** You should have received a copy of the GNU Lesser General Public +#** License along with this program; +#** If not, see . +#** + +# @configure_input@ + +# Tool-related substitution variables +PROTOBUF_LIB_DIR=@PROTOBUF_LIBDIR@ +ZMQ_LIB_DIR=@ZEROMQ_LIBDIR@ + +export PATH=$PATH:../../../src/components/cpp/bin +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../../src/api/cpp:../../../src/keyvalue_parser:$ZMQ_LIB_DIR:$PROTOBUF_LIB_DIR + + cleanup() +# run if user hits control-c +{ + kill -9 $SDPID + kill -9 $PUBID + exit $? +} + +# trap keyboard interrupt (control-c) +trap cleanup SIGINT + +ServiceDirectory & +SDPID=$! + +# sleep for a second to give the service directory a chance to start up +sleep 1 + +./SpdlogDynamicConfiguration & +PUBID=$! + +sleep 25 + +cleanup \ No newline at end of file