Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  JOG.cpp   Sprache: C

 
/* -*- 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/. */


#include "mozilla/glean/bindings/jog/JOG.h"

#include <locale>

#include "mozilla/AppShutdown.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/glean/bindings/jog/jog_ffi_generated.h"
#include "mozilla/Logging.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/StaticPrefs_telemetry.h"
#include "mozilla/AppShutdown.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsThreadUtils.h"
#include "nsTHashMap.h"
#include "nsTHashSet.h"

namespace mozilla::glean {

static LazyLogModule sLog("jog");

// Storage
// Thread Safety: Only used on the main thread.
StaticAutoPtr<nsTHashSet<nsCString>> gCategories;
StaticAutoPtr<nsTHashMap<nsCString, uint32_t>> gMetrics;
StaticAutoPtr<nsTHashMap<uint32_t, nsCString>> gMetricNames;
StaticAutoPtr<nsTHashMap<nsCString, uint32_t>> gPings;

// static
bool JOG::HasCategory(const nsACString& aCategoryName) {
  MOZ_ASSERT(NS_IsMainThread());

  return gCategories && gCategories->Contains(aCategoryName);
}

static Maybe<bool> sFoundAndLoadedJogfile;

// static
bool JOG::EnsureRuntimeMetricsRegistered(bool aForce) {
  MOZ_ASSERT(NS_IsMainThread());

  if (sFoundAndLoadedJogfile) {
    return sFoundAndLoadedJogfile.value();
  }
  sFoundAndLoadedJogfile = Some(false);

  MOZ_LOG(sLog, LogLevel::Debug, ("Determining whether there's JOG for you."));

  if (!mozilla::StaticPrefs::telemetry_fog_artifact_build()) {
    // Supporting Artifact Builds is a developer-only thing.
    // We're on the main thread here.
    // Let's not spend any more time than we need to.
    MOZ_LOG(sLog, LogLevel::Debug,
            ("!telemetry.fog.artifact_build. No JOG for you."));
    return false;
  }
  // The metrics we need to process were placed in GreD in jogfile.json
  // That file was generated by
  // toolkit/components/glean/build_scripts/glean_parser_ext/jog.py
  nsCOMPtr<nsIFile> jogfile;
  if (NS_WARN_IF(NS_FAILED(
          NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(jogfile))))) {
    return false;
  }
  if (NS_WARN_IF(NS_FAILED(jogfile->Append(u"jogfile.json"_ns)))) {
    return false;
  }
  bool jogfileExists = false;
  if (NS_WARN_IF(NS_FAILED(jogfile->Exists(&jogfileExists))) ||
      !jogfileExists) {
    return false;
  }

  // We _could_ register everything here in C++ land,
  // but let's use Rust because (among other reasons) it's more fun.
  nsAutoString jogfileString;
  if (NS_WARN_IF(NS_FAILED(jogfile->GetPath(jogfileString)))) {
    return false;
  }
  sFoundAndLoadedJogfile = Some(jog::jog_load_jogfile(&jogfileString));
  MOZ_LOG(sLog, LogLevel::Debug,
          ("%s", sFoundAndLoadedJogfile.value()
                     ? "Found and loaded jogfile. Yes! JOG for you!"
                     : "Couldn't find and load jogfile. No JOG for you."));
  return sFoundAndLoadedJogfile.value();
}

// static
bool JOG::AreRuntimeMetricsComprehensive() {
  MOZ_ASSERT(NS_IsMainThread());
  return sFoundAndLoadedJogfile && sFoundAndLoadedJogfile.value();
}

// static
void JOG::GetCategoryNames(nsTArray<nsString>& aNames) {
  MOZ_ASSERT(NS_IsMainThread());
  if (!gCategories) {
    return;
  }
  for (const auto& category : *gCategories) {
    aNames.EmplaceBack(NS_ConvertUTF8toUTF16(category));
  }
}

// static
Maybe<uint32_t> JOG::GetMetric(const nsACString& aMetricName) {
  MOZ_ASSERT(NS_IsMainThread());
  return !gMetrics ? Nothing() : gMetrics->MaybeGet(aMetricName);
}

// static
Maybe<nsCString> JOG::GetMetricName(uint32_t aMetricId) {
  MOZ_ASSERT(NS_IsMainThread());
  return !gMetricNames ? Nothing() : gMetricNames->MaybeGet(aMetricId);
}

// static
void JOG::GetMetricNames(const nsACString& aCategoryName,
                         nsTArray<nsString>& aNames) {
  MOZ_ASSERT(NS_IsMainThread());
  if (!gMetricNames) {
    return;
  }
  for (const auto& identifier : gMetricNames->Values()) {
    if (StringBeginsWith(identifier, aCategoryName) &&
        identifier.CharAt(aCategoryName.Length()) == '.') {
      const char* metricName = &identifier.Data()[aCategoryName.Length() + 1];
      aNames.AppendElement()->AssignASCII(metricName);
    }
  }
}

