Bug 1267919 - Part 2. Add documentation and a schema for a new "sync" telemetry ping. r?bsmedberg,Dexter draft
authorThom Chiovoloni <tchiovoloni@mozilla.com>
Thu, 30 Jun 2016 10:28:18 -0400
changeset 386352 67b059ed58ea63a16fa8e24f2a117ca25eb58017
parent 386351 a14056332e0de815967fd9f4ea4b1c561ff8bfa9
child 386353 6441c97b88afa4b534b6d9ce0a2765a2787f7839
child 386354 b896d797a51d8ccd5212866ff18deba3bb0fe3a7
child 386355 08cf76891929399ca4f0e69c59e663b14f383a17
push id22688
push userbmo:tchiovoloni@mozilla.com
push dateMon, 11 Jul 2016 18:55:25 +0000
reviewersbsmedberg, Dexter
bugs1267919
milestone50.0a1
Bug 1267919 - Part 2. Add documentation and a schema for a new "sync" telemetry ping. r?bsmedberg,Dexter MozReview-Commit-ID: IOsvmqfF3WN
services/sync/tests/unit/sync_ping_schema.json
toolkit/components/telemetry/docs/index.rst
toolkit/components/telemetry/docs/pings.rst
toolkit/components/telemetry/docs/sync-ping.rst
new file mode 100644
--- /dev/null
+++ b/services/sync/tests/unit/sync_ping_schema.json
@@ -0,0 +1,147 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "description": "schema for Sync pings, documentation avaliable in toolkit/components/telemetry/docs/sync-ping.rst",
+  "type": "object",
+  "additionalProperties": false,
+  "required": ["when", "version", "took", "uid"],
+  "properties": {
+    "version": { "type": "integer", "minimum": 0 },
+    "didLogin": { "type": "boolean" },
+    "when": { "type": "integer" },
+    "status": {
+      "type": "object",
+      "anyOf": [
+        {"required": ["sync"]},
+        {"required": ["service"]}
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "sync": { "type": "string" },
+        "service": { "type": "string" }
+      }
+    },
+    "why": { "enum": ["startup", "schedule", "score", "user", "tabs"] },
+    "took": { "type": "integer", "minimum": -1 },
+    "uid": {
+      "type": "string",
+      "oneOf": [
+        { "pattern": "^[0-9a-f]{32}$" },
+        { "maxLength": 0 }
+      ]
+    },
+    "failureReason": { "$ref": "#/definitions/error" },
+    "engines": {
+      "type": "array",
+      "minItems": 1,
+      "items": { "$ref": "#/definitions/engine" }
+    }
+  },
+  "definitions": {
+    "engine": {
+      "required": ["name"],
+      "additionalProperties": false,
+      "properties": {
+        "failureReason": { "$ref": "#/definitions/error" },
+        "name": { "enum": ["addons", "bookmarks", "clients", "forms", "history", "passwords", "prefs", "tabs"] },
+        "took": { "type": "integer", "minimum": 1 },
+        "status": { "type": "string" },
+        "incoming": {
+          "type": "object",
+          "additionalProperties": false,
+          "anyOf": [
+            {"required": ["applied"]},
+            {"required": ["failed"]},
+            {"required": ["newFailed"]},
+            {"required": ["reconciled"]}
+          ],
+          "properties": {
+            "applied": { "type": "integer", "minimum": 1 },
+            "failed": { "type": "integer", "minimum": 1 },
+            "newFailed": { "type": "integer", "minimum": 1 },
+            "reconciled": { "type": "integer", "minimum": 1 }
+          }
+        },
+        "outgoing": {
+          "type": "array",
+          "minItems": 1,
+          "items": { "$ref": "#/definitions/outgoingBatch" }
+        },
+        "validation": {
+          "type": "array",
+          "minItems": 1,
+          "$ref": "#/definitions/validationProblem"
+        }
+      }
+    },
+    "outgoingBatch": {
+      "type": "object",
+      "additionalProperties": false,
+      "anyOf": [
+        {"required": ["sent"]},
+        {"required": ["failed"]}
+      ],
+      "properties": {
+        "sent": { "type": "integer", "minimum": 1 },
+        "failed": { "type": "integer", "minimum": 1 }
+      }
+    },
+    "error": {
+      "oneOf": [
+        { "$ref": "#/definitions/httpError" },
+        { "$ref": "#/definitions/nsError" },
+        { "$ref": "#/definitions/shutdownError" },
+        { "$ref": "#/definitions/authError" },
+        { "$ref": "#/definitions/otherError" },
+        { "$ref": "#/definitions/unexpectedError" }
+      ]
+    },
+    "httpError": {
+      "required": ["name", "code"],
+      "properties": {
+        "name": { "enum": ["httperror"] },
+        "code": { "type": "integer" }
+      }
+    },
+    "nsError": {
+      "required": ["name", "code"],
+      "properties": {
+        "name": { "enum": ["nserror"] },
+        "code": { "type": "integer" }
+      }
+    },
+    "shutdownError": {
+      "required": ["name"],
+      "properties": {
+        "name": { "enum": ["shutdownerror"] }
+      }
+    },
+    "authError": {
+      "required": ["name"],
+      "properties": {
+        "name": { "enum": ["autherror"] },
+        "from": { "enum": ["tokenserver", "fxaccounts", "hawkclient"] }
+      }
+    },
+    "otherError": {
+      "required": ["name"],
+      "properties": {
+        "name": { "enum": ["othererror"] },
+        "error": { "type": "string" }
+      }
+    },
+    "unexpectedError": {
+      "required": ["name"],
+      "properties": {
+        "name": { "enum": ["unexpectederror"] },
+        "error": { "type": "string" }
+      }
+    },
+    "validationProblem": {
+      "required": ["name", "count"],
+      "properties": {
+        "name": { "type": "string" },
+        "count": { "type": "integer" }
+      }
+    }
+  }
+}
\ No newline at end of file
--- a/toolkit/components/telemetry/docs/index.rst
+++ b/toolkit/components/telemetry/docs/index.rst
@@ -20,10 +20,11 @@ Client-side, this consists of:
    environment
    scalars
    main-ping
    core-ping
    deletion-ping
    crash-ping
    uitour-ping
    heartbeat-ping
