libreoffice-online/common/Log.cpp
Tor Lillqvist 95eb849217 Still more iOS app and related Online C++ code hacking
Re-think the plumbing between the different parts of the C++ Online
code. Do try to have it work more like in real Online on all but the
lowest socket level. Except that we don't have multiple processes, but
threads inside the same process. And instead of using actual system
sockets for WebSocket traffic between the threads, we use our own
FakeSocket things, with no WebSocket framing of messages.

Reduce the amount of #ifdef MOBILEAPP a bit also by compiling in the
UnitFoo things. Hardcode that so that no unit testing is ever
attempted, though. We don't try to dlopen any library.

Corresponding changes in the app Objective-C code. Plus fixes and
functionality improvements.

Now it gets so far that the JavaScript code thinks it has the document
tiles presented, and doesn't crash. But it hangs occasionally. And all
tiles show up blank.

Anyway, progress.

Change-Id: I769497c9a46ddb74984bc7af36d132b7b43895d4
2018-09-19 11:31:18 +03:00

200 lines
5.6 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <config.h>
#ifdef __linux
#include <sys/prctl.h>
#include <sys/syscall.h>
#endif
#include <unistd.h>
#include <atomic>
#include <cassert>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <string>
#include <Poco/ConsoleChannel.h>
#include <Poco/DateTimeFormatter.h>
#include <Poco/FileChannel.h>
#include <Poco/FormattingChannel.h>
#include <Poco/PatternFormatter.h>
#include <Poco/Process.h>
#include <Poco/SplitterChannel.h>
#include <Poco/Thread.h>
#include <Poco/Timestamp.h>
#include "Log.hpp"
#include "Util.hpp"
namespace Log
{
using namespace Poco;
/// Helper to avoid destruction ordering issues.
struct StaticNameHelper
{
std::atomic<bool> inited;
std::string name;
std::string id;
StaticNameHelper() :
inited(true)
{
}
~StaticNameHelper()
{
inited = false;
}
};
static StaticNameHelper Source;
// We need a signal safe means of writing messages
// $ man 7 signal
void signalLog(const char *message)
{
while (true)
{
const int length = strlen(message);
const int written = write (STDERR_FILENO, message, length);
if (written < 0)
{
if (errno == EINTR)
continue; // ignore.
else
break;
}
message += written;
if (message[0] == '\0')
break;
}
}
// We need a signal safe means of writing messages
// $ man 7 signal
void signalLogNumber(size_t num)
{
int i;
char buf[22];
buf[21] = '\0';
for (i = 20; i > 0 && num > 0; --i)
{
buf[i] = '0' + num % 10;
num /= 10;
}
signalLog(buf + i + 1);
}
char* prefix(char* buffer, const char* level, bool sigSafe)
{
#ifdef __linux
long osTid;
char procName[32];
const char *threadName = procName;
if (sigSafe)
{
osTid = syscall(SYS_gettid);
if (prctl(PR_GET_NAME, reinterpret_cast<unsigned long>(procName), 0, 0, 0) != 0)
strncpy(procName, "<noid>", sizeof(procName) - 1);
}
else
{
osTid = Util::getThreadId();
threadName = Util::getThreadName();
}
#elif defined IOS
const char *threadName = Util::getThreadName();
auto osTid = pthread_mach_thread_np(pthread_self());
#endif
Poco::DateTime time;
snprintf(buffer, 1023, "%s-%.05lu %.4u-%.2u-%.2u %.2u:%.2u:%.2u.%.6u [ %s ] %s ",
(Source.inited ? Source.id.c_str() : "<shutdown>"),
osTid,
time.year(), time.month(), time.day(),
time.hour(), time.minute(), time.second(),
time.millisecond() * 1000 + time.microsecond(),
threadName, level);
return buffer;
}
void signalLogPrefix()
{
char buffer[1024];
prefix(buffer, "SIG", true);
signalLog(buffer);
}
void initialize(const std::string& name,
const std::string& logLevel,
const bool withColor,
const bool logToFile,
const std::map<std::string, std::string>& config)
{
Source.name = name;
std::ostringstream oss;
oss << Source.name;
#ifndef MOBILEAPP // Just one process in a mobile app, the pid is uninteresting.
oss << '-'
<< std::setw(5) << std::setfill('0') << Poco::Process::id();
#endif
Source.id = oss.str();
// Configure the logger.
AutoPtr<Channel> channel;
if (logToFile)
{
channel = static_cast<Poco::Channel*>(new FileChannel("loolwsd.log"));
for (const auto& pair : config)
{
channel->setProperty(pair.first, pair.second);
}
}
else if (withColor)
channel = static_cast<Poco::Channel*>(new Poco::ColorConsoleChannel());
else
channel = static_cast<Poco::Channel*>(new Poco::ConsoleChannel());
/**
* Open the channel explicitly, instead of waiting for first log message
* This is important especially for the kit process where opening the channel
* after chroot can cause file creation inside the jail instead of outside
* */
channel->open();
auto& logger = Poco::Logger::create(Source.name, channel, Poco::Message::PRIO_TRACE);
logger.setLevel(logLevel.empty() ? std::string("trace") : logLevel);
const std::time_t t = std::time(nullptr);
oss.str("");
oss.clear();
oss << "Initializing " << name << ".";
// TODO: replace with std::put_time when we move to gcc 5+.
char buf[32];
if (strftime(buf, sizeof(buf), "%a %F %T%z", std::localtime(&t)) > 0)
{
oss << " Local time: " << buf << ".";
}
oss << " Log level is [" << logger.getLevel() << "].";
LOG_INF(oss.str());
}
Poco::Logger& logger()
{
return Poco::Logger::get(Source.inited ? Source.name : std::string());
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */