mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-02 12:07:52 +00:00
Bug 842393 - Documentation for Firefox Health Report; r=rnewman
DONTBUILD (docs only)
This commit is contained in:
parent
49d70bf739
commit
173f54b831
28
services/datareporting/README.rst
Normal file
28
services/datareporting/README.rst
Normal file
@ -0,0 +1,28 @@
|
||||
======================
|
||||
Data Reporting Service
|
||||
======================
|
||||
|
||||
This directory contains files related to data collection and reporting
|
||||
within Gecko applications.
|
||||
|
||||
The important files in this directory are:
|
||||
|
||||
DataReportingService.js
|
||||
An XPCOM service that coordinates collection and reporting of data.
|
||||
|
||||
policy.jsm
|
||||
A module containing the logic for coordinating and driving collection
|
||||
and upload of data.
|
||||
|
||||
sessions.jsm
|
||||
Records Gecko application session history. This is loaded as part of
|
||||
the XPCOM service because it needs to capture state from very early in
|
||||
the application lifecycle. Bug 841561 tracks implementing this in C++.
|
||||
|
||||
|
||||
There is other code in the tree that collects and uploads data. The
|
||||
original intent of this directory and XPCOM service was to serve as a
|
||||
focal point for the coordination of all this activity so that it could
|
||||
all be done consistently and properly. This vision may or may not be fully
|
||||
realized.
|
||||
|
@ -11,31 +11,49 @@ metrics and periodically submits them to a central server.
|
||||
Implementation Notes
|
||||
====================
|
||||
|
||||
The XPCOM service powering FHR is defined in HealthReportService.js. It
|
||||
simply instantiates an instance of HealthReporter from healthreporter.jsm.
|
||||
healthreporter.jsm contains the main interface for FHR, the
|
||||
*HealthReporter* type. An instance of this is created by the data
|
||||
reporting service. See /services/datareporting/.
|
||||
|
||||
All the logic for enforcing the privacy policy and for scheduling data
|
||||
submissions lives in policy.jsm.
|
||||
providers.jsm contains numerous Metrics.Provider and Metrics.Measurement
|
||||
used for collecting application metrics. If you are looking for the FHR
|
||||
probes, this is where they are.
|
||||
|
||||
Preferences
|
||||
===========
|
||||
|
||||
Preferences controlling behavior of Firefox Health Report live in the
|
||||
*healthreport.* branch.
|
||||
*datareporting.healthreport.* branch.
|
||||
|
||||
Some important preferences are:
|
||||
|
||||
* **healthreport.serviceEnabled** - Controls whether the entire health report
|
||||
* **service.enabled** - Controls whether the entire health report
|
||||
service runs. The overall service performs data collection, storing, and
|
||||
submission.
|
||||
submission. This is the primary kill switch for Firefox Health Report
|
||||
outside of the build system variable. i.e. if you are using an
|
||||
official Firefox build and wish to disable FHR, this is what you
|
||||
should change.
|
||||
|
||||
* **healthreport.policy.dataSubmissionEnabled** - Controls whether data
|
||||
submission is enabled. If this is *false*, data will still be collected
|
||||
and stored - it just won't ever be submitted to a remote server.
|
||||
* **uploadEnabled** - Whether uploading of data is enabled. This
|
||||
is the preference the checkbox in the UI reflects. If this is
|
||||
disabled, FHR still collects data - it just doesn't upload it.
|
||||
|
||||
If the entire service is disabled, you lose data collection. This means that
|
||||
data analysis won't be available because there is no data to analyze!
|
||||
|
||||
Registering Providers
|
||||
=====================
|
||||
|
||||
Firefox Health Report providers are registered via the category manager.
|
||||
See HealthReportComponents.manifest for providers defined in this
|
||||
directory.
|
||||
|
||||
Essentially, the category manager receives the name of a JS type and the
|
||||
URI of a JSM to import that exports this symbol. At run-time, the
|
||||
providers registered in the category manager are instantiated. This
|
||||
allows for a loose coupling of providers which in turns makes managing
|
||||
the code behind the providers much simpler.
|
||||
|
||||
Other Notes
|
||||
===========
|
||||
|
||||
|
109
services/metrics/README.rst
Normal file
109
services/metrics/README.rst
Normal file
@ -0,0 +1,109 @@
|
||||
============================
|
||||
Metrics Collection Framework
|
||||
============================
|
||||
|
||||
This directory contains generic code for collecting and persisting
|
||||
metrics data for Gecko applications.
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Metrics by itself doesn't do much. It simply provides a framework for
|
||||
collecting data. It is up to users of this framework to hook up the
|
||||
individual components into a system that makes sense for their purposes.
|
||||
An example consumer of Metrics is Firefox Health Report (see
|
||||
/services/healthreport).
|
||||
|
||||
Relationship to Telemetry
|
||||
-------------------------
|
||||
|
||||
Telemetry provides similar features to code in this directory. The two
|
||||
may be unified in the future.
|
||||
|
||||
Type Overview
|
||||
=============
|
||||
|
||||
This directory defines a number of JavaScript *types*/*classes*:
|
||||
|
||||
Metrics.Provider
|
||||
An entity that collects and manages data. A provider is typically
|
||||
domain-specific. e.g. AddonsProvider, SearchesProvider.
|
||||
|
||||
Metrics.Measurement
|
||||
Represents a collection of related pieces/fields of data. Instances of
|
||||
these are essentially data structure descriptors.
|
||||
|
||||
Metrics.Storage
|
||||
Persistent SQLite-backed store for collected metrics data and state.
|
||||
|
||||
Metrics.Collector
|
||||
High-level entity coordinating activity among several Metrics.Provider
|
||||
instances.
|
||||
|
||||
SQLite Storage
|
||||
==============
|
||||
|
||||
*Metrics.Storage* provides an interface for persisting metrics data to a
|
||||
SQLite database.
|
||||
|
||||
The storage API organizes values by fields. A field is a named member of
|
||||
a Measurement that has specific type and retention characteristics. Some
|
||||
example field types include:
|
||||
|
||||
* Last text value
|
||||
* Last numeric value for a given day
|
||||
* Discrete text values for a given day
|
||||
|
||||
See storage.jsm for more.
|
||||
|
||||
While SQLite is used under the hood, this implementation detail is
|
||||
hidden from the consumer.
|
||||
|
||||
Providers and Measurements
|
||||
==========================
|
||||
|
||||
The most important types in this framework are *Metrics.Provider* and
|
||||
*Metrics.Measurement*, henceforth known as *Provider* and *Measurement*,
|
||||
respectively. As you will see, these two types go hand in hand.
|
||||
|
||||
A Provider is an entity that *provides* data about a specific subsystem
|
||||
or feature. They do this by recording data to specific Measurement
|
||||
types. Both Provider and Measurement are abstract base types.
|
||||
|
||||
A Measurement implementation defines a name and version. More
|
||||
importantly, it also defines its storage requirements and how
|
||||
previously-stored values are serialized.
|
||||
|
||||
Storage allocation is performed by communicating with the SQLite
|
||||
backend. There is a startup function that tells SQLite what fields the
|
||||
measurement is recording. The storage backend then registers these in
|
||||
the database. Internally, this is creating a new primary key for
|
||||
individual fields so later storage operations can directly reference
|
||||
these primary keys in order to retrieve data without having to perform
|
||||
complicated joins.
|
||||
|
||||
A Provider can be thought of as a collection of Measurement
|
||||
implementations. e.g. an Addons provider may consist of a measurement
|
||||
for all *current* add-ons as well as a separate measurement for
|
||||
historical counts of add-ons. A provider's primary role is to take
|
||||
metrics data and write it to various measurements. This effectively
|
||||
persists the data to SQLite.
|
||||
|
||||
Data is emitted from providers in either a push or pull based mechanism.
|
||||
In push-based scenarios, the provider likely subscribes to external
|
||||
events (e.g. observer notifications). An event of interest can occur at
|
||||
any time. When it does, the provider immediately writes the event of
|
||||
interest to storage or buffers it for eventual writing. In pull-based
|
||||
scenarios, the provider is periodically queried and asked to populate
|
||||
data.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
To use the code in this directory, import Metrics.jsm. e.g.
|
||||
|
||||
Components.utils.import("resource://gre/modules/Metrics.jsm");
|
||||
|
||||
This exports a *Metrics* object which holds references to the main JS
|
||||
types and functions provided by this feature.
|
||||
|
@ -135,10 +135,26 @@ Measurement.prototype = Object.freeze({
|
||||
return this._serializers[format];
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether this measurement contains the named field.
|
||||
*
|
||||
* @param name
|
||||
* (string) Name of field.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
hasField: function (name) {
|
||||
return this._fieldsByName.has(name);
|
||||
},
|
||||
|
||||
/**
|
||||
* The unique identifier for a named field.
|
||||
*
|
||||
* This will throw if the field is not known.
|
||||
*
|
||||
* @param name
|
||||
* (string) Name of field.
|
||||
*/
|
||||
fieldID: function (name) {
|
||||
let entry = this._fieldsByName.get(name);
|
||||
|
||||
@ -192,41 +208,123 @@ Measurement.prototype = Object.freeze({
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Data Recording Functions
|
||||
//
|
||||
// Functions in this section are used to record new values against this
|
||||
// measurement instance.
|
||||
//
|
||||
// Generally speaking, these functions will throw if the specified field does
|
||||
// not exist or if the storage function requested is not appropriate for the
|
||||
// type of that field. These functions will also return a promise that will
|
||||
// be resolved when the underlying storage operation has completed.
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Increment a daily counter field in this measurement by 1.
|
||||
*
|
||||
* By default, the counter for the current day will be incremented.
|
||||
*
|
||||
* If the field is not known or is not a daily counter, this will throw.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param field
|
||||
* (string) The name of the field whose value to increment.
|
||||
* @param date
|
||||
* (Date) Day on which to increment the counter.
|
||||
* @return Promise<>
|
||||
*/
|
||||
incrementDailyCounter: function (field, date=new Date()) {
|
||||
return this.storage.incrementDailyCounterFromFieldID(this.fieldID(field),
|
||||
date);
|
||||
},
|
||||
|
||||
/**
|
||||
* Record a new numeric value for a daily discrete numeric field.
|
||||
*
|
||||
* @param field
|
||||
* (string) The name of the field to append a value to.
|
||||
* @param value
|
||||
* (Number) Number to append.
|
||||
* @param date
|
||||
* (Date) Day on which to append the value.
|
||||
*
|
||||
* @return Promise<>
|
||||
*/
|
||||
addDailyDiscreteNumeric: function (field, value, date=new Date()) {
|
||||
return this.storage.addDailyDiscreteNumericFromFieldID(
|
||||
this.fieldID(field), value, date);
|
||||
},
|
||||
|
||||
/**
|
||||
* Record a new text value for a daily discrete text field.
|
||||
*
|
||||
* This is like `addDailyDiscreteNumeric` but for daily discrete text fields.
|
||||
*/
|
||||
addDailyDiscreteText: function (field, value, date=new Date()) {
|
||||
return this.storage.addDailyDiscreteTextFromFieldID(
|
||||
this.fieldID(field), value, date);
|
||||
},
|
||||
|
||||
/**
|
||||
* Record the last seen value for a last numeric field.
|
||||
*
|
||||
* @param field
|
||||
* (string) The name of the field to set the value of.
|
||||
* @param value
|
||||
* (Number) The value to set.
|
||||
* @param date
|
||||
* (Date) When this value was recorded.
|
||||
*
|
||||
* @return Promise<>
|
||||
*/
|
||||
setLastNumeric: function (field, value, date=new Date()) {
|
||||
return this.storage.setLastNumericFromFieldID(this.fieldID(field), value,
|
||||
date);
|
||||
},
|
||||
|
||||
/**
|
||||
* Record the last seen value for a last text field.
|
||||
*
|
||||
* This is like `setLastNumeric` except for last text fields.
|
||||
*/
|
||||
setLastText: function (field, value, date=new Date()) {
|
||||
return this.storage.setLastTextFromFieldID(this.fieldID(field), value,
|
||||
date);
|
||||
},
|
||||
|
||||
/**
|
||||
* Record the most recent value for a daily last numeric field.
|
||||
*
|
||||
* @param field
|
||||
* (string) The name of a daily last numeric field.
|
||||
* @param value
|
||||
* (Number) The value to set.
|
||||
* @param date
|
||||
* (Date) Day on which to record the last value.
|
||||
*
|
||||
* @return Promise<>
|
||||
*/
|
||||
setDailyLastNumeric: function (field, value, date=new Date()) {
|
||||
return this.storage.setDailyLastNumericFromFieldID(this.fieldID(field),
|
||||
value, date);
|
||||
},
|
||||
|
||||
/**
|
||||
* Record the most recent value for a daily last text field.
|
||||
*
|
||||
* This is like `setDailyLastNumeric` except for a daily last text field.
|
||||
*/
|
||||
setDailyLastText: function (field, value, date=new Date()) {
|
||||
return this.storage.setDailyLastTextFromFieldID(this.fieldID(field),
|
||||
value, date);
|
||||
},
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// End of data recording APIs.
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Obtain all values stored for this measurement.
|
||||
*
|
||||
@ -564,6 +662,11 @@ Provider.prototype = Object.freeze({
|
||||
return this.storage.enqueueOperation(func);
|
||||
},
|
||||
|
||||
/**
|
||||
* Obtain persisted provider state.
|
||||
*
|
||||
* State is backend by storage.
|
||||
*/
|
||||
getState: function (key) {
|
||||
let name = this.name;
|
||||
let storage = this.storage;
|
||||
|
Loading…
x
Reference in New Issue
Block a user