4c68a97ce5
Write to the Trace Event JSON file in just one place, protected by a mutex. Handle metadata events separately. We want them to propagate to the output if Event Trace generation is just enabled, regardless whether it has been turned on or not. We can send the metadata for the Kit process only after we have opened the docuemnt as sending a Trace Event to WSD uses the (singleton) Document object in Kit. Introduce some new functions for the above and adapt callers appropriately. Generate a Complete event for the handling of one image tile, from setting the src attribute of the Image object to finishing the onload function. Signed-off-by: Tor Lillqvist <tml@collabora.com> Change-Id: I5978e0fb2495e0d2dc479bf861eb4ac7da03fa50
204 lines
5.3 KiB
C++
204 lines
5.3 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
/*
|
|
* 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/.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <atomic>
|
|
#include <chrono>
|
|
#include <map>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#ifdef TEST_TRACEEVENT_EXE
|
|
#include <iostream>
|
|
#else
|
|
#include <Log.hpp>
|
|
#endif
|
|
|
|
// The base class for objects generating Trace Events when enabled.
|
|
//
|
|
// It depends on the embedding processs what is done to the Trace Events generated. In the WSD
|
|
// process they are written to the Trace Event log file as generated (as buffered by the C++
|
|
// library). In the Kit process they are buffered and then sent to the WSD process for writing to
|
|
// the same log file. In the TraceEvent test program they are written out to stdout.
|
|
|
|
class TraceEvent
|
|
{
|
|
private:
|
|
static void emitInstantEvent(const std::string& name, const std::string& args);
|
|
|
|
protected:
|
|
static std::atomic<bool> recordingOn; // True during recoding/emission
|
|
int _pid;
|
|
std::string _args;
|
|
thread_local static int threadLocalNesting; // For use only by the ProfileZone derived class
|
|
|
|
static long getThreadId()
|
|
{
|
|
#ifdef TEST_TRACEEVENT_EXE
|
|
static thread_local int threadId = 0;
|
|
static std::atomic<int> threadCounter(1);
|
|
|
|
if (!threadId)
|
|
threadId = threadCounter++;
|
|
return threadId;
|
|
#else
|
|
return Util::getThreadId();
|
|
#endif
|
|
}
|
|
|
|
static std::string createArgsString(const std::map<std::string, std::string>& args)
|
|
{
|
|
if (!recordingOn)
|
|
return "0";
|
|
|
|
std::string result = "{";
|
|
bool first = true;
|
|
for (auto i : args)
|
|
{
|
|
if (!first)
|
|
result += ',';
|
|
result += '"';
|
|
result += i.first;
|
|
result += "\":\"";
|
|
result += i.second;
|
|
result += '"';
|
|
first = false;
|
|
}
|
|
result += '}';
|
|
|
|
return result;
|
|
}
|
|
|
|
TraceEvent(const std::string &args)
|
|
: _pid(-1)
|
|
, _args(args)
|
|
{
|
|
if (recordingOn)
|
|
{
|
|
_pid = getpid();
|
|
}
|
|
}
|
|
|
|
public:
|
|
static void startRecording();
|
|
static void stopRecording();
|
|
static bool isRecordingOn()
|
|
{
|
|
return recordingOn;
|
|
}
|
|
|
|
static void emitInstantEvent(const std::string& name)
|
|
{
|
|
emitInstantEvent(name, "");
|
|
}
|
|
|
|
static void emitInstantEvent(const std::string& name, const std::map<std::string, std::string>& args)
|
|
{
|
|
emitInstantEvent(name, createArgsString(args));
|
|
}
|
|
|
|
// These methods need to be implemented separately in the WSD and Kit processes. (WSD writes the
|
|
// actual Trace Event log file, Kit just forwards the Trace Events to WSD for output.)
|
|
|
|
// This should do its thing if Trace Event generation is enabled, even if not turned on. Used
|
|
// for metadata that will be needed by a Trace Event viewer if Trace Event generation is turned
|
|
// on later during the process life-time.
|
|
static void emitOneRecordingIfEnabled(const std::string &recording);
|
|
|
|
// Unless Trace Event generation is enabled and turned on, this should do nothing.
|
|
static void emitOneRecording(const std::string &recording);
|
|
|
|
TraceEvent(const TraceEvent&) = delete;
|
|
void operator=(const TraceEvent&) = delete;
|
|
};
|
|
|
|
class NamedEvent : public TraceEvent
|
|
{
|
|
protected:
|
|
const std::string _name;
|
|
|
|
NamedEvent(const std::string& name)
|
|
: TraceEvent("")
|
|
, _name(name)
|
|
{
|
|
}
|
|
|
|
NamedEvent(const std::string& name, const std::string& args)
|
|
: TraceEvent(args)
|
|
, _name(name)
|
|
{
|
|
}
|
|
|
|
NamedEvent(const std::string& name, const std::map<std::string, std::string>& args)
|
|
: TraceEvent(createArgsString(args))
|
|
, _name(name)
|
|
{
|
|
}
|
|
};
|
|
|
|
class ProfileZone : public NamedEvent
|
|
{
|
|
private:
|
|
std::chrono::time_point<std::chrono::system_clock> _createTime;
|
|
int _nesting;
|
|
|
|
void emitRecording();
|
|
|
|
ProfileZone(const std::string& name, const std::string &args)
|
|
: NamedEvent(name, args)
|
|
, _nesting(-1)
|
|
{
|
|
if (recordingOn)
|
|
{
|
|
// Use system_clock as that matches the clock_gettime(CLOCK_REALTIME) that core uses.
|
|
_createTime = std::chrono::system_clock::now();
|
|
|
|
_nesting = threadLocalNesting++;
|
|
}
|
|
}
|
|
|
|
public:
|
|
ProfileZone(const std::string& name, const std::map<std::string, std::string> &arguments)
|
|
: ProfileZone(name, createArgsString(arguments))
|
|
{
|
|
}
|
|
|
|
ProfileZone(const char* id)
|
|
: ProfileZone(id, "")
|
|
{
|
|
}
|
|
|
|
~ProfileZone()
|
|
{
|
|
if (_pid > 0)
|
|
{
|
|
threadLocalNesting--;
|
|
|
|
if (_nesting != threadLocalNesting)
|
|
{
|
|
#ifdef TEST_TRACEEVENT_EXE
|
|
std::cerr << "Incorrect ProfileZone nesting for " << _name << "\n";
|
|
#else
|
|
LOG_WRN("Incorrect ProfileZone nesting for " << _name);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
emitRecording();
|
|
}
|
|
}
|
|
}
|
|
|
|
ProfileZone(const ProfileZone&) = delete;
|
|
void operator=(const ProfileZone&) = delete;
|
|
};
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|