/****************************************************************************** * Copyright (c) 2016 EfficiOS Inc., Philippe Proulx * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Proulx, Philippe ******************************************************************************/ #include <unistd.h> #include <sys/time.h> #include <sys/types.h> #include <string> #include <iostream> #include <dlfcn.h> #ifndef TITAN_RUNTIME_2 #include "RT1/TitanLoggerApi.hh" #else #include "RT2/TitanLoggerApi.hh" #endif #include "LTTngUSTLogger.hh" #define TRACEPOINT_DEFINE #define TRACEPOINT_PROBE_DYNAMIC_LINKAGE #include "tp.hh" #ifndef RTLD_NODELETE # define RTLD_NODELETE 0 #endif #define TPP_SO_FILENAME "lttngust-logger-tp.so" extern "C" { ILoggerPlugin *create_plugin() { return new LTTngUSTLogger(); } void destroy_plugin(ILoggerPlugin *plugin) { delete plugin; } } LTTngUSTLogger::LTTngUSTLogger() { major_version_ = 1; minor_version_ = 0; name_ = mcopystr("LTTngUSTLogger"); help_ = mcopystr("LTTngUSTLogger writes CTF traces using LTTng-UST"); is_configured_ = true; /* Open tracepoint provider. */ hasTpp = (dlopen(TPP_SO_FILENAME, RTLD_NOW | RTLD_NODELETE) != NULL); if (!hasTpp) { TTCN_warning("Cannot open \"%s\" to load LTTng-UST tracepoint provider. " "The LTTngUSTLogger plugin will not emit LTTng-UST events.", TPP_SO_FILENAME); } } LTTngUSTLogger::~LTTngUSTLogger() { Free(name_); name_ = NULL; Free(help_); help_ = NULL; } CHARSTRING LTTngUSTLogger::joinStrings(const TitanLoggerApi::Strings& strings) { CHARSTRING mergedString(""); for (int i = 0; i < strings.str__list().n_elem(); i++) { if (i != 0) { mergedString += '\n'; } mergedString += strings.str__list()[i]; } return mergedString; } void LTTngUSTLogger::log(const TitanLoggerApi::TitanLogEvent& event, bool log_buffered, bool separate_file, bool use_emergency_mask) { using namespace TitanLoggerApi; if (!hasTpp) { return; } /* Read timestamp and severity (common arguments). */ const TimestampType& timestamp = event.timestamp(); int severity = (int) event.severity(); /* Log source infos of this event. */ for (int i = 0; i < event.sourceInfo__list().n_elem(); i++) { tracepoint(titan_core, sourceInfo, timestamp, severity, event.sourceInfo__list()[i]); } /* Log specific event type. */ const LogEventType_choice& eventTypeChoice = event.logEvent().choice(); switch (eventTypeChoice.get_selection()) { case LogEventType_choice::ALT_actionEvent: tracepoint(titan_core, actionEvent, timestamp, severity, (const char *) joinStrings(eventTypeChoice.actionEvent())); break; case LogEventType_choice::ALT_defaultEvent: { const DefaultEvent_choice& defaultEventChoice = eventTypeChoice.defaultEvent().choice(); switch (defaultEventChoice.get_selection()) { case DefaultEvent_choice::ALT_defaultopActivate: tracepoint(titan_core, defaultEvent_defaultopActivate, timestamp, severity, defaultEventChoice.defaultopActivate()); break; case DefaultEvent_choice::ALT_defaultopDeactivate: tracepoint(titan_core, defaultEvent_defaultopDeactivate, timestamp, severity, defaultEventChoice.defaultopDeactivate()); break; case DefaultEvent_choice::ALT_defaultopExit: tracepoint(titan_core, defaultEvent_defaultopExit, timestamp, severity, defaultEventChoice.defaultopExit()); break; default: break; } break; } case LogEventType_choice::ALT_errorLog: tracepoint(titan_core, errorLog, timestamp, severity, eventTypeChoice.errorLog()); break; case LogEventType_choice::ALT_executorEvent: { const ExecutorEvent_choice& executorEventChoice = eventTypeChoice.executorEvent().choice(); switch (executorEventChoice.get_selection()) { case ExecutorEvent_choice::ALT_executorRuntime: tracepoint(titan_core, executorEvent_executorRuntime, timestamp, severity, executorEventChoice.executorRuntime()); break; case ExecutorEvent_choice::ALT_executorConfigdata: tracepoint(titan_core, executorEvent_executorConfigdata, timestamp, severity, executorEventChoice.executorConfigdata()); break; case ExecutorEvent_choice::ALT_extcommandStart: tracepoint(titan_core, executorEvent_extcommandStart, timestamp, severity, executorEventChoice.extcommandStart()); break; case ExecutorEvent_choice::ALT_extcommandSuccess: tracepoint(titan_core, executorEvent_extcommandSuccess, timestamp, severity, executorEventChoice.extcommandSuccess()); break; case ExecutorEvent_choice::ALT_executorComponent: tracepoint(titan_core, executorEvent_executorComponent, timestamp, severity, executorEventChoice.executorComponent()); break; case ExecutorEvent_choice::ALT_logOptions: tracepoint(titan_core, executorEvent_logOptions, timestamp, severity, executorEventChoice.logOptions()); break; case ExecutorEvent_choice::ALT_executorMisc: tracepoint(titan_core, executorEvent_executorMisc, timestamp, severity, executorEventChoice.executorMisc()); break; default: break; } break; } case LogEventType_choice::ALT_functionEvent: { const FunctionEvent_choice& functionEventChoice = eventTypeChoice.functionEvent().choice(); switch (functionEventChoice.get_selection()) { case FunctionEvent_choice::ALT_unqualified: tracepoint(titan_core, functionEvent_unqualified, timestamp, severity, (const char *) functionEventChoice.unqualified()); break; case FunctionEvent_choice::ALT_random: tracepoint(titan_core, functionEvent_random, timestamp, severity, functionEventChoice.random()); break; default: break; } break; } case LogEventType_choice::ALT_parallelEvent: { const ParallelEvent_choice& parallelEventChoice = eventTypeChoice.parallelEvent().choice(); switch (parallelEventChoice.get_selection()) { case ParallelEvent_choice::ALT_parallelPTC: tracepoint(titan_core, parallelEvent_parallelPTC, timestamp, severity, parallelEventChoice.parallelPTC()); break; case ParallelEvent_choice::ALT_parallelPTC__exit: tracepoint(titan_core, parallelEvent_parallelPTC_exit, timestamp, severity, parallelEventChoice.parallelPTC__exit()); break; case ParallelEvent_choice::ALT_parallelPort: tracepoint(titan_core, parallelEvent_parallelPort, timestamp, severity, parallelEventChoice.parallelPort()); break; default: break; } break; } case LogEventType_choice::ALT_testcaseOp: { const TestcaseEvent_choice& testcaseEventChoice = eventTypeChoice.testcaseOp().choice(); switch (testcaseEventChoice.get_selection()) { case TestcaseEvent_choice::ALT_testcaseStarted: tracepoint(titan_core, testcaseOp_testcaseStarted, timestamp, severity, testcaseEventChoice.testcaseStarted()); break; case TestcaseEvent_choice::ALT_testcaseFinished: tracepoint(titan_core, testcaseOp_testcaseFinished, timestamp, severity, testcaseEventChoice.testcaseFinished()); break; default: break; } break; } case LogEventType_choice::ALT_portEvent: { const PortEvent_choice& portEventChoice = eventTypeChoice.portEvent().choice(); switch (portEventChoice.get_selection()) { case PortEvent_choice::ALT_portQueue: tracepoint(titan_core, portEvent_portQueue, timestamp, severity, portEventChoice.portQueue()); break; case PortEvent_choice::ALT_portState: tracepoint(titan_core, portEvent_portState, timestamp, severity, portEventChoice.portState()); break; case PortEvent_choice::ALT_procPortSend: tracepoint(titan_core, portEvent_procPortSend, timestamp, severity, portEventChoice.procPortSend()); break; case PortEvent_choice::ALT_procPortRecv: tracepoint(titan_core, portEvent_procPortRecv, timestamp, severity, portEventChoice.procPortRecv()); break; case PortEvent_choice::ALT_msgPortSend: tracepoint(titan_core, portEvent_msgPortSend, timestamp, severity, portEventChoice.msgPortSend()); break; case PortEvent_choice::ALT_msgPortRecv: tracepoint(titan_core, portEvent_msgPortRecv, timestamp, severity, portEventChoice.msgPortRecv()); break; case PortEvent_choice::ALT_dualMapped: tracepoint(titan_core, portEvent_dualMapped, timestamp, severity, portEventChoice.dualMapped()); break; case PortEvent_choice::ALT_dualDiscard: tracepoint(titan_core, portEvent_dualDiscard, timestamp, severity, portEventChoice.dualDiscard()); break; case PortEvent_choice::ALT_portMisc: tracepoint(titan_core, portEvent_portMisc, timestamp, severity, portEventChoice.portMisc()); break; default: break; } break; } case LogEventType_choice::ALT_statistics: { const StatisticsType_choice& statsChoice = eventTypeChoice.statistics().choice(); switch (statsChoice.get_selection()) { case StatisticsType_choice::ALT_verdictStatistics: tracepoint(titan_core, statistics_verdictStatistics, timestamp, severity, statsChoice.verdictStatistics()); break; case StatisticsType_choice::ALT_controlpartStart: tracepoint(titan_core, statistics_controlpartStart, timestamp, severity, statsChoice.controlpartStart()); break; case StatisticsType_choice::ALT_controlpartFinish: tracepoint(titan_core, statistics_controlpartFinish, timestamp, severity, statsChoice.controlpartFinish()); break; case StatisticsType_choice::ALT_controlpartErrors: tracepoint(titan_core, statistics_controlpartErrors, timestamp, severity, statsChoice.controlpartErrors()); break; default: break; } break; } case LogEventType_choice::ALT_timerEvent: { const TimerEvent_choice& timerEventChoice = eventTypeChoice.timerEvent().choice(); switch (timerEventChoice.get_selection()) { case TimerEvent_choice::ALT_readTimer: tracepoint(titan_core, timerEvent_readTimer, timestamp, severity, timerEventChoice.readTimer()); break; case TimerEvent_choice::ALT_startTimer: tracepoint(titan_core, timerEvent_startTimer, timestamp, severity, timerEventChoice.startTimer()); break; case TimerEvent_choice::ALT_guardTimer: tracepoint(titan_core, timerEvent_guardTimer, timestamp, severity, timerEventChoice.guardTimer()); break; case TimerEvent_choice::ALT_stopTimer: tracepoint(titan_core, timerEvent_stopTimer, timestamp, severity, timerEventChoice.stopTimer()); break; case TimerEvent_choice::ALT_timeoutTimer: tracepoint(titan_core, timerEvent_timeoutTimer, timestamp, severity, timerEventChoice.timeoutTimer()); break; case TimerEvent_choice::ALT_timeoutAnyTimer: tracepoint(titan_core, timerEvent_timeoutAnyTimer, timestamp, severity, timerEventChoice.timeoutAnyTimer()); break; case TimerEvent_choice::ALT_unqualifiedTimer: tracepoint(titan_core, timerEvent_unqualifiedTimer, timestamp, severity, (const char *) timerEventChoice.unqualifiedTimer()); break; default: break; } break; } case LogEventType_choice::ALT_userLog: tracepoint(titan_core, userLog, timestamp, severity, (const char *) joinStrings(eventTypeChoice.userLog())); break; case LogEventType_choice::ALT_verdictOp: { const VerdictOp_choice& verdictOpChoice = eventTypeChoice.verdictOp().choice(); switch (verdictOpChoice.get_selection()) { case VerdictOp_choice::ALT_setVerdict: tracepoint(titan_core, verdictOp_setVerdict, timestamp, severity, verdictOpChoice.setVerdict()); break; case VerdictOp_choice::ALT_getVerdict: tracepoint(titan_core, verdictOp_getVerdict, timestamp, severity, verdictOpChoice.getVerdict()); break; case VerdictOp_choice::ALT_finalVerdict: { const FinalVerdictType_choice& finalVerdictTypeChoice = verdictOpChoice.finalVerdict().choice(); switch (finalVerdictTypeChoice.get_selection()) { case FinalVerdictType_choice::ALT_info: tracepoint(titan_core, verdictOp_finalVerdict_info, timestamp, severity, finalVerdictTypeChoice.info()); break; case FinalVerdictType_choice::ALT_notification: tracepoint(titan_core, verdictOp_finalVerdict_notification, timestamp, severity, finalVerdictTypeChoice.notification()); break; default: break; } break; } default: break; } break; } case LogEventType_choice::ALT_warningLog: tracepoint(titan_core, warningLog, timestamp, severity, eventTypeChoice.warningLog()); break; case LogEventType_choice::ALT_matchingEvent: { const MatchingEvent_choice& matchingEventChoice = eventTypeChoice.matchingEvent().choice(); switch (matchingEventChoice.get_selection()) { case MatchingEvent_choice::ALT_matchingDone: tracepoint(titan_core, matchingEvent_matchingDone, timestamp, severity, matchingEventChoice.matchingDone()); break; case MatchingEvent_choice::ALT_matchingSuccess: tracepoint(titan_core, matchingEvent_matchingSuccess, timestamp, severity, matchingEventChoice.matchingSuccess()); break; case MatchingEvent_choice::ALT_matchingFailure: switch (matchingEventChoice.matchingFailure().choice().get_selection()) { case MatchingFailureType_choice::ALT_system__: tracepoint(titan_core, matchingEvent_matchingFailure_system, timestamp, severity, matchingEventChoice.matchingFailure()); break; case MatchingFailureType_choice::ALT_compref: tracepoint(titan_core, matchingEvent_matchingFailure_compref, timestamp, severity, matchingEventChoice.matchingFailure()); break; default: break; } break; case MatchingEvent_choice::ALT_matchingProblem: tracepoint(titan_core, matchingEvent_matchingProblem, timestamp, severity, matchingEventChoice.matchingProblem()); break; case MatchingEvent_choice::ALT_matchingTimeout: tracepoint(titan_core, matchingEvent_matchingTimeout, timestamp, severity, matchingEventChoice.matchingTimeout()); break; default: break; } break; } case LogEventType_choice::ALT_debugLog: tracepoint(titan_core, debugLog, timestamp, severity, eventTypeChoice.debugLog()); break; case LogEventType_choice::ALT_executionSummary: tracepoint(titan_core, executionSummary, timestamp, severity, eventTypeChoice.executionSummary()); break; case LogEventType_choice::ALT_unhandledEvent: tracepoint(titan_core, unhandledEvent, timestamp, severity, (const char *) eventTypeChoice.unhandledEvent()); break; default: break; } }