+   sync-ping
    preferences
    crashes
--- a/toolkit/components/telemetry/docs/pings.rst
+++ b/toolkit/components/telemetry/docs/pings.rst
@@ -45,16 +45,17 @@ Ping types
 * :doc:`main <main-ping>` - contains the information collected by Telemetry (Histograms, hang stacks, ...)
 * :doc:`saved-session <main-ping>` - has the same format as a main ping, but it contains the *"classic"* Telemetry payload with measurements covering the whole browser session. This is only a separate type to make storage of saved-session easier server-side. This is temporary and will be removed soon.
 * :doc:`crash <crash-ping>` - a ping that is captured and sent after Firefox crashes.
 * :doc:`uitour-ping` - a ping submitted via the UITour API
 * ``activation`` - *planned* - sent right after installation or profile creation
 * ``upgrade`` - *planned* - sent right after an upgrade
 * :doc:`heartbeat-ping` - contains information on Heartbeat surveys
 * :doc:`deletion <deletion-ping>` - sent when FHR upload is disabled, requesting deletion of the data associated with this user
+* :doc:`sync <sync-ping>` - sent after a sync is completed or fails, contains information on sync errors and performance.
 
 Archiving
 =========
 
 When archiving is enabled through the relative preference, pings submitted to ``TelemetryController`` are also stored locally in the user profile directory, in `<profile-dir>/datareporting/archived`.
 
 To allow for cheaper lookup of archived pings, storage follows a specific naming scheme for both the directory and the ping file name: `<YYYY-MM>/<timestamp>.<UUID>.<type>.json`.
 
