Update documentation to reflect both supported platforms everywh… (#389)

Update documentation to reflect both supported platforms everywhere
This commit is contained in:
Jan-Erik Rediger 2019-10-18 15:13:26 +02:00 коммит произвёл GitHub
Родитель 871eab0ef8 891e9df38f
Коммит f0b4fdcbbb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
16 изменённых файлов: 267 добавлений и 30 удалений

Просмотреть файл

@ -13,6 +13,10 @@ Products using the Glean SDK to collect telemetry **must**:
### Integrating with your project ### Integrating with your project
{{#include ../tab_header.md}}
<div data-lang="Kotlin" class="tab">
#### Setting up the dependency #### Setting up the dependency
Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](https://github.com/mozilla-mobile/android-components/blob/master/README.md#maven-repository)) by adding the following to your Gradle configuration: Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](https://github.com/mozilla-mobile/android-components/blob/master/README.md#maven-repository)) by adding the following to your Gradle configuration:
@ -58,20 +62,43 @@ apply from: 'https://raw.githubusercontent.com/mozilla-mobile/android-components
There are [additional parameters](android-build-configuration-options.md) that can be set to control the behavior of the `sdk_generator.gradle` script, but they are rarely used in normal use. There are [additional parameters](android-build-configuration-options.md) that can be set to control the behavior of the `sdk_generator.gradle` script, but they are rarely used in normal use.
</div>
<div data-lang="Swift" class="tab">
#### Setting up the dependency
Glean can be consumed through [Carthage](https://github.com/Carthage/Carthage), a dependency manager for macOS and iOS.
For consuming the latest version of Glean, add the following line to your `Cartfile`::
```
github "mozilla/glean" "master"
```
#### Integrating with the build system
> **Note:** This is not yet documented, as the exact mechanism is not finalized. See [Bug 1589383](https://bugzilla.mozilla.org/show_bug.cgi?id=1589383) for more information.
</div>
{{#include ../tab_footer.md}}
### Adding new metrics ### Adding new metrics
All metrics that your project collects must be defined in a `metrics.yaml` file. All metrics that your project collects must be defined in a `metrics.yaml` file.
This file should be at the root of the module (the same directory as the `build.gradle` file you updated). Add this file to your project and define it as an input file for the `sdk_generator.sh` script in the `Run Script` step defined before.
The format of that file is documented [with `glean_parser`](https://mozilla.github.io/glean_parser/metrics-yaml.html). The format of that file is documented [with `glean_parser`](https://mozilla.github.io/glean_parser/metrics-yaml.html).
To learn more, see [adding new metrics](adding-new-metrics.md). To learn more, see [adding new metrics](adding-new-metrics.md).
> **Important**: as stated [above](#before-using-glean), any new data collection requires documentation and data-review. This is also required for any new metric automatically collected by the Glean SDK. > **Important**: as stated [before](adding-glean-to-your-project.md#before-using-glean), any new data collection requires documentation and data-review.
> This is also required for any new metric automatically collected by the Glean SDK.
### Adding custom pings ### Adding custom pings
Please refer to the [custom pings documentation](pings/custom.md). Please refer to the [custom pings documentation](pings/custom.md).
> **Important**: as stated [above](#before-using-glean), any new data collection, including new custom pings, requires documentation and data-review. This is also required for any new ping automatically collected by the Glean SDK. > **Important**: as stated [before](adding-glean-to-your-project.md#before-using-glean), any new data collection requires documentation and data-review.
> This is also required for any new metric automatically collected by the Glean SDK.
### Testing metrics ### Testing metrics
@ -87,14 +114,17 @@ These specific steps are described in [the `probe_scraper` documentation](https:
The following steps are required for applications using the Glean SDK, but not libraries. The following steps are required for applications using the Glean SDK, but not libraries.
{{#include ../tab_header.md}}
<div data-lang="Kotlin" class="tab">
### Initializing the Glean SDK ### Initializing the Glean SDK
The Glean SDK should only be initialized from the main application, not individual libraries. If you are adding Glean support to a library, you can safely skip this section. The Glean SDK should only be initialized from the main application, not individual libraries. If you are adding Glean support to a library, you can safely skip this section.
Please also note that the Glean SDK does not support use across multiple processes, and must only be initialized on the application's main process. Initializing in other processes is a no-op. Please also note that the Glean SDK does not support use across multiple processes, and must only be initialized on the application's main process. Initializing in other processes is a no-op.
Additionally, Glean must be initialized on the main (UI) thread of the applications main process. Failure to do so will throw an `IllegalThreadStateException`. Additionally, Glean must be initialized on the main (UI) thread of the applications main process. Failure to do so will throw an `IllegalThreadStateException`.
Before any data collection can take place, the Glean SDK **must** be initialized from the application. An excellent place to initialize Glean is within the `onCreate` method of the class that extends Android's `Application` class.
An excellent place to perform this operation is within the `onCreate` method of the class that extends Android's `Application` class.
```Kotlin ```Kotlin
import org.mozilla.yourApplication.GleanMetrics.Pings import org.mozilla.yourApplication.GleanMetrics.Pings
@ -140,3 +170,64 @@ The application should provide some form of user interface to call this method.
When going from enabled to disabled, all pending events, metrics and pings are cleared, except for `first_run_date`. When going from enabled to disabled, all pending events, metrics and pings are cleared, except for `first_run_date`.
When re-enabling, core Glean metrics will be recomputed at that time. When re-enabling, core Glean metrics will be recomputed at that time.
</div>
<div data-lang="Swift" class="tab">
### Initializing the Glean SDK
The Glean SDK should only be initialized from the main application, not individual libraries.
If you are adding Glean support to a library, you can safely skip this section.
Please also note that the Glean SDK does not support use across multiple processes, and must only be initialized on the application's main process.
An excellent place to initialize Glean is within the `application(_:)` method of the class that extends the `UIApplicationDelegate` class.
```Swift
import Glean
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// If you have custom pings in your application, you must register them
// using the following command. This command should be omitted for
// applications not using custom pings.
Glean.shared.registerPings(GleanMetrics.Pings)
// Call setUploadEnabled first, since Glean.initialize
// might send pings if there are any metrics queued up
// from a previous run.
Glean.shared.setUploadEnabled(Settings.isTelemetryEnabled)
// Initialize the Glean library.
Glean.shared.initialize()
}
}
```
Once initialized, if collection is enabled, the Glean SDK will automatically start collecting [baseline metrics](pings/metrics.md) and sending its [pings](pings/index.md).
The Glean SDK should be initialized as soon as possible, and importantly, before any other libraries in the application start using Glean.
Library code should never call `Glean.shared.initialize`, since it should be called exactly once per application.
> **Note**: if the application has the concept of release channels and knows which channel it is on at run-time,
> then it can provide the Glean SDK with this information by setting it as part of the `Configuration` object parameter of the `Glean.shared.initialize` method. For example:
```Swift
Glean.shared.initialize(Configuration(channel: "beta"))
```
### Enabling and disabling metrics
`Glean.shared.setUploadEnabled()` should be called in response to the user enabling or disabling telemetry.
This method should also be called at least once prior to calling `Glean.shared.initialize()`.
The application should provide some form of user interface to call this method.
When going from enabled to disabled, all pending events, metrics and pings are cleared, except for `first_run_date`.
When re-enabling, core Glean metrics will be recomputed at that time.
</div>
{{#include ../tab_footer.md}}

Просмотреть файл

@ -1,7 +1,7 @@
# Adding new metrics # Adding new metrics
All metrics that your project collects must be defined in a `metrics.yaml` file. All metrics that your project collects must be defined in a `metrics.yaml` file.
This file should be at the root of the application or library module (the same directory as the `build.gradle` file you updated). This file should be at the root of the application or library module.
The format of that file is documented [here](https://mozilla.github.io/glean_parser/metrics-yaml.html). The format of that file is documented [here](https://mozilla.github.io/glean_parser/metrics-yaml.html).
When adding a new metric, the workflow is: When adding a new metric, the workflow is:
@ -47,7 +47,7 @@ category2.subcategory: # Categories can contain subcategories
The details of the metric parameters are described in [metric parameters](metric-parameters.md). The details of the metric parameters are described in [metric parameters](metric-parameters.md).
The `metrics.yaml` file is used to generate `Kotlin` code that becomes the public API to access your application's metrics. The `metrics.yaml` file is used to generate code in the target language (e.g. Kotlin, Swift, ...) that becomes the public API to access your application's metrics.
## Recommendations for defining new metrics ## Recommendations for defining new metrics
@ -93,7 +93,14 @@ If the metric is still needed, it should go back for [another round of data revi
## A note about case inflection ## A note about case inflection
Category and metric names in the `metrics.yaml` are in `snake_case`, but given the Kotlin coding standards defined by [ktlint](https://github.com/pinterest/ktlint), these identifiers must be `camelCase` in Kotlin. For example, the metric defined in the `metrics.yaml` as: {{#include ../tab_header.md}}
<div data-lang="Kotlin" class="tab">
Category and metric names in the `metrics.yaml` are in `snake_case`,
but given the Kotlin coding standards defined by [ktlint](https://github.com/pinterest/ktlint),
these identifiers must be `camelCase` in Kotlin.
For example, the metric defined in the `metrics.yaml` as:
```YAML ```YAML
@ -106,5 +113,30 @@ is accessible in Kotlin as:
```Kotlin ```Kotlin
import org.mozilla.yourApplication.GleanMetrics.Views import org.mozilla.yourApplication.GleanMetrics.Views
Views.loginOpened... GleanMetrics.Views.loginOpened...
``` ```
</div>
<div data-lang="Swift" class="tab">
Category and metric names in the `metrics.yaml` are in `snake_case`,
but given the Swift coding standards defined by [swiftlint](https://github.com/realm/SwiftLint),
these identifiers must be `camelCase` in Swift.
For example, the metric defined in the `metrics.yaml` as:
```YAML
views:
login_opened:
...
```
is accessible in Kotlin as:
```Swift
GleanMetrics.Views.loginOpened...
```
</div>
{{#include ../tab_footer.md}}

Просмотреть файл

@ -7,6 +7,10 @@ The Glean SDK supports tagging all its pings with experiments annotations. The a
## API ## API
{{#include ../tab_header.md}}
<div data-lang="Kotlin" class="tab">
```Kotlin ```Kotlin
// Annotate Glean pings with experiments data. // Annotate Glean pings with experiments data.
Glean.setExperimentActive( Glean.setExperimentActive(
@ -37,6 +41,16 @@ assertEquals(
) )
``` ```
</div>
<div data-lang="Swift" class="tab">
> **Note**: Experiments are currently not supported by Glean for iOS.
</div>
{{#include ../tab_footer.md}}
## Limits ## Limits
* `experimentId`, `branch`, and the keys of the 'extra' field are fixed at a maximum length of 30. Length for the values of the `extra` field is fixed at 50. Longer strings used as ids, keys, or values are truncated to their respective maximum length. For the original Kotlin implementation of the Glean SDK, this is measured in Unicode characters. For the Rust implementation, this is measured in the number of bytes when the string is encoded in UTF-8. * `experimentId`, `branch`, and the keys of the 'extra' field are fixed at a maximum length of 30. Length for the values of the `extra` field is fixed at 50. Longer strings used as ids, keys, or values are truncated to their respective maximum length. For the original Kotlin implementation of the Glean SDK, this is measured in Unicode characters. For the Rust implementation, this is measured in the number of bytes when the string is encoded in UTF-8.

Просмотреть файл

@ -77,4 +77,4 @@ XCTAssertTrue(try Flags.a11yEnabled.testGetValue())
## Reference ## Reference
* [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-boolean-metric-type/index.html) * [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-boolean-metric-type/index.html)
* [Swift API docs](../../../swift/Classes/BooleanMetricType.html)

Просмотреть файл

@ -78,4 +78,4 @@ XCTAssertEqual(6, try Controls.refreshPressed.testGetValue())
## Reference ## Reference
* [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-counter-metric-type/index.html) * [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-counter-metric-type/index.html)
* [Swift API docs](../../../swift/Classes/CounterMetricType.html)

Просмотреть файл

@ -81,6 +81,4 @@ assertEquals(2L, snapshot.count())
## Reference ## Reference
* See [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-custom-distribution-metric-type/index.html) * [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-custom-distribution-metric-type/index.html)

Просмотреть файл

@ -103,3 +103,4 @@ XCTAssertEqual(6, try Controls.refreshPressed.testGetValue())
## Reference ## Reference
* [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-datetime-metric-type/index.html) * [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-datetime-metric-type/index.html)
* [Swift API docs](../../../swift/Classes/DatetimeMetricType.html)

Просмотреть файл

@ -95,5 +95,5 @@ XCTAssertEqual("login_opened", first.name)
## Reference ## Reference
* See [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-event-metric-type/index.html). * [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-event-metric-type/index.html).
* [Swift API docs](../../../swift/Classes/EventMetricType.html)

Просмотреть файл

@ -95,3 +95,4 @@ XCTAssertEqual(3, try Stability.crashCount["native_code_crash"].testGetValue())
## Reference ## Reference
* Kotlin API docs [LabeledMetricType](../../../javadoc/glean/mozilla.telemetry.glean.private/-labeled-metric-type/index.html), [CounterMetricType](../../../javadoc/glean/mozilla.telemetry.glean.private/-counter-metric-type/index.html) * Kotlin API docs [LabeledMetricType](../../../javadoc/glean/mozilla.telemetry.glean.private/-labeled-metric-type/index.html), [CounterMetricType](../../../javadoc/glean/mozilla.telemetry.glean.private/-counter-metric-type/index.html)
* Swift API docs: [LabeledMetricType](../../../swift/Classes/LabeledMetricType.html), [CounterMetricType](../../../swift/Classes/CounterMetricType.html)

Просмотреть файл

@ -87,3 +87,4 @@ XCTAssert(Login.errorsByStage["server_auth"].testHasValue())
## Reference ## Reference
* Kotlin API docs: [LabeledMetricType](../../../javadoc/glean/mozilla.telemetry.glean.private/-labeled-metric-type/index.html), [StringMetricType](../../../javadoc/glean/mozilla.telemetry.glean.private/-string-metric-type/index.html) * Kotlin API docs: [LabeledMetricType](../../../javadoc/glean/mozilla.telemetry.glean.private/-labeled-metric-type/index.html), [StringMetricType](../../../javadoc/glean/mozilla.telemetry.glean.private/-string-metric-type/index.html)
* Swift API docs: [LabeledMetricType](../../../swift/Classes/LabeledMetricType.html), [StringMetricType](../../../swift/Classes/StringMetricType.html)

Просмотреть файл

@ -108,4 +108,5 @@ XCTAssertEqual(2, snapshot.count)
## Reference ## Reference
* See [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-memory-distribution-metric-type/index.html) * [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-memory-distribution-metric-type/index.html)
* [Swift API docs](../../../swift/Classes/MemoryDistributionMetricType.html)

Просмотреть файл

@ -91,3 +91,4 @@ XCTAssertEqual("wikipedia", try SearchDefault.name.testGetValue())
## Reference ## Reference
* [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-string-metric-type/index.html). * [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-string-metric-type/index.html).
* [Swift API docs](../../../swift/Classes/StringMetricType.html)

Просмотреть файл

@ -159,3 +159,4 @@ HistorySync.setRawNanos(duration)
## Reference ## Reference
* [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-timespan-metric-type/index.html) * [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-timespan-metric-type/index.html)
* [Swift API docs](../../../swift/Classes/TimespanMetricType.html)

Просмотреть файл

@ -34,7 +34,7 @@ For example, to measure page load time on a number of tabs that are loading at t
<div data-lang="Kotlin" class="tab"> <div data-lang="Kotlin" class="tab">
```Kotlin ```Kotlin
import mozilla.components.service.glean.timing.GleanTimerId import mozilla.components.service.glean.GleanTimerId
import org.mozilla.yourApplication.GleanMetrics.Pages import org.mozilla.yourApplication.GleanMetrics.Pages
val timerId : GleanTimerId val timerId : GleanTimerId
@ -129,4 +129,5 @@ XCTAssertEqual(2, snapshot.count)
## Reference ## Reference
* See [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-timing-distribution-metric-type/index.html) * [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-timing-distribution-metric-type/index.html)
* [Swift API docs](../../../swift/Classes/TimingDistributionMetricType.html)

Просмотреть файл

@ -80,5 +80,5 @@ XCTAssertEqual(uuid, try User.clientId.testGetValue())
## Reference ## Reference
* See [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-uuid-metric-type/index.html). * [Kotlin API docs](../../../javadoc/glean/mozilla.telemetry.glean.private/-uuid-metric-type/index.html).
* [Swift API docs](../../../swift/Classes/UuidMetricType.html)

Просмотреть файл

@ -2,11 +2,19 @@
In order to support unit testing inside of client applications using the Glean SDK, a set of testing API functions have been included. In order to support unit testing inside of client applications using the Glean SDK, a set of testing API functions have been included.
The intent is to make the Glean SDK easier to test 'out of the box' in any client application it may be used in. The intent is to make the Glean SDK easier to test 'out of the box' in any client application it may be used in.
These functions expose a way to inspect and validate recorded metric values within the client application but are restricted to test code only through visibility annotations (`@VisibleForTesting(otherwise = VisibleForTesting.NONE)`). These functions expose a way to inspect and validate recorded metric values within the client application but are restricted to test code only through visibility annotations
(`@VisibleForTesting(otherwise = VisibleForTesting.NONE)` for Kotlin, `internal` methods for Swift).
## General test API method semantics ## General test API method semantics
In order to prevent issues with async calls when unit testing Glean, it is important to put the Glean SDK into testing mode by applying the JUnit `GleanTestRule` to your test class. When the Glean SDK is in testing mode, it enables uploading and clears the recorded metrics at the beginning of each test run. The rule can be used as shown below: {{#include ../tab_header.md}}
<div data-lang="Kotlin" class="tab">
In order to prevent issues with async calls when unit testing Glean,
it is important to put the Glean SDK into testing mode by applying the JUnit `GleanTestRule` to your test class.
When the Glean SDK is in testing mode, it enables uploading and clears the recorded metrics at the beginning of each test run.
The rule can be used as shown below:
```kotlin ```kotlin
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
@ -39,7 +47,58 @@ This function will return a datatype appropriate to the specific type of the met
assertEquals("https://example.com/search?", GleanMetrics.Search.defaultSearchEngineUrl.testGetValue()) assertEquals("https://example.com/search?", GleanMetrics.Search.defaultSearchEngineUrl.testGetValue())
``` ```
Note that each of these functions has its visibility limited to the scope of unit tests by making use of the `@VisibleForTesting` annotation, so the IDE should complain if you attempt to use them inside of client code. Note that each of these functions has its visibility limited to the scope of unit tests by making use of the `@VisibleForTesting` annotation,
so the IDE should complain if you attempt to use them inside of client code.
</div>
<div data-lang="Swift" class="tab">
> **NOTE**: There's no automatic test rule for Glean tests implemented.
In order to prevent issues with async calls when unit testing Glean, it is important to put the Glean SDK into testing mode.
When the Glean SDK is in testing mode, it enables uploading and clears the recorded metrics at the beginning of each test run.
Activate it by resetting Glean in your test's setup:
```swift
@testable import Glean
import XCTest
class GleanUsageTests: XCTestCase {
override func setUp() {
Glean.shared.resetGlean(clearStores: true)
}
// ...
}
```
This will ensure that metrics are done recording when the other test functions are used.
To check if a value exists (i.e. it has been recorded), there is a `testHasValue()` function on each of the metric instances:
```Swift
XCTAssertTrue(GleanMetrics.Search.defaultSearchEngineUrl.testHasValue())
```
To check the actual values, there is a `testGetValue()` function on each of the metric instances.
It is important to check that the values are recorded as expected, since many of the metric types may truncate or error-correct the value.
This function will return a datatype appropriate to the specific type of the metric it is being used with:
```Swift
XCTAssertEqual("https://example.com/search?", try GleanMetrics.Search.defaultSearchEngineUrl.testGetValue())
```
Note that each of these functions is marked as `internal`, you need to import `Glean` explicitly in test mode:
```Swift
@testable import Glean
```
</div>
{{#include ../tab_footer.md}}
## Testing metrics for custom pings ## Testing metrics for custom pings
@ -53,13 +112,18 @@ You should only need to provide a `pingName` if the metric is being sent in more
You can call the `testHasValue()` and `testGetValue()` functions with `pingName` like this: You can call the `testHasValue()` and `testGetValue()` functions with `pingName` like this:
```kotlin ```kotlin
GleanMetrics.Foo.UriCount.testHasValue("customPing") GleanMetrics.Foo.uriCount.testHasValue("customPing")
GleanMetrics.Foo.UriCount.testGetValue("customPing") GleanMetrics.Foo.uriCount.testGetValue("customPing")
``` ```
## Example of using the test API ## Example of using the test API
{{#include ../tab_header.md}}
<div data-lang="Kotlin" class="tab">
Here is a longer example to better illustrate the intended use of the test API: Here is a longer example to better illustrate the intended use of the test API:
```kotlin ```kotlin
// Record a metric value with extra to validate against // Record a metric value with extra to validate against
GleanMetrics.BrowserEngagement.click.record( GleanMetrics.BrowserEngagement.click.record(
@ -84,3 +148,34 @@ assertEquals(3, events.size)
// Check extra key/value for first event in the list // Check extra key/value for first event in the list
assertEquals("Courier", events.elementAt(0).extra["font"]) assertEquals("Courier", events.elementAt(0).extra["font"])
``` ```
</div>
<div data-lang="Swift" class="tab">
Here is a longer example to better illustrate the intended use of the test API:
```Swift
// Record a metric value with extra to validate against
GleanMetrics.BrowserEngagement.click.record([.font: "Courier"])
// Record more events without extras attached
BrowserEngagement.click.record()
BrowserEngagement.click.record()
// Check if we collected any events into the 'click' metric
XCTAssertTrue(BrowserEngagement.click.testHasValue())
// Retrieve a snapshot of the recorded events
let events = try! BrowserEngagement.click.testGetValue()
// Check if we collected all 3 events in the snapshot
XCTAssertEqual(3, events.count)
// Check extra key/value for first event in the list
XCTAssertEqual("Courier", events[0].extra?["font"])
```
</div>
{{#include ../tab_footer.md}}