Network Stats 2.0 proposal

Draft
This page is not complete.

Non-standard
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

This API is available on Firefox OS for internal applications only.

Proposal motivation

  • Add data usage alarms.
  • Add support to multiple SIMs.
  • Better support to time clock changes.
  • Allow to request stats without boundaries.
  • Clear stats for a given interface / SIM.
  • Add per-app network usage support

Summary

The Network Stats API allows to monitor data usage (system/per-app), exposes this data to certified applications and allows to set and manage data usage alarms. Data usage alarms can be set at a desired threshold for any available network interface.

Data and alarms can be access through the navigator.mozNetworkStats which is an instance of the mozNetworkStatsManager interface.

Accessing data

Information about the volume of received and sent data are automatically stored by the system/application. The method to access internal data is mozNetworkStatsManager.find(). This method expects the following parameters:

  • start: A Date object representing the beginning of data measurement.
  • end: A Date object representing the end of data measurement.
  • networkInterface: The origin of the data. It can be wifi or mobile. To know in advance which kind of origin is available, the mozNetworkStatsManager.availableInterfaces property return an Array of nsIDOMNetworkStatsInterface representing each supported origin. The nsIDOMNetworkStatsInterface will determine the type of the connection (wifi or mobile) and for mobile connections it will identify the SIM with an Id.
  • manifestURL: A string of a manifestURL for an application. This is an optional parameter, if manifestURL is provided, the target will be the data for the specific application. Otherwise the target is the system data.

When called, this method return a DOMRequest to handle the success or failure of the information request. In case of success the request's result is a mozNetworkStats object.

var networkInterfaces = navigator.mozNetworkStats.availableInterfaces;
   
var today = new Date();
var yesterday = new Date(today.getTime() - (24 * 60 * 60 * 1000));
   
var request = navigator.mozNetworkStats.find(networkIfaces[0], theDayBefore, today);

request.onsuccess = function () {
  console.log("Data received today: " + request.result.data[1].rxBytes + " bytes");
  console.log("Data sent today: " + request.result.data[1].txBytes + " bytes");
  console.log("Data received yesterday: " + request.result.data[0].rxBytes + " bytes");
  console.log("Data sent yesterday: " + request.result.data[0].txBytes + " bytes");
}

request.onerror = function () {
  console.log("Something goes wrong: " + request.error);
}
var networkInterfaces = navigator.mozNetworkStats.availableInterfaces;
   
var today = new Date();
var yesterday = new Date(today.getTime() - (24 * 60 * 60 * 1000));
   
var request = navigator.mozNetworkStats.find(networkIfaces[0], theDayBefore, today, "app://browser.gaiamobile.org/manifest.webapp");

request.onsuccess = function () {
  console.log("Data received today: " + request.result.data[1].rxBytes + " bytes");
  console.log("Data sent today: " + request.result.data[1].txBytes + " bytes");
  console.log("Data received yesterday: " + request.result.data[0].rxBytes + " bytes");
  console.log("Data sent yesterday: " + request.result.data[0].txBytes + " bytes");
}

request.onerror = function () {
  console.log("Something goes wrong: " + request.error);
}

Note that, the application manifestURL can be retrieved from mozApps API.

Clearing data stats

Historical data can be deleted through the method mozNetworkStatsManager.clearStats(), which expects an optional networkInterface object nsIDOMNetworkStatsInterface. If networkInterface is null, the data of all network interfaces is deleted. 

When called, this method returns a DOMRequest to handle the success or failure of the information request. In case of success the request's result is true.

var networkInterfaces = navigator.mozNetworkStats.availableInterfaces;

var request = navigator.mozNetworkStats.clearStats(networkInterfaces[0]);

request.onsuccess = function () {
  console.log("Data cleared successfully");
}

request.onerror = function () {
  console.log("Something goes wrong: ", request.error);
}

Sampling over time

To get a vision of the data usage over time, the information about the amount of data is stored in chunk, each chunk is a value representing the amount of data exchange since the last chunk was stored.

When requesting for the stats, the resulting mozNetworkStats object contain as much data chunk as possible for the interval define between the start and end date. The total number of chunks depend on two parameters (note that those parameters are read only):

Each data chunk is a mozNetworkStatsData object, and all the data chunks for a given time frame are available through the mozNetworkStats.data property, which is an Array of mozNetworkStatsData objects.

