Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* 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/. */
// An experimental logging interface for connecting the JS Engine to some
// (*cough*Gecko*cough*) consumer.
#ifndef _js_experimental_LoggingInterface_h_
#define _js_experimental_LoggingInterface_h_
#include "mozilla/LoggingCore.h"
#include "jstypes.h"
#include "js/GCAPI.h"
struct JSContext;
namespace JS {
// An Opaque pointer to a LoggerType. It must be possible for this logger type
// to conform to the interface below, using the LogLevel type exported in
// mozglue LoggingCore.h
//
// There are some requirements that we cannot express through the type-system:
//
// - A Logger must outlive any caller. This is an obvious statement, but in the
// context of the JS engine means that a logger must live until after the JS
// engine is shutdown.
// - A logger cannot move. The logging interfaces assumes 1) That an
// OpaqueLogger will remain a valid handle to a logger for the entire duration
// of an initialize JS library, and 2) We are able to cache a reference to the
// log level of a particular logger (see getLevelRef below).
using OpaqueLogger = void*;
// [SMDOC] Logging Interface
//
// The logging interface contains a set of function pointers which explain how
// to talk to an embedder provided logging system.
//
// The design of the JS Consumer of this relies heavily on these to be freely
// copyable.
struct LoggingInterface {
// Acquire a new logger for a given name.
//
// This interface has no way of indicating backwards that a logger is no
// longer needed, and as such this pointer needs to be kept alive by the
// embedding for the lifetime of the JS engine.
OpaqueLogger (*getLoggerByName)(const char* loggerName) = nullptr;
// Print a message to a particular logger with a particular level and
// format.
void (*logPrintVA)(const OpaqueLogger aModule, mozilla::LogLevel aLevel,
const char* aFmt, va_list ap)
MOZ_FORMAT_PRINTF(3, 0) = nullptr;
// Return a reference to the provided OpaqueLogger's level ref; Implementation
// wise this can be a small violation of encapsulation but is intended to help
// ensure that we can build lightweight logging without egregious costs to
// simply check even if a mesage will the writen
mozilla::AtomicLogLevel& (*getLevelRef)(OpaqueLogger) = nullptr;
// Wrapper function for calling va-version
void logPrint(const OpaqueLogger aModule, mozilla::LogLevel aLevel,
const char* aFmt, ...) MOZ_FORMAT_PRINTF(4, 5) {
JS::AutoSuppressGCAnalysis suppress;
va_list ap;
va_start(ap, aFmt);
this->logPrintVA(aModule, aLevel, aFmt, ap);
va_end(ap);
}
// Used to ensure that before we use an interface, it's successfully been
// completely filled in.
bool isComplete() const {
return getLoggerByName && logPrintVA && getLevelRef;
}
};
// Install the logging interface. This will also install the interface into
// any JS loggers
extern JS_PUBLIC_API bool SetLoggingInterface(LoggingInterface& iface);
} // namespace JS
#endif /* _js_experimental_LoggingInterface_h_ */