tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

LoggingInterface.h (3832B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 // An experimental logging interface for connecting the JS Engine to some
      8 // (*cough*Gecko*cough*) consumer.
      9 
     10 #ifndef _js_experimental_LoggingInterface_h_
     11 #define _js_experimental_LoggingInterface_h_
     12 
     13 #include "mozilla/LoggingCore.h"
     14 
     15 #include "jstypes.h"
     16 #include "fmt/format.h"
     17 #include "js/GCAPI.h"
     18 
     19 struct JSContext;
     20 
     21 namespace JS {
     22 
     23 // An Opaque pointer to a LoggerType. It must be possible for this logger type
     24 // to conform to the interface below, using the LogLevel type exported in
     25 // mozglue LoggingCore.h
     26 //
     27 // There are some requirements that we cannot express through the type-system:
     28 //
     29 // - A Logger must outlive any caller. This is an obvious statement, but in the
     30 //   context of the JS engine means that a logger must live until after the JS
     31 //   engine is shutdown.
     32 // - A logger cannot move. The logging interfaces assumes 1) That an
     33 //   OpaqueLogger will remain a valid handle to a logger for the entire duration
     34 //   of an initialize JS library, and 2) We are able to cache a reference to the
     35 //   log level of a particular logger (see getLevelRef below).
     36 using OpaqueLogger = void*;
     37 
     38 // [SMDOC] Logging Interface
     39 //
     40 // The logging interface contains a set of function pointers which explain how
     41 // to talk to an embedder provided logging system.
     42 //
     43 // The design of the JS Consumer of this relies heavily on these to be freely
     44 // copyable.
     45 struct LoggingInterface {
     46  // Acquire a new logger for a given name.
     47  //
     48  // This interface has no way of indicating backwards that a logger is no
     49  // longer needed, and as such this pointer needs to be kept alive by the
     50  // embedding for the lifetime of the JS engine.
     51  OpaqueLogger (*getLoggerByName)(const char* loggerName) = nullptr;
     52 
     53  // Print a message to a particular logger with a particular level and
     54  // format.
     55  void (*logPrintVA)(const OpaqueLogger aModule, mozilla::LogLevel aLevel,
     56                     const char* aFmt, va_list ap)
     57      MOZ_FORMAT_PRINTF(3, 0) = nullptr;
     58 
     59  void (*logPrintFMT)(const OpaqueLogger aModule, mozilla::LogLevel aLevel,
     60                      fmt::string_view, fmt::format_args);
     61 
     62  // Return a reference to the provided OpaqueLogger's level ref; Implementation
     63  // wise this can be a small violation of encapsulation but is intended to help
     64  // ensure that we can build lightweight logging without egregious costs to
     65  // simply check even if a mesage will the writen
     66  mozilla::AtomicLogLevel& (*getLevelRef)(OpaqueLogger) = nullptr;
     67 
     68  // Wrapper function for calling va-version
     69  void logPrint(const OpaqueLogger aModule, mozilla::LogLevel aLevel,
     70                const char* aFmt, ...) MOZ_FORMAT_PRINTF(4, 5) {
     71    JS::AutoSuppressGCAnalysis suppress;
     72    va_list ap;
     73    va_start(ap, aFmt);
     74    this->logPrintVA(aModule, aLevel, aFmt, ap);
     75    va_end(ap);
     76  }
     77 
     78  template <typename... T>
     79  void logPrintFmt(const OpaqueLogger aModule, mozilla::LogLevel aLevel,
     80                   fmt::format_string<T...> aFmt, T&&... aArgs) {
     81    JS::AutoSuppressGCAnalysis suppress;
     82    this->logPrintFMT(aModule, aLevel, aFmt, fmt::make_format_args(aArgs...));
     83  }
     84 
     85  // Used to ensure that before we use an interface, it's successfully been
     86  // completely filled in.
     87  bool isComplete() const {
     88    return getLoggerByName && logPrintVA && getLevelRef;
     89  }
     90 };
     91 
     92 // Install the logging interface. This will also install the interface into
     93 // any JS loggers
     94 extern JS_PUBLIC_API bool SetLoggingInterface(LoggingInterface& iface);
     95 
     96 }  // namespace JS
     97 
     98 #endif /* _js_experimental_LoggingInterface_h_ */