var rate = navigator.mozNetworkStats.sampleRate;
var max  = navigator.mozNetworkStats.maxStorageAge;

var config = {
  start: new Date((new Date()).getTime() - (rate * max)), // This allows to get all the available data chunks.
  end  : new Date()
};

var request = navigator.mozNetworkStats.find(config);

request.onsuccess = function () {
  var total = {
    receive: 0,
    send   : 0
  };

  this.result.forEach(function (chunk) {
    total.receive += chunk.rxBytes;
    total.send    += chunk.txBytes;
  });

  console.log("Since: " + config.start.toString());
  console.log("Data received: " + (total.receive / 1000).toFixed(2) + "Kb");
  console.log("Data sent: " + (total.send / 1000).toFixed(2) + "Kb")
}

request.onerror = function () {
  console.log("Something goes wrong: " + request.error);
}

Add data usage alarm

The API allows to set data usage alarms and receive a notification when a threshold is reached in some network interface. The mozNetworkStatsManager.addUsageAlarm() method expects the networkInterface parameter of type nsIDOMNetworkStatsInterface, the threshold that will trigger the alarm and a optional configuration object, which can contain the following properties:

  • alarmStart: A Date object representing the beginning of threshold measurement. If not provided, data measurement starts counting since the last data clear or the beginning.
  • data: A cloneable object to pass to the callback.

When called, this method return a DOMRequest to handle the success or failure of the information request. In case of success the request's result is the id of the alarm.

var networkIfaces = navigator.mozNetworkStats.availableInterfaces;

var options = {
  alarmStart: new Date((new Date()).getTime() - 24 * 60 * 60 * 1000)
};

var request = navigator.mozNetworkStats.addUsageAlarm(config[0], 10000, options);

request.onsuccess = function () {
  console.log("Alarm id: " + request.result);
}

request.onerror = function () {
  console.log("Something goes wrong: " + request.error);
}

Once the alarm is set, when the threshold is reached a notification is sent via system message containing a nsIDOMMozUsageAlarm object. The system message type is networkstats-alarm and requires the networkstats-manage permission.

Remove data usage alarms

To remove data usage alarms the mozNetworkStatsManager.removeUsageAlarms() method expects the id of the alarm to remove. If the id is not provided then all the alarms for the caller origin are removed.

When called, this method return a DOMRequest to handle the success or failure of the information request. In case of success the request's result is true.

Get data usage alarms

To get all data usage alarms the mozNetworkStatsManager.getAllUsageAlarms() method expects the optional networkInterface parameter of type nsIDOMNetworkStatsInterface to retrieve the alarms for one network interface. If no parameter is passed all alarms are returned for the requester origin.

When called, this method return a DOMRequest to handle the success or failure of the information request. In case of success the request's result is an Array of nsIDOMMozUsageAlarm objects.

var request = navigator.mozNetworkStats.getUsageAlarms();

request.onsuccess = function () {
  for (var i = 0; i < request.result.length; i++) {
    var alarm = request.result[i];
    console.log("Alarm " + alarm.id + " for connection " + alarm.iface + " at " + alarm.threshold);
  }
}

request.onerror = function () {
  console.log("Something goes wrong: " + request.error);
}

IDLs

nsIDOMMozNetworkStatsManager

/**
 * NetworkStats API registers transmitted and received bytes per each interface:
 * at the current moment wi-fi or mobile.
 *
 * Different mobile statistics and alarms are hold per different interfaces
 * in order to support SIM switching and multi SIM scenarios.
 */

dictionary AlarmUsageOptions
{
  jsval alarmStart;              // date
  jsval data;
};

[scriptable,  uuid(46526afc-a120-4fd5-87b6-f8134b071106)]
interface nsIDOMMozNetworkStatsManager : nsISupports
{

  /**
   * Constants for known interface types
   */
  const long WIFI = 1;
  const long MOBILE = 2;

  /**
   * Find samples between two dates start and end.
   *
   * Find method get samples with userTimestamp between start and end,
   * both included.
   *
   * If manifestURL is provided, Find method will retrieve per-app usage, 
   * otherwise the target will be system usage.
   *
   * If success, the request result will be an nsIDOMMozNetworkStats object.
   */
  nsIDOMDOMRequest find(in nsIDOMNetworkStatsInterfaces networkInterface,
                        in jsval start,
                        in jsval end
                        [optional] in DOMString manifestURL);

