35 #define _GLIBCXX_USE_NANOSLEEP // gets us sleep_for() 41 #include "loggermessage.pb.h" 49 #include <sys/eventfd.h> 50 #include <sys/epoll.h> 55 const char * LEVELSTRING[] =
64 const unsigned short MAX_PACKET_LEN = 0xffff;
67 #define TOTAL_LEVELS (static_cast<int>(sizeof(LEVELSTRING) / sizeof(char *))) 68 #define MAX_LEVEL (TOTAL_LEVELS - 1) 74 u32LogSequenceNumber_{},
85 iEventFd_ = eventfd(0,0);
87 iepollFd_ = epoll_create1(0);
90 struct epoll_event ev;
92 ev.data.fd = iEventFd_;
93 epoll_ctl(iepollFd_,EPOLL_CTL_ADD,iEventFd_,&ev);
97 ev.data.fd = udpLoggerTxSocket_.
getHandle();
98 epoll_ctl(iepollFd_,EPOLL_CTL_ADD,udpLoggerTxSocket_.
getHandle(),&ev);
100 thread_ = std::thread{&LogService::processControlMessages,
this};
108 const uint64_t one{1};
109 write(iEventFd_,&one,
sizeof(one));
125 vlog_i(level,fmt,ap);
136 log_i(level, strings);
145 vlog_i(level, fmt, ap);
152 ofs_.open(file,std::ofstream::trunc);
163 bool EMANE::LogService::isLogAllowed(
LogLevel level)
const 165 return level <= level_;
173 bOpenBackend_ =
true;
179 thread_ = std::thread{&LogService::processControlMessages,
this};
184 void EMANE::LogService::processControlMessages(
void)
186 char buf[MAX_PACKET_LEN] ={0};
188 char errmsg[1024] = {0};
192 std::uint16_t * pu16HeaderLength =
reinterpret_cast<std::uint16_t *
> (buf);
194 int iMinExpectedLength =
static_cast<int> (
sizeof(*pu16HeaderLength));
196 struct epoll_event events[2];
204 nfds = epoll_wait(iepollFd_,events,2,-1);
211 for(
int n = 0; n < nfds; ++n)
213 if(events[n].data.fd == udpLoggerTxSocket_.
getHandle())
216 if((iRxLength = udpLoggerTxSocket_.
recv(buf,
sizeof(buf),0)) > iMinExpectedLength)
218 EMANEMessage::LoggerMessage loggerMessage;
220 if(!loggerMessage.ParseFromArray(buf +
sizeof(*pu16HeaderLength),
221 ntohs(*pu16HeaderLength)))
225 "!!! logger message failed ParseFromArray !!!");
227 writeLogString(errmsg);
231 if(loggerMessage.type() == EMANEMessage::LoggerMessage_Type_RECORD)
233 if(loggerMessage.has_record())
235 writeLogString(loggerMessage.record().record().c_str());
241 "!!! logger message type RECORD does NOT have record !!!");
243 writeLogString(errmsg);
250 "!!! unhandled logger message type %d !!!",
251 loggerMessage.type());
253 writeLogString(errmsg);
257 else if(iRxLength < 0)
262 "!!! socket read error (%s) !!!",
265 writeLogString(errmsg);
271 else if(iRxLength == 0)
274 snprintf(errmsg,
sizeof(errmsg),
"socket empty, bye");
276 writeLogString(errmsg);
285 snprintf(errmsg,
sizeof(errmsg),
286 "!!! socket read len of %d, msg length must be greater than %d, ignore !!!",
287 iRxLength, iMinExpectedLength);
289 writeLogString(errmsg);
306 void EMANE::LogService::log_i(
LogLevel level,
const char *fmt, ...)
312 vlog_i(level,fmt,ap);
321 std::string sMessage{};
323 std::for_each(strings.begin(),
325 [&sMessage](
const std::string & sPart){sMessage += sPart; sMessage.push_back(
' ');});
327 log_i(level,
"%s",sMessage.c_str());
331 void EMANE::LogService::vlog_i(
LogLevel level,
const char *fmt, va_list ap)
333 auto now = Clock::now();
335 std::time_t t{Clock::to_time_t(now)};
339 localtime_r(&t, <m);
343 char buff[iBuffSize] = {0};
345 int iLen = snprintf(buff,
sizeof(buff),
"%02d:%02d:%02d.%06lu %5s ",
349 std::chrono::duration_cast<Microseconds>(now.time_since_epoch()).count()%1000000,
350 level >= 0 && level <
TOTAL_LEVELS ? LEVELSTRING[level] :
"?");
352 if(iLen < 0 || iLen > iBuffSize)
358 int iAppended = vsnprintf(buff + iLen, iBuffSize - iLen, fmt, ap);
374 static_cast<size_t>(iLen),
376 u32LogSequenceNumber_++};
381 std::uint16_t u16HeaderLen = htons(serialization.size());
383 outputVector[0] =
Utils::make_iovec((
void *) &u16HeaderLen,
sizeof(u16HeaderLen));
384 outputVector[1] =
Utils::make_iovec((
void *) serialization.c_str(), serialization.size());
386 udpLoggerTxSocket_.
send(static_cast<const iovec*>(&outputVector[0]),
387 static_cast<int>(outputVector.size()),
388 localSocketAddress_);
392 void EMANE::LogService::writeLogString(
const char * pzLogMessage)
394 (*pStream_)<<pzLogMessage<<std::endl;
std::string Serialization
void open(const INETAddr &address, bool bReuseAddress=false)
void void vlog(LogLevel level, const char *format, va_list ap)
iovec make_iovec(void *base, std::size_t len)
ssize_t send(const iovec *iov, int iovcnt, const INETAddr &remoteAddress, int flags=0) const
std::vector< iovec > VectorIO
std::uint8_t buff[ETH_ALEN]
void log(LogLevel level, const char *format,...) __attribute__((format(printf
void redirectLogsToFile(const std::string &file)
std::chrono::duration< double > DoubleSeconds
std::list< std::string > Strings
ssize_t recv(void *buf, size_t len, int flags=0)
void setLogLevel(LogLevel level)
INETAddr getLocalAddress() const