new file mode 100644
--- /dev/null
+++ b/toolkit/components/telemetry/docs/sync-ping.rst
@@ -0,0 +1,142 @@
+
+"sync" ping
+===========
+
+This ping is generated after a sync is completed, for both successful and failed syncs. It's payload contains measurements
+pertaining to sync performance and error information. It does not contain the enviroment block, nor the clientId.
+
+A JSON-schema document describing the exact format of the ping's payload property can be found at `services/sync/tests/unit/sync\_ping\_schema.json <https://dxr.mozilla.org/mozilla-central/source/services/sync/tests/unit/sync_ping_schema.json>`_.
+
+Structure::
+
+    {
+      version: 4,
+      type: "sync",
+      ... common ping data
+      payload: {
+        version: 1,
+        when: <integer milliseconds since epoch>,
+        took: <integer duration in milliseconds>,
+        uid: <string>, // FxA unique ID, or empty string.
+        didLogin: <bool>, // Optional, is this the first sync after login? Excluded if we don't know.
+        why: <string>, // Optional, why the sync occured, excluded if we don't know.
+
+        // Optional, excluded if there was no error.
+        failureReason: {
+          name: <string>, // "httperror", "networkerror", "shutdownerror", etc.
+          code: <integer>, // Only present for "httperror" and "networkerror".
+          error: <string>, // Only present for "othererror" and "unexpectederror".
+          from: <string>, // Optional, and only present for "autherror".
+        },
+        // Internal sync status information. Omitted if it would be empty.
+        status: {
+          sync: <string>, // The value of the Status.sync property, unless it indicates success.
+          service: <string>, // The value of the Status.service property, unless it indicates success.
+        },
+        // Information about each engine's sync.
+        engines: [
+          {
+            name: <string>, // "bookmarks", "tabs", etc.
+            took: <integer duration in milliseconds>, // Optional, values of 0 are omitted.
+
+            status: <string>, // The value of Status.engines, if it holds a non-success value.
+
+            // Optional, excluded if all items would be 0. A missing item indicates a value of 0.
+            incoming: {
+              applied: <integer>, // Number of records applied
+              succeeded: <integer>, // Number of records that applied without error
+              failed: <integer>, // Number of records that failed to apply
+              newFailed: <integer>, // Number of records that failed for the first time this sync
+              reconciled: <integer>, // Number of records that were reconciled
+            },
+
+            // Optional, excluded if it would be empty. Records that would be
+            // empty (e.g. 0 sent and 0 failed) are omitted.
+            outgoing: [
+              {
+                sent: <integer>, // Number of outgoing records sent. Zero values are omitted.
+                failed: <integer>, // Number that failed to send. Zero values are omitted.
+              }
+            ],
+            // Optional, excluded if there were no errors
+            failureReason: { ... }, // Same as above.
+
+            // Optional, excluded if it would be empty or if the engine cannot
+            // or did not run validation on itself. Entries with a count of 0
+            // are excluded.
+            validation: [
+              {
+                name: <string>, // The problem identified.
+                count: <integer>, // Number of times it occurred.
+              }
+            ]
+          }
+        ]
+      }
+    }
+
+info
+----
+
+took
+~~~~
+
+These values should be monotonic.  If we can't get a monotonic timestamp, -1 will be reported on the payload, and the values will be omitted from the engines. Additionally, the value will be omitted from an engine if it would be 0 (either due to timer inaccuracy or finishing instantaneously).
+
+uid
+~~~
+
+This property containing the FxA account identifier, which is provided by the FxA auth server APIs: `<https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md>`_. It may be an empty string in the case that we are unable to authenticate with FxA, and have never authenticated in the past.  If present, it should be a 32 character hexidecimal string.
+
+why
+~~~
+
+One of the following values:
+
+- ``startup``: This is the first sync triggered after browser startup.
+- ``schedule``: This is a sync triggered because it has been too long since the last sync.
+- ``score``: This sync is triggered by a high score value one of sync's trackers, indicating that many changes have occurred since the last sync.
+- ``user``: The user manually triggered the sync.
+- ``tabs``: The user opened the synced tabs sidebar, which triggers a sync.
+
+status
+~~~~~~
+
+The ``engine.status``, ``payload.status.sync``, and ``payload.status.service`` properties are sync error codes, which are listed in `services/sync/modules/constants.js <https://dxr.mozilla.org/mozilla-central/source/services/sync/modules/constants.js>`_, and success values are not reported.
+
+failureReason
+~~~~~~~~~~~~~
+
+Stores error information, if any is present. Always contains the "name" property, which identifies the type of error it is. The types can be.
+
+- ``httperror``: Indicates that we recieved an HTTP error response code, but are unable to be more specific about the error. Contains the following properties:
+
+    - ``code``: Integer HTTP status code.
+
+- ``nserror``: Indicates that an exception with the provided error code caused sync to fail.
+
+    - ``code``: The nsresult error code (integer).
+
+- ``shutdownerror``: Indicates that the sync failed because we shut down before completion.
+
+- ``autherror``: Indicates an unrecoverable authentication error.
+
+    - ``from``: Where the authentication error occurred, one of the following values: ``tokenserver``, ``fxaccounts``, or ``hawkclient``.
+
+- ``othererror``: Indicates that it is a sync error code that we are unable to give more specific information on. As with the ``syncStatus`` property, it is a sync error code, which are listed in `services/sync/modules/constants.js <https://dxr.mozilla.org/mozilla-central/source/services/sync/modules/constants.js>`_.
+
+    - ``error``: String identifying which error was present.
+
+- ``unexpectederror``: Indicates that some other error caused sync to fail, typically an uncaught exception.
+
+   - ``error``: The message provided by the error.
+
+engine.name
+~~~~~~~~~~~
+
+Third-party engines are not reported, so only the following values are allowed: ``addons``, ``bookmarks``, ``clients``, ``forms``, ``history``, ``passwords``, ``prefs``, and ``tabs``.
+
+engine.validation
+~~~~~~~~~~~~~~~~~
+
+For engines that can run validation on themselves, an array of objects describing validation errors that have occurred. Items that would have a count of 0 are excluded. Each engine will have its own set of items that it might put in the ``name`` field, but there are a finite number. See ``BookmarkProblemData.getSummary`` in `services/sync/modules/bookmark\_validator.js <https://dxr.mozilla.org/mozilla-central/source/services/sync/modules/bookmark_validator.js>`_ for an example.