  /**
   * Remove all stats related with the provided interface from DB.
   * If interface is not provided, data of those interfaces returned by
   * availableInterfaces is cleared.
   */
  nsIDOMDOMRequest clearStats([optional] in nsIDOMNetworkStatsInterface networkInterface); 

  /**
   * Install an usage alarm on an interface. The interface must be in
   * availableInterfaces or an InvalidInterface error is passed in the
   * onError of the DOMRequest.
   *
   * When total data usage reaches threshold bytes, a system message is
   * sent to the application. Optional parameter data must be a cloneable
   * object and it is included inside the alarm system message.
   *
   * If success, the result field of the request keeps the alarm Id.
   *
   * Optional parameter options allows to set a validity interval for the
   * alarm and to include optional data that will be passed to the message handler.
   */
  nsIDOMDOMRequest               addUsageAlarm(in nsIDOMNetworkStatsInterface networkInterface,
                                               in long threshold,
                                               [optional] in jsval options /* AlarmUsageOptions */);

  /**
   * Obtain all alarms for those interfaces in availableInterfaces.
   * If an interface is provided, only retrieves the alarms
   * for that interface. The interface must be one of those in
   * availableInterfaces or an InvalidInterface error is passed in the
   * onError of the DOMRequest.
   *
   * If success, the request result will be an nsIDOMMozUsageAlarm object.
   */
  nsIDOMDOMRequest               getAllUsageAlarms([optional] in nsIDOMNetworkStatsInterface networkIface);

  /**
   * Remove all usage alarms. If an alarmId is provided, then only that
   * alarm is removed.
   */
  nsIDOMDOMRequest               removeUsageAlarms([optional] in long alarmId);

  /**
   * Return currently available interfaces.
   */
  readonly attribute jsval availableInterfaces; // array of nsIDOMNetworkStatsInterface
    
  /**
   * Minimum time in milliseconds between samples stored in the database.
   */
  readonly attribute long  sampleRate;

  /**
   * Time in milliseconds recorded by the API until present time. All samples
   * older than maxStorageAge from now are deleted.
   */
  readonly attribute long  maxStorageAge;
};

nsIDOMMozUsageAlarm

[scriptable, builtinclass, uuid(2dcd5394-ad90-45d0-a755-3da80095f22f)]
interface nsIDOMMozUsageAlarm : nsISupports
{
  readonly attribute unsigned long   alarmId;
  readonly attribute DOMString       iface;
  readonly attribute long            threshold;
  readonly attribute jsval           data;
  readonly attribute jsval           alarmStart;
};

nsIDOMMozNetworkStatsInterface

/**
 * Represents a data interface for which the manager is recording statistics.
 */
[scriptable, uuid(f540615b-d803-43ff-8200-2a9d145a5645)]
interface nsIDOMNetworkStatsInterface : nsISupports
{
  attribute long      type;
  attribute long      id;
};

nsIDOMMozNetworkStatsData

[scriptable, builtinclass, uuid(3b16fe17-5583-483a-b486-b64a3243221c)]
interface nsIDOMMozNetworkStatsData : nsISupports
{
  readonly attribute unsigned long   rxBytes;   // Received bytes.
  readonly attribute unsigned long   txBytes;   // Sent bytes.
  readonly attribute jsval           date;      // Date.
};

nsIDOMMozNetworkStats

[scriptable, builtinclass, uuid(037435a6-f563-48f3-99b3-a0106d8ba5bd)]
interface nsIDOMMozNetworkStats : nsISupports
{
  /**
   * Interface for which the returned data belongs to.
   */
  readonly attribute nsIDOMNetworkStatsInterface          networkInterface;

  /**
   * Stats for the interface. Samples are sorted by timestamp, increasing.
   */
  readonly attribute jsval              data; // array of NetworkStatsData.
  
  /**
   * Application ManifestURL
   */
  readonly attribute DOMString manifestURL;

  /**
   * Timestamp of the boundaries.
   */
  readonly attribute jsval   start;
  readonly attribute jsval   end;
};

Specification

Not part of any specification.

 

Document Tags and Contributors

 Contributors to this page: chrisdavidmills, teoli, johnshih, acperez
 Last updated by: chrisdavidmills,