summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2013-10-01 09:26:41 +0200
committerPatrick Ohly <patrick.ohly@intel.com>2013-10-25 21:07:27 +0100
commite7a8f1b456f967323b403ecf543b28a3d52db5a8 (patch)
tree9ccf373715cc8c4ec03b6c41b8ef9ab4bd4e7c6e
parent6e47a118da64cccddc6ce3e453f0cf33ec841336 (diff)
logging: support DLT (FDO #66769)
Diagnostic Log and Trace (DLT) manages a sequence of log messages, with remote controllable level of detail. SyncEvolution optionally (can be chosen at compile time and again at runtime) uses DLT instead of its own syncevolution-log.html files.
-rw-r--r--README-DLT.rst30
-rw-r--r--configure.ac24
-rw-r--r--src/dbus/server/main.cpp25
-rw-r--r--src/dbus/server/server.am2
-rw-r--r--src/dbus/server/session-helper.cpp28
-rw-r--r--src/dbus/server/session-helper.h3
-rw-r--r--src/dbus/server/session.cpp10
-rw-r--r--src/dbus/server/sync-helper.cpp14
-rw-r--r--src/syncevo/LocalTransportAgent.cpp19
-rw-r--r--src/syncevo/LogDLT.cpp116
-rw-r--r--src/syncevo/LogDLT.h61
-rw-r--r--src/syncevo/LogRedirect.cpp22
-rw-r--r--src/syncevo/LogStdout.cpp10
-rw-r--r--src/syncevo/Logging.cpp6
-rw-r--r--src/syncevo/Logging.h18
-rw-r--r--src/syncevo/SyncContext.cpp99
-rw-r--r--src/syncevo/syncevo.am4
-rwxr-xr-xtest/test-dbus.py2
18 files changed, 447 insertions, 46 deletions
diff --git a/README-DLT.rst b/README-DLT.rst
new file mode 100644
index 00000000..16bbc598
--- /dev/null
+++ b/README-DLT.rst
@@ -0,0 +1,30 @@
+Diagnostic Log and Trace
+========================
+
+Diagnostic Log and Trace (DLT) is a logging mechanism defined and
+implemented by GENIVI: http://projects.genivi.org/diagnostic-log-trace/
+
+SyncEvolution optionally supports DLT as follows:
+
+ * syncevo-dbus-server, syncevo-dbus-helper and syncevo-local-sync can
+ log to DLT. Operations with "syncevolution --daemon=no" never use
+ DLT.
+ * Each of the three processes uses a different application ID. By
+ default, these IDs are "SYNS", "SYNH", "SYNL". These default can be
+ changed via configure options. All processes use just one context,
+ with the fixed ID "SYNC".
+ * syncevo-dbus-helper and syncevo-local-sync only run occasionally.
+ This makes is hard to adjust their log levels, for example via the
+ dlt-viewer, because the processes and their contexts are only shown
+ (known?) while the processes run. To work around this, the initial
+ log level of these two helpers are inherited from the
+ log level of the "SYNC" context in syncevo-dbus-helper.
+ * That log level defaults to "WARN", which ensures that normal runs
+ produce no output.
+ * To enable DLT support during compilation, use
+ "--enable-dlt" and "--with-dlt-syncevolution=SYNS,SYNH,SYNL" where SYNS/H/L
+ are the actual application IDs.
+ * To enable DLT support at runtime, run syncevo-dbus-server with
+ "--dlt". Logging to syslog should be disabled with "--no-syslog".
+ * The hierarchical log from libsynthesis gets flattened into a flat
+ stream of messages and no syncevolution-log.html files are written.
diff --git a/configure.ac b/configure.ac
index 5995cf80..608c9c4e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -290,6 +290,30 @@ AC_ARG_ENABLE(libsoup,
# SoupTransportAgent depends on glib
case "$TRANSPORT" in *libsoup*) need_glib=yes;; esac
+AC_ARG_ENABLE(dlt,
+ AS_HELP_STRING([--enable-dlt],
+ [enable logging via GENIVI Diagnostic Log and Trace (DLT)]),
+ [enable_dlt=$enableval
+ test $enable_dlt = "yes" || test $enable_dlt = "no" || AC_ERROR([invalid value of --enable-dlt: $enableval])],
+ [enable_dlt="no"])
+if test "$enable_dlt" = "yes"; then
+ PKG_CHECK_MODULES(DLT, automotive-dlt,
+ [USE_DLT=1],
+ [AC_ERROR([dlt not found, required for --enable-dlt])])
+ AC_DEFINE(USE_DLT, 1, "optionally use GENIVI Diagnostic Log and Trace for logging")
+ AC_ARG_WITH([dlt-syncevolution],
+ AS_HELP_STRING([--with-dlt-syncevolution=SYNS,SYNH,SYNL],
+ [controls the application IDs used by syncevo-dbus-server, syncevo-dbus-helper and syncevo-local-sync]),
+ [with_dlt_ids="$withval"],
+ [with_dlt_ids="SYNS,SYNH,SYNL"])
+ syns=`echo $with_dlt_ids | cut -d , -f 1`
+ synh=`echo $with_dlt_ids | cut -d , -f 2`
+ synl=`echo $with_dlt_ids | cut -d , -f 3`
+ AC_DEFINE_UNQUOTED(DLT_SYNCEVO_DBUS_SERVER_ID, "$syns", "DLT app ID for syncevo-dbus-server")
+ AC_DEFINE_UNQUOTED(DLT_SYNCEVO_DBUS_HELPER_ID, "$synh", "DLT app ID for syncevo-dbus-helper")
+ AC_DEFINE_UNQUOTED(DLT_SYNCEVO_LOCAL_HELPER_ID, "$synl", "DLT app ID for syncevo-local-helper")
+fi
+
bluetooth_disabled=no
AC_ARG_ENABLE(bluetooth,
AS_HELP_STRING([--enable-bluetooth],
diff --git a/src/dbus/server/main.cpp b/src/dbus/server/main.cpp
index a8d8c6d9..63c757bd 100644
--- a/src/dbus/server/main.cpp
+++ b/src/dbus/server/main.cpp
@@ -33,8 +33,13 @@
#include <syncevo/SuspendFlags.h>
#include <syncevo/LogRedirect.h>
#include <syncevo/LogSyslog.h>
+#include <syncevo/LogDLT.h>
#include <syncevo/GLibSupport.h>
+#ifdef USE_DLT
+# include <dlt.h>
+#endif
+
using namespace SyncEvo;
using namespace GDBusCXX;
@@ -100,6 +105,9 @@ int main(int argc, char **argv, char **envp)
int logLevelDBus = 2;
gboolean stdoutEnabled = false;
gboolean syslogEnabled = true;
+#ifdef USE_DLT
+ gboolean dltEnabled = false;
+#endif
#ifdef ENABLE_DBUS_PIM
gboolean startPIM = false;
#endif
@@ -115,6 +123,9 @@ int main(int argc, char **argv, char **envp)
"Enable printing to stdout (result of operations) and stderr (errors/info/debug).",
NULL },
{ "no-syslog", 's', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &syslogEnabled, "Disable printing to syslog.", NULL },
+#ifdef USE_DLT
+ { "dlt", 0, 0, G_OPTION_ARG_NONE, &dltEnabled, "Enable logging via GENIVI Diagnostic Log and Trace.", NULL },
+#endif
#ifdef ENABLE_DBUS_PIM
{ "start-pim", 'p', 0, G_OPTION_ARG_NONE, &startPIM,
"Activate the PIM Manager (= unified address book) immediately.",
@@ -154,6 +165,20 @@ int main(int argc, char **argv, char **envp)
// Redirect output and optionally log to syslog.
PushLogger<LogRedirect> redirect(new LogRedirect(LogRedirect::STDERR_AND_STDOUT));
redirect->setLevel(stdoutEnabled ? level : Logger::NONE);
+#ifdef USE_DLT
+ PushLogger<LoggerDLT> loggerdlt;
+ if (dltEnabled) {
+ // DLT logging with default log level DLT_LOG_WARN. This
+ // default was chosen because DLT's own default,
+ // DLT_LOG_INFO, leads to too much output given that a lot
+ // of the standard messages in SyncEvolution and
+ // libsynthesis are labelled informational.
+ setenv("SYNCEVOLUTION_USE_DLT", StringPrintf("%d", DLT_LOG_WARN).c_str(), true);
+ loggerdlt.reset(new LoggerDLT(DLT_SYNCEVO_DBUS_SERVER_ID, "SyncEvolution D-Bus server"));
+ } else {
+ unsetenv("SYNCEVOLUTION_USE_DLT");
+ }
+#endif
PushLogger<LoggerSyslog> syslogger;
if (syslogEnabled && level > Logger::NONE) {
syslogger.reset(new LoggerSyslog(execName));
diff --git a/src/dbus/server/server.am b/src/dbus/server/server.am
index ab01679d..302754c4 100644
--- a/src/dbus/server/server.am
+++ b/src/dbus/server/server.am
@@ -82,7 +82,7 @@ nodist_src_dbus_server_libsyncevodbusserver_la_SOURCES += \
src_dbus_server_libsyncevodbusserver_la_LDFLAGS += $(DBUS_PIM_PLUGIN_LDFLAGS)
src_dbus_server_libsyncevodbusserver_la_LIBADD += $(FOLKS_LIBS) $(DBUS_PIM_PLUGIN_LIBS) $(PHONENUMBERS_LIBS)
-src_dbus_server_libsyncevodbusserver_la_CXXFLAGS += $(FOLKS_CFLAGS) $(DBUS_PIM_PLUGIN_CFLAGS) $(PHONENUMBERS_CFLAGS)
+src_dbus_server_libsyncevodbusserver_la_CXXFLAGS += $(FOLKS_CFLAGS) $(DBUS_PIM_PLUGIN_CFLAGS) $(PHONENUMBERS_CFLAGS) $(DLT_CFLAGS)
endif
# Need to list all plugins here and not include the active one in the regular
diff --git a/src/dbus/server/session-helper.cpp b/src/dbus/server/session-helper.cpp
index 7d233966..19776ea4 100644
--- a/src/dbus/server/session-helper.cpp
+++ b/src/dbus/server/session-helper.cpp
@@ -42,14 +42,13 @@ static void dumpString(const std::string &output)
*/
class SessionHelperLogger : public Logger
{
- boost::shared_ptr<LogRedirect> m_parentLogger;
+ Handle m_parentLogger;
boost::shared_ptr<SessionHelper> m_helper;
Level m_dbusLogLevel;
public:
- SessionHelperLogger(const boost::shared_ptr<LogRedirect> &parentLogger,
- const boost::shared_ptr<SessionHelper> &helper):
- m_parentLogger(parentLogger),
+ SessionHelperLogger(const boost::shared_ptr<SessionHelper> &helper):
+ m_parentLogger(Logger::instance()),
m_helper(helper),
m_dbusLogLevel(DEBUG)
{
@@ -84,7 +83,7 @@ public:
va_list argsCopy;
va_copy(argsCopy, args);
if (m_parentLogger) {
- m_parentLogger->messagev(options, format, argsCopy);
+ m_parentLogger.messagev(options, format, argsCopy);
} else {
formatLines(options.m_level, DEBUG,
options.m_processName,
@@ -94,10 +93,16 @@ public:
}
va_end(argsCopy);
} else if (m_parentLogger) {
- // Only flush parent logger, to capture output sent to
- // stdout/stderr by some library and send it via D-Bus
- // (recursively!) before printing out own, new output.
- m_parentLogger->flush();
+ // Pass through to parent, but marked in such a way that
+ // only the DLT and syslog logger will react to it, but
+ // not LogStdout. That's necessary because
+ // syncevo-dbus-server handles stdout for us.
+ va_list argsCopy;
+ va_copy(argsCopy, args);
+ MessageOptions buffer(options);
+ buffer.m_flags |= MessageOptions::ONLY_GLOBAL_LOG;
+ m_parentLogger.messagev(buffer, format, argsCopy);
+ va_end(argsCopy);
}
if (m_helper &&
@@ -117,8 +122,7 @@ public:
SessionHelper::SessionHelper(GMainLoop *loop,
const GDBusCXX::DBusConnectionPtr &conn,
- const boost::shared_ptr<ForkExecChild> &forkexec,
- const boost::shared_ptr<LogRedirect> &parentLogger) :
+ const boost::shared_ptr<ForkExecChild> &forkexec) :
GDBusCXX::DBusObjectHelper(conn,
std::string(SessionCommon::HELPER_PATH) + "/" + forkexec->getInstance(),
SessionCommon::HELPER_IFACE,
@@ -127,7 +131,7 @@ SessionHelper::SessionHelper(GMainLoop *loop,
m_loop(loop),
m_conn(conn),
m_forkexec(forkexec),
- m_logger(new SessionHelperLogger(parentLogger, boost::shared_ptr<SessionHelper>(this, NopDestructor()))),
+ m_logger(new SessionHelperLogger(boost::shared_ptr<SessionHelper>(this, NopDestructor()))),
emitLogOutput(*this, "LogOutput"),
emitSyncProgress(*this, "SyncProgress"),
emitSourceProgress(*this, "SourceProgress"),
diff --git a/src/dbus/server/session-helper.h b/src/dbus/server/session-helper.h
index 3c380008..6f9dc0e0 100644
--- a/src/dbus/server/session-helper.h
+++ b/src/dbus/server/session-helper.h
@@ -85,8 +85,7 @@ class SessionHelper : public GDBusCXX::DBusObjectHelper,
public:
SessionHelper(GMainLoop *loop,
const GDBusCXX::DBusConnectionPtr &conn,
- const boost::shared_ptr<ForkExecChild> &forkexec,
- const boost::shared_ptr<LogRedirect> &parentLogger);
+ const boost::shared_ptr<ForkExecChild> &forkexec);
~SessionHelper();
void setDBusLogLevel(Logger::Level level);
diff --git a/src/dbus/server/session.cpp b/src/dbus/server/session.cpp
index 12b5bb75..03c4ee12 100644
--- a/src/dbus/server/session.cpp
+++ b/src/dbus/server/session.cpp
@@ -31,6 +31,10 @@
#include <syncevo/SyncContext.h>
#include <syncevo/BoostHelper.h>
+#ifdef USE_DLT
+#include <syncevo/LogDLT.h>
+#endif
+
#include <memory>
#include <boost/foreach.hpp>
@@ -793,6 +797,11 @@ void Session::useHelperAsync(const SimpleResult &result)
args.push_back("--dbus-verbosity");
args.push_back(StringPrintf("%d", m_server.getDBusLogLevel()));
m_forkExecParent = SyncEvo::ForkExecParent::create("syncevo-dbus-helper", args);
+#ifdef USE_DLT
+ if (getenv("SYNCEVOLUTION_USE_DLT")) {
+ m_forkExecParent->addEnvVar("SYNCEVOLUTION_USE_DLT", StringPrintf("%d", LoggerDLT::getCurrentDLTLogLevel()));
+ }
+#endif
// We own m_forkExecParent, so the "this" pointer for
// onConnect will live longer than the signal in
// m_forkExecParent -> no need for resource
@@ -884,6 +893,7 @@ static void Logging2Server(Server &server,
// there is considered an error.
Logger::MessageOptions options(Logger::strToLevel(strLevel.c_str()));
options.m_processName = &procname;
+ options.m_flags = Logger::MessageOptions::ALREADY_LOGGED;
Logging2ServerAndStdout(server, path, options, "%s", explanation.c_str());
}
}
diff --git a/src/dbus/server/sync-helper.cpp b/src/dbus/server/sync-helper.cpp
index a564e9a3..8fefb3c0 100644
--- a/src/dbus/server/sync-helper.cpp
+++ b/src/dbus/server/sync-helper.cpp
@@ -28,6 +28,7 @@
#include <syncevo/SuspendFlags.h>
#include <syncevo/SyncContext.h>
#include <syncevo/LogRedirect.h>
+#include <syncevo/LogDLT.h>
using namespace SyncEvo;
using namespace GDBusCXX;
@@ -45,11 +46,10 @@ namespace {
}
void onConnect(const DBusConnectionPtr &conn,
- const boost::shared_ptr<LogRedirect> &parentLogger,
const boost::shared_ptr<ForkExecChild> &forkexec,
boost::shared_ptr<SessionHelper> &helper)
{
- helper.reset(new SessionHelper(loop, conn, forkexec, parentLogger));
+ helper.reset(new SessionHelper(loop, conn, forkexec));
helper->activate();
helper->setDBusLogLevel(Logger::Level(logLevelDBus));
}
@@ -107,6 +107,14 @@ int main(int argc, char **argv, char **envp)
redirect.reset(new LogRedirect(LogRedirect::STDERR_AND_STDOUT));
pushRedirect.reset(redirect);
}
+#ifdef USE_DLT
+ // Set by syncevo-dbus-server for us.
+ bool useDLT = getenv("SYNCEVOLUTION_USE_DLT") != NULL;
+ PushLogger<LoggerDLT> loggerdlt;
+ if (useDLT) {
+ loggerdlt.reset(new LoggerDLT(DLT_SYNCEVO_DBUS_HELPER_ID, "SyncEvolution local sync helper"));
+ }
+#endif
setvbuf(stderr, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
@@ -140,7 +148,7 @@ int main(int argc, char **argv, char **envp)
boost::shared_ptr<SessionHelper> helper;
bool failed = false;
- forkexec->m_onConnect.connect(boost::bind(onConnect, _1, redirect,
+ forkexec->m_onConnect.connect(boost::bind(onConnect, _1,
boost::cref(forkexec),
boost::ref(helper)));
forkexec->m_onFailure.connect(boost::bind(onFailure, _2, boost::ref(failed)));
diff --git a/src/syncevo/LocalTransportAgent.cpp b/src/syncevo/LocalTransportAgent.cpp
index 3b0ce035..d348878c 100644
--- a/src/syncevo/LocalTransportAgent.cpp
+++ b/src/syncevo/LocalTransportAgent.cpp
@@ -27,6 +27,7 @@
#include <syncevo/DBusTraits.h>
#include <syncevo/SuspendFlags.h>
#include <syncevo/LogRedirect.h>
+#include <syncevo/LogDLT.h>
#include <syncevo/BoostHelper.h>
#include <synthesis/syerror.h>
@@ -100,6 +101,11 @@ void LocalTransportAgent::start()
}
m_status = ACTIVE;
m_forkexec = ForkExecParent::create("syncevo-local-sync");
+#ifdef USE_DLT
+ if (getenv("SYNCEVOLUTION_USE_DLT")) {
+ m_forkexec->addEnvVar("SYNCEVOLUTION_USE_DLT", StringPrintf("%d", LoggerDLT::getCurrentDLTLogLevel()));
+ }
+#endif
m_forkexec->m_onConnect.connect(boost::bind(&LocalTransportAgent::onChildConnect, this, _1));
// fatal problems, including quitting child with non-zero status
m_forkexec->m_onFailure.connect(boost::bind(&LocalTransportAgent::onFailure, this, _2));
@@ -177,6 +183,9 @@ void LocalTransportAgent::logChildOutput(const std::string &level, const std::st
{
Logger::MessageOptions options(Logger::strToLevel(level.c_str()));
options.m_processName = &m_clientContext;
+ // Child should have written this into its own log file and/or syslog/dlt already.
+ // Only pass it on to a user of the command line interface.
+ options.m_flags = Logger::MessageOptions::ALREADY_LOGGED;
SyncEvo::Logger::instance().messageWithOptions(options, "%s", message.c_str());
}
@@ -1146,6 +1155,16 @@ int LocalTransportMain(int argc, char **argv)
Logger::Handle handle(child->createLogger());
logger.reset(handle);
}
+
+#ifdef USE_DLT
+ // Set by syncevo-dbus-server for us.
+ bool useDLT = getenv("SYNCEVOLUTION_USE_DLT") != NULL;
+ PushLogger<LoggerDLT> loggerdlt;
+ if (useDLT) {
+ loggerdlt.reset(new LoggerDLT(DLT_SYNCEVO_LOCAL_HELPER_ID, "SyncEvolution local sync helper"));
+ }
+#endif
+
child->run();
int ret = child->getReturnCode();
logger.reset();
diff --git a/src/syncevo/LogDLT.cpp b/src/syncevo/LogDLT.cpp
new file mode 100644
index 00000000..fd808594
--- /dev/null
+++ b/src/syncevo/LogDLT.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * This library 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 2.1 of the License, or (at your option) version 3.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <syncevo/LogDLT.h>
+
+#ifdef USE_DLT
+
+#include <dlt.h>
+
+#include <syncevo/declarations.h>
+SE_BEGIN_CXX
+
+static DltLogLevelType SyncEvoLevel2DLTLevel(Logger::Level level)
+{
+ switch (level) {
+ case Logger::NONE: return DLT_LOG_OFF;
+ case Logger::ERROR: return DLT_LOG_ERROR;
+ case Logger::WARNING: return DLT_LOG_WARN;
+ case Logger::SHOW:
+ case Logger::INFO: return DLT_LOG_INFO;
+ case Logger::DEV:
+ case Logger::DEBUG: return DLT_LOG_DEBUG;
+ }
+ return DLT_LOG_OFF;
+}
+
+static LoggerDLT *LoggerDLTInstance;
+
+LoggerDLT::LoggerDLT(const char *appid, const char *description) :
+ m_parentLogger(Logger::instance()),
+ m_dltContext(calloc(1, sizeof(DltContext)))
+{
+ DLT_REGISTER_APP(appid, description);
+ int level = atoi(getEnv("SYNCEVOLUTION_USE_DLT", "-1"));
+ if (level > 0) {
+ DLT_REGISTER_CONTEXT_LL_TS(*(DltContext *)m_dltContext, "SYNC", "SyncEvolution messages",
+ (DltLogLevelType)level, DLT_TRACE_STATUS_OFF);
+ } else {
+ DLT_REGISTER_CONTEXT(*(DltContext *)m_dltContext, "SYNC", "SyncEvolution messages");
+ }
+ LoggerDLTInstance = this;
+}
+
+LoggerDLT::~LoggerDLT()
+{
+ DLT_UNREGISTER_CONTEXT(*(DltContext *)m_dltContext);
+ DLT_UNREGISTER_APP();
+ LoggerDLTInstance = NULL;
+}
+
+void LoggerDLT::messagev(const MessageOptions &options,
+ const char *format,
+ va_list args)
+{
+ // always to parent first (usually stdout):
+ // if the parent is a LogRedirect instance, then
+ // it'll flush its own output first, which ensures
+ // that the new output comes later (as desired)
+ {
+ va_list argscopy;
+ va_copy(argscopy, args);
+ m_parentLogger.messagev(options, format, argscopy);
+ va_end(argscopy);
+ }
+
+ DltContextData log;
+ if (!(options.m_flags & MessageOptions::ALREADY_LOGGED) &&
+ dlt_user_log_write_start((DltContext *)m_dltContext, &log, SyncEvoLevel2DLTLevel(options.m_level)) > 0) {
+ std::string buffer = StringPrintfV(format, args);
+ // Avoid almost empty messages. They are triggered by
+ // SyncEvolution to format the INFO output and don't add any
+ // valuable information to the DLT log.
+ if (!buffer.empty() &&
+ buffer != "\n") {
+ dlt_user_log_write_string(&log, buffer.c_str());
+ dlt_user_log_write_finish(&log);
+ }
+ }
+}
+
+int LoggerDLT::getCurrentDLTLogLevel()
+{
+ if (LoggerDLTInstance) {
+ for (int level = DLT_LOG_VERBOSE;
+ level > DLT_LOG_DEFAULT;
+ --level) {
+ DltContextData log;
+ // Emulates DLT_LOG(): logging active if dlt_user_log_write_start() returns something > 0.
+ // Otherwise discard the DltContextData without doing anything.
+ if (dlt_user_log_write_start((DltContext *)LoggerDLTInstance->m_dltContext, &log, (DltLogLevelType)level) > 0) {
+ return level;
+ }
+ }
+ }
+ return DLT_LOG_DEFAULT;
+}
+
+SE_END_CXX
+
+#endif // USE_DLT
diff --git a/src/syncevo/LogDLT.h b/src/syncevo/LogDLT.h
new file mode 100644
index 00000000..f93e1dc0
--- /dev/null
+++ b/src/syncevo/LogDLT.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * This library 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 2.1 of the License, or (at your option) version 3.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef INCL_LOGDLT
+#define INCL_LOGDLT
+
+#include <config.h>
+
+#ifdef USE_DLT
+
+#include <syncevo/Logging.h>
+#include <syncevo/util.h>
+
+#include <syncevo/declarations.h>
+SE_BEGIN_CXX
+
+/**
+ * A logger which writes to DLT and passes log messages
+ * through to its parent.
+ */
+class LoggerDLT : public Logger
+{
+ Handle m_parentLogger;
+ // avoid dependency on dlt.h here
+ void *m_dltContext;
+
+public:
+ LoggerDLT(const char *appid, const char *description);
+ ~LoggerDLT();
+
+ virtual void messagev(const MessageOptions &options,
+ const char *format,
+ va_list args);
+
+ /**
+ * Extracts current log level from the LoggerDLT which was
+ * pushed onto the stack, DLT_LOG_DEFAULT if none active.
+ */
+ static int getCurrentDLTLogLevel();
+};
+
+SE_END_CXX
+
+#endif // USE_DLT
+#endif // INCL_LOGSYSLOG
diff --git a/src/syncevo/LogRedirect.cpp b/src/syncevo/LogRedirect.cpp
index ca7666ce..45640cca 100644
--- a/src/syncevo/LogRedirect.cpp
+++ b/src/syncevo/LogRedirect.cpp
@@ -247,16 +247,18 @@ void LogRedirect::messagev(const MessageOptions &options,
// check for other output first
process();
- // Choose output channel: SHOW goes to original stdout,
- // everything else to stderr.
- LoggerStdout::write(options.m_level == SHOW ?
- (m_out ? m_out : stdout) :
- (m_err ? m_err : stderr),
- options.m_level, getLevel(),
- options.m_prefix,
- options.m_processName,
- format,
- args);
+ if (!(options.m_flags & MessageOptions::ONLY_GLOBAL_LOG)) {
+ // Choose output channel: SHOW goes to original stdout,
+ // everything else to stderr.
+ LoggerStdout::write(options.m_level == SHOW ?
+ (m_out ? m_out : stdout) :
+ (m_err ? m_err : stderr),
+ options.m_level, getLevel(),
+ options.m_prefix,
+ options.m_processName,
+ format,
+ args);
+ }
}
void LogRedirect::redirect(int original, FDs &fds) throw()
diff --git a/src/syncevo/LogStdout.cpp b/src/syncevo/LogStdout.cpp
index f78ff9dc..a2014e2e 100644
--- a/src/syncevo/LogStdout.cpp
+++ b/src/syncevo/LogStdout.cpp
@@ -84,10 +84,12 @@ void LoggerStdout::messagev(const MessageOptions &options,
const char *format,
va_list args)
{
- write(m_file, options.m_level, getLevel(),
- options.m_prefix,
- options.m_processName,
- format, args);
+ if (!(options.m_flags & MessageOptions::ONLY_GLOBAL_LOG)) {
+ write(m_file, options.m_level, getLevel(),
+ options.m_prefix,
+ options.m_processName,
+ format, args);
+ }
}
SE_END_CXX
diff --git a/src/syncevo/Logging.cpp b/src/syncevo/Logging.cpp
index 0e80947c..837c8828 100644
--- a/src/syncevo/Logging.cpp
+++ b/src/syncevo/Logging.cpp
@@ -255,13 +255,15 @@ Logger::MessageOptions::MessageOptions(Level level,
const std::string *prefix,
const char *file,
int line,
- const char *function) :
+ const char *function,
+ int flags) :
m_level(level),
m_prefix(prefix),
m_file(file),
m_line(line),
m_function(function),
- m_processName(NULL)
+ m_processName(NULL),
+ m_flags(flags)
{
}
diff --git a/src/syncevo/Logging.h b/src/syncevo/Logging.h
index dde9e325..ce9a2497 100644
--- a/src/syncevo/Logging.h
+++ b/src/syncevo/Logging.h
@@ -199,13 +199,29 @@ class Logger
const char *m_function;
/** name of the process which originally created the message, if different from current one */
const std::string *m_processName;
+ /** additional flags */
+ int m_flags;
+
+ enum {
+ /**
+ * The message was written into a global log (syslog, dlt, ...)
+ * already. Such a message must not be logged again.
+ */
+ ALREADY_LOGGED = 1<<0,
+ /**
+ * The message must be written into a global log,
+ * but not to stdout.
+ */
+ ONLY_GLOBAL_LOG = 1<<1
+ };
MessageOptions(Level level);
MessageOptions(Level level,
const std::string *prefix,
const char *file,
int line,
- const char *function);
+ const char *function,
+ int flags = 0);
};
/**
diff --git a/src/syncevo/SyncContext.cpp b/src/syncevo/SyncContext.cpp
index d157a19e..13b0aaa6 100644
--- a/src/syncevo/SyncContext.cpp
+++ b/src/syncevo/SyncContext.cpp
@@ -73,6 +73,10 @@ using namespace std;
#include <synthesis/SDK_util.h>
#include <synthesis/san.h>
+#ifdef USE_DLT
+# include <dlt.h>
+#endif
+
#include "test.h"
#include <syncevo/declarations.h>
@@ -279,6 +283,9 @@ class LogDirLogger : public Logger
{
Logger::Handle m_parentLogger; /**< the logger which was active before we started to intercept messages */
boost::weak_ptr<LogDir> m_logdir; /**< grants access to report and Synthesis engine */
+#ifdef USE_DLT
+ bool m_useDLT; /**< SyncEvolution and libsynthesis are logging to DLT */
+#endif
public:
LogDirLogger(const boost::weak_ptr<LogDir> &logdir);
@@ -930,6 +937,9 @@ private:
LogDirLogger::LogDirLogger(const boost::weak_ptr<LogDir> &logdir) :
m_parentLogger(Logger::instance()),
m_logdir(logdir)
+#ifdef USE_DLT
+ , m_useDLT(getenv("SYNCEVOLUTION_USE_DLT") != NULL)
+#endif
{
}
@@ -958,8 +968,16 @@ void LogDirLogger::messagev(const MessageOptions &options,
m_parentLogger.messagev(options, format, argscopy);
va_end(argscopy);
- boost::shared_ptr<LogDir> logdir = m_logdir.lock();
- if (logdir) {
+ // Special handling of our own messages: include in sync report
+ // (always, because that is how we did it traditionally) and write
+ // to our own syncevolution-log.html (if not already logged).
+ //
+ // The TestLocalSync.testServerFailure and some others check that
+ // we record the child's error message in our sync report. If we
+ // don't then it shows up later marked as an "error on the target
+ // side", which is probably not what we want.
+ boost::shared_ptr<LogDir> logdir;
+ if ((bool)(logdir = m_logdir.lock())) {
if (logdir->m_report &&
options.m_level <= ERROR &&
logdir->m_report->getError().empty()) {
@@ -971,7 +989,14 @@ void LogDirLogger::messagev(const MessageOptions &options,
logdir->m_report->setError(error);
}
- if (logdir->m_client.getEngine().get()) {
+ if (!(options.m_flags & MessageOptions::ALREADY_LOGGED) &&
+#ifdef USE_DLT
+ // Don't send to libsynthesis if using DLT,
+ // because then it would end up getting logged
+ // in DLT twice.
+ !m_useDLT &&
+#endif
+ logdir->m_client.getEngine().get()) {
va_list argscopy;
va_copy(argscopy, args);
// Once to Synthesis log, with full debugging.
@@ -2646,23 +2671,77 @@ void SyncContext::getConfigXML(string &xml, string &configname)
stringstream debug;
bool logging = !m_sourceListPtr->getLogdir().empty();
int loglevel = getLogLevel();
+#ifdef USE_DLT
+ const char *useDLT = getenv("SYNCEVOLUTION_USE_DLT");
+#else
+ static const char *useDLT = NULL;
+#endif
debug <<
" <debug>\n"
// logpath is a config variable set by SyncContext::doSync()
" <logpath>$(logpath)</logpath>\n"
- " <filename>" <<
- LogfileBasename << "</filename>" <<
+ " <filename>" << (useDLT ? "" : LogfileBasename) << "</filename>" <<
" <logflushmode>flush</logflushmode>\n"
- " <logformat>html</logformat>\n"
- " <folding>auto</folding>\n"
- " <timestamp>yes</timestamp>\n"
- " <timestampall>yes</timestampall>\n"
+ " <logformat>" << (useDLT ? "dlt" : "html") << "</logformat>\n"
+ " <folding>auto</folding>\n" <<
+ (useDLT ?
+ " <timestamp>no</timestamp>\n"
+ " <timestampall>no</timestampall>\n" :
+ " <timestamp>yes</timestamp>\n"
+ " <timestampall>yes</timestampall>\n") <<
" <timedsessionlognames>no</timedsessionlognames>\n"
" <subthreadmode>separate</subthreadmode>\n"
" <logsessionstoglobal>yes</logsessionstoglobal>\n"
" <singlegloballog>yes</singlegloballog>\n";
- if (logging) {
+#ifdef USE_DLT
+ if (useDLT) {
+ const char *contexts[] = {
+ "PROT",
+ "SESS",
+ "ADMN",
+ "DATA",
+ "REMI",
+ "PARS",
+ "GEN",
+ "TRNS",
+ "SMLT",
+ "SYS"
+ };
+ BOOST_FOREACH (const char *context, contexts) {
+ // Help libsynthesis debuglogger.cpp set default log levels,
+ // based on our own one.
+ SE_LOG_DEBUG(NULL, "default libsynthesis DLT logging of %s = %s",
+ context, useDLT);
+ setenv((std::string("LIBSYNTHESIS_") + context).c_str(),
+ useDLT,
+ false);
+ }
+
+ debug <<
+ // We have to enable all logging inside libsynthesis.
+ // The actual filtering then takes place inside DLT.
+ // Message logging is not supported.
+ " <enable option=\"all\"/>\n"
+ // Allow logging outside of sessions.
+ " <globallogs>yes</globallogs>\n"
+ // Don't try per-session logging, it all goes to DLT anyway.
+ " <sessionlogs>yes</sessionlogs>\n"
+ ;
+
+ // Be extra verbose if currently enabled. Cannot be changed later on.
+ if (atoi(useDLT) > DLT_LOG_DEBUG) {
+ debug <<
+ " <enable option=\"userdata\"/>\n"
+ " <enable option=\"scripts\"/>\n";
+ }
+ if (atoi(useDLT) > DLT_LOG_DEBUG) {
+ debug <<
+ " <enable option=\"exotic\"/>\n";
+ }
+ } else
+#endif // USE_DLT
+ if (logging) {
debug <<
" <sessionlogs>yes</sessionlogs>\n"
" <globallogs>yes</globallogs>\n";
diff --git a/src/syncevo/syncevo.am b/src/syncevo/syncevo.am
index 5d25ba4f..17940179 100644
--- a/src/syncevo/syncevo.am
+++ b/src/syncevo/syncevo.am
@@ -49,6 +49,8 @@ src_syncevo_sources = \
\
src/syncevo/Logging.h \
src/syncevo/Logging.cpp \
+ src/syncevo/LogDLT.h \
+ src/syncevo/LogDLT.cpp \
src/syncevo/LogStdout.h \
src/syncevo/LogStdout.cpp \
src/syncevo/LogRedirect.h \
@@ -212,6 +214,7 @@ src_syncevo_libsyncevolution_la_LIBADD = \
$(TRANSPORT_LIBS) \
@LIBS@ \
$(src_syncevo_ldadd) \
+ $(DLT_LIBS) \
$(DBUS_LIBS) \
$(NSS_LIBS)
if ENABLE_MODULES
@@ -228,6 +231,7 @@ src_syncevo_libsyncevolution_la_CFLAGS = \
$(SYNCEVO_WFLAGS)
src_syncevo_libsyncevolution_la_CPPFLAGS = \
$(src_syncevo_cppflags) \
+ $(DLT_CFLAGS) \
$(DBUS_CFLAGS) \
-DDATA_DIR=\""$(pkgdatadir)"\" \
-DXML_CONFIG_DIR=\""$(datadir)/syncevolution/xml"\" \
diff --git a/test/test-dbus.py b/test/test-dbus.py
index d6165cfa..720fd5d3 100755
--- a/test/test-dbus.py
+++ b/test/test-dbus.py
@@ -4317,7 +4317,7 @@ END:VCARD''')
'sending message to child failed: The connection is closed'))
self.assertSyncStatus('target_+config@client', 22002, 'synchronization process died prematurely')
- @timeout(200)
+ @timeout(600)
def testServerFailure(self):
"""TestLocalSync.testServerFailure - check that D-Bus helper detects when server dies"""
self.setUpConfigs(childPassword="-")