// static
Maybe<uint32_t> JOG::GetPing(const nsACString& aPingName) {
  MOZ_ASSERT(NS_IsMainThread());
  return !gPings ? Nothing() : gPings->MaybeGet(aPingName);
}

// static
void JOG::GetPingNames(nsTArray<nsString>& aNames) {
  MOZ_ASSERT(NS_IsMainThread());
  if (!gPings) {
    return;
  }
  for (const auto& ping : gPings->Keys()) {
    aNames.EmplaceBack(NS_ConvertUTF8toUTF16(ping));
  }
}

}  // namespace mozilla::glean

// static
nsCString dottedSnakeToCamel(const nsACString& aSnake) {
  nsCString camel;
  bool first = true;
  for (const nsACString& segment : aSnake.Split('_')) {
    for (const nsACString& part : segment.Split('.')) {
      if (first) {
        first = false;
        camel.Append(part);
      } else if (part.Length()) {
        char lower = part.CharAt(0);
        if ('a' <= lower && lower <= 'z') {
          camel.Append(
              std::toupper(lower, std::locale()));  // append the Capital.
          camel.Append(part.BeginReading() + 1,
                       part.Length() - 1);  // append the rest.
        } else {
          // Not gonna try to capitalize anything outside a->z.
          camel.Append(part);
        }
      }
    }
  }
  return camel;
}

// static
nsCString kebabToCamel(const nsACString& aKebab) {
  nsCString camel;
  bool first = true;
  for (const nsACString& segment : aKebab.Split('-')) {
    if (first) {
      first = false;
      camel.Append(segment);
    } else if (segment.Length()) {
      char lower = segment.CharAt(0);
      if ('a' <= lower && lower <= 'z') {
        camel.Append(
            std::toupper(lower, std::locale()));  // append the Capital.
        camel.Append(segment.BeginReading() + 1,
                     segment.Length() - 1);  // append the rest.
      } else {
        // Not gonna try to capitalize anything outside a->z.
        camel.Append(segment);
      }
    }
  }
  return camel;
}

using mozilla::AppShutdown;
using mozilla::ShutdownPhase;
using mozilla::glean::gCategories;
using mozilla::glean::gMetricNames;
using mozilla::glean::gMetrics;
using mozilla::glean::gPings;

extern "C" NS_EXPORT void JOG_RegisterMetric(
    const nsACString& aCategory, const nsACString& aName,
    uint32_t aMetric,  // includes type.
    uint32_t aMetricId) {
  MOZ_ASSERT(NS_IsMainThread());

  if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown)) {
    return;
  }

  MOZ_LOG(mozilla::glean::sLog, mozilla::LogLevel::Verbose,
          ("Registering metric %s.%s id %" PRIu32 " id+type %" PRIu32 "",
           PromiseFlatCString(aCategory).get(), PromiseFlatCString(aName).get(),
           aMetricId, aMetric));

  // aCategory is dotted.snake_case. aName is snake_case.
  auto categoryCamel = dottedSnakeToCamel(aCategory);
  auto nameCamel = dottedSnakeToCamel(aName);

  // Register the category
  if (!gCategories) {
    gCategories = new nsTHashSet<nsCString>();
    RunOnShutdown([&] { gCategories = nullptr; },
                  ShutdownPhase::XPCOMWillShutdown);
  }
  gCategories->Insert(categoryCamel);

  // Register the metric
  if (!gMetrics) {
    gMetrics = new nsTHashMap<nsCString, uint32_t>();
    RunOnShutdown([&] { gMetrics = nullptr; },
                  ShutdownPhase::XPCOMWillShutdown);
  }
  gMetrics->InsertOrUpdate(categoryCamel + "."_ns + nameCamel, aMetric);

  // Register the metric name (for GIFFT)
  if (!gMetricNames) {
    gMetricNames = new nsTHashMap<uint32_t, nsCString>();
    RunOnShutdown([&] { gMetricNames = nullptr; },
                  ShutdownPhase::XPCOMWillShutdown);
  }
  gMetricNames->InsertOrUpdate(aMetricId, categoryCamel + "."_ns + nameCamel);
}

extern "C" NS_EXPORT void JOG_RegisterPing(const nsACString& aPingName,
                                           uint32_t aPingId) {
  MOZ_ASSERT(NS_IsMainThread());

  if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown)) {
    return;
  }

  // aPingName is kebab-case. JS expects camelCase.
  auto pingCamel = kebabToCamel(aPingName);

  // Register the ping
  if (!gPings) {
    gPings = new nsTHashMap<nsCString, uint32_t>();
    RunOnShutdown([&] { gPings = nullptr; }, ShutdownPhase::XPCOMWillShutdown);
  }
  gPings->InsertOrUpdate(pingCamel, aPingId);
}

Messung V0.5
C=92 H=85 G=88

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge