Bug 1576730 - Support scalars in GeckoView Telemetry. r=chutten,snorp

Differential Revision: https://phabricator.services.mozilla.com/D44539

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Agi Sferro 2019-09-05 15:56:43 +00:00
Родитель 278200d665
Коммит 72e1ec0f20
12 изменённых файлов: 213 добавлений и 33 удалений

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

@ -44,6 +44,7 @@ import java.lang.Class;
import java.lang.Exception;
import java.lang.Float;
import java.lang.Integer;
import java.lang.Long;
import java.lang.Object;
import java.lang.Runnable;
import java.lang.RuntimeException;
@ -1110,13 +1111,16 @@ package org.mozilla.geckoview {
}
public static interface RuntimeTelemetry.Delegate {
method @AnyThread default public void onTelemetryReceived(@NonNull RuntimeTelemetry.Metric);
method @AnyThread default public void onBooleanScalar(@NonNull RuntimeTelemetry.Metric<Boolean>);
method @AnyThread default public void onHistogram(@NonNull RuntimeTelemetry.Metric<long[]>);
method @AnyThread default public void onLongScalar(@NonNull RuntimeTelemetry.Metric<Long>);
method @AnyThread default public void onStringScalar(@NonNull RuntimeTelemetry.Metric<String>);
}
public static class RuntimeTelemetry.Metric {
public static class RuntimeTelemetry.Metric<T> {
ctor protected Metric();
field @NonNull public final String name;
field @NonNull public final long[] values;
field @NonNull public final T value;
}
public class ScreenLength {

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

@ -8,6 +8,9 @@ const APIS = {
AddHistogram: function({ id, value }) {
browser.test.addHistogram(id, value);
},
SetScalar: function({ id, value }) {
browser.test.setScalar(id, value);
},
GetRequestedLocales: function() {
return browser.test.getRequestedLocales();
},

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

@ -108,6 +108,10 @@ this.test = class extends ExtensionAPI {
async addHistogram(id, value) {
return Services.telemetry.getHistogramById(id).add(value);
},
async setScalar(id, value) {
return Services.telemetry.scalarSet(id, value);
},
},
};
}

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

@ -88,6 +88,22 @@
"name": "value"
}
]
},
{
"name": "setScalar",
"type": "function",
"async": true,
"description": "Set the given value to the scalar with the given id.",
"parameters": [
{
"type": "string",
"name": "id"
},
{
"type": "any",
"name": "value"
}
]
}
]
}

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

@ -35,22 +35,46 @@ class TelemetryTest : BaseSessionTest() {
sessionRule.addHistogram("TELEMETRY_TEST_STREAMING", 1)
sessionRule.addHistogram("TELEMETRY_TEST_STREAMING", 109)
sessionRule.setScalar("telemetry.test.boolean_kind", true)
sessionRule.setScalar("telemetry.test.unsigned_int_kind", 1234)
sessionRule.setScalar("telemetry.test.string_kind", "test scalar")
// Forces flushing telemetry data at next histogram
sessionRule.setPrefsUntilTestEnd(mapOf("toolkit.telemetry.geckoview.batchDurationMS" to 0))
sessionRule.addHistogram("TELEMETRY_TEST_STREAMING", 2000)
val telemetryReceived = GeckoResult<Void>()
sessionRule.delegateDuringNextWait(object : RuntimeTelemetry.Delegate {
sessionRule.waitUntilCalled(object : RuntimeTelemetry.Delegate {
@AssertCalled
override fun onTelemetryReceived(metric: RuntimeTelemetry.Metric) {
override fun onHistogram(metric: RuntimeTelemetry.Metric<LongArray>) {
assertThat("Metric name should be correct", metric.name,
equalTo("TELEMETRY_TEST_STREAMING"))
assertThat("Metric name should be correct", metric.values,
assertThat("Metric name should be correct", metric.value,
equalTo(longArrayOf(401, 12, 1, 109, 2000)))
telemetryReceived.complete(null)
}
@AssertCalled
override fun onStringScalar(metric: RuntimeTelemetry.Metric<String>) {
assertThat("Metric name should be correct", metric.name,
equalTo("telemetry.test.string_kind"))
assertThat("Metric name should be correct", metric.value,
equalTo("test scalar"))
}
@AssertCalled
override fun onBooleanScalar(metric: RuntimeTelemetry.Metric<Boolean>) {
assertThat("Metric name should be correct", metric.name,
equalTo("telemetry.test.boolean_kind"))
assertThat("Metric name should be correct", metric.value,
equalTo(true))
}
@AssertCalled
override fun onLongScalar(metric: RuntimeTelemetry.Metric<Long>) {
assertThat("Metric name should be correct", metric.name,
equalTo("telemetry.test.unsigned_int_kind"))
assertThat("Metric name should be correct", metric.value,
equalTo(1234L))
}
})
sessionRule.addHistogram("TELEMETRY_TEST_STREAMING", 2000)
sessionRule.waitForResult(telemetryReceived)
}
}

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

@ -2038,6 +2038,19 @@ public class GeckoSessionTestRule implements TestRule {
void setArgs(JSONObject object) throws JSONException;
}
/**
* Sets value to the given scalar.
*
* @param id the scalar to be set.
* @param value the value to set.
*/
public <T> void setScalar(final String id, final T value) {
webExtensionApiCall("SetScalar", args -> {
args.put("id", id);
args.put("value", value);
});
}
private Object webExtensionApiCall(final String apiName, SetArgs argsSetter) {
// Ensure background script is connected
UiThreadUtils.waitForCondition(() -> RuntimeCreator.backgroundPort() != null,

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

@ -35,9 +35,30 @@ public class RuntimeCreator {
public RuntimeTelemetry.Delegate delegate = null;
@Override
public void onTelemetryReceived(@NonNull RuntimeTelemetry.Metric metric) {
public void onHistogram(@NonNull RuntimeTelemetry.Metric<long[]> metric) {
if (delegate != null) {
delegate.onTelemetryReceived(metric);
delegate.onHistogram(metric);
}
}
@Override
public void onBooleanScalar(@NonNull RuntimeTelemetry.Metric<Boolean> metric) {
if (delegate != null) {
delegate.onBooleanScalar(metric);
}
}
@Override
public void onStringScalar(@NonNull RuntimeTelemetry.Metric<String> metric) {
if (delegate != null) {
delegate.onStringScalar(metric);
}
}
@Override
public void onLongScalar(@NonNull RuntimeTelemetry.Metric<Long> metric) {
if (delegate != null) {
delegate.onLongScalar(metric);
}
}
}

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

@ -9,8 +9,6 @@ package org.mozilla.geckoview;
import android.support.annotation.AnyThread;
import android.support.annotation.NonNull;
import java.util.Arrays;
import org.json.JSONException;
import org.json.JSONObject;
@ -66,8 +64,10 @@ public final class RuntimeTelemetry {
/**
* The runtime telemetry metric object.
*
* @param <T> type of the underlying metric sample
*/
public static class Metric {
public static class Metric<T> {
/**
* The runtime metric name.
*/
@ -76,21 +76,22 @@ public final class RuntimeTelemetry {
/**
* The metric values.
*/
public final @NonNull long[] values;
public final @NonNull T value;
/* package */ Metric(final String name, final long[] values) {
/* package */ Metric(final String name, final T value) {
this.name = name;
this.values = values;
this.value = value;
}
@Override
public String toString() {
return "name: " + name + ", values: " + Arrays.toString(values);
return "name: " + name + ", value: " + value;
}
// For testing
protected Metric() {
this.name = null;
this.values = null;
name = null;
value = null;
}
}
@ -101,12 +102,36 @@ public final class RuntimeTelemetry {
*/
public interface Delegate {
/**
* A runtime telemetry metric has been received.
* A runtime telemetry histogram metric has been received.
*
* @param metric The runtime metric details.
*/
@AnyThread
default void onTelemetryReceived(final @NonNull Metric metric) {}
default void onHistogram(final @NonNull Metric<long[]> metric) {}
/**
* A runtime telemetry boolean scalar has been received.
*
* @param metric The runtime metric details.
*/
@AnyThread
default void onBooleanScalar(final @NonNull Metric<Boolean> metric) {}
/**
* A runtime telemetry long scalar has been received.
*
* @param metric The runtime metric details.
*/
@AnyThread
default void onLongScalar(final @NonNull Metric<Long> metric) {}
/**
* A runtime telemetry string scalar has been received.
*
* @param metric The runtime metric details.
*/
@AnyThread
default void onStringScalar(final @NonNull Metric<String> metric) {}
}
// The proxy connects to telemetry core and forwards telemetry events
@ -142,13 +167,40 @@ public final class RuntimeTelemetry {
private static native void registerDelegateProxy(Proxy proxy);
@WrapForJNI(calledFrom = "gecko")
/* package */ void dispatchTelemetry(
/* package */ void dispatchHistogram(
final String name, final long[] values) {
if (mDelegate == null) {
// TODO throw?
return;
}
mDelegate.onTelemetryReceived(new Metric(name, values));
mDelegate.onHistogram(new Metric<>(name, values));
}
@WrapForJNI(calledFrom = "gecko")
/* package */ void dispatchStringScalar(
final String name, final String value) {
if (mDelegate == null) {
return;
}
mDelegate.onStringScalar(new Metric<>(name, value));
}
@WrapForJNI(calledFrom = "gecko")
/* package */ void dispatchBooleanScalar(
final String name, final boolean value) {
if (mDelegate == null) {
return;
}
mDelegate.onBooleanScalar(new Metric<>(name, value));
}
@WrapForJNI(calledFrom = "gecko")
/* package */ void dispatchLongScalar(
final String name, final long value) {
if (mDelegate == null) {
return;
}
mDelegate.onLongScalar(new Metric<>(name, value));
}
@Override // JNIObject

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

@ -11,6 +11,22 @@ exclude: true
# GeckoView API Changelog.
⚠️ breaking change
## v71
- Added [`onBooleanScalar`][71.1], [`onLongScalar`][71.2],
[`onStringScalar`][71.3] to [`RuntimeTelemetry.Delegate`][70.12] to support
scalars in streaming telemetry. ⚠️ As part of this change,
`onTelemetryReceived` has been renamed to [`onHistogram`][71.4], and
[`Metric`][71.5] now takes a type parameter.
([bug 1576730]({{bugzilla}}1576730))
[71.1]: {{javadoc_uri}}/RuntimeTelemetry.Delegate.html#onBooleanScalar-org.mozilla.geckoview.RuntimeTelemetry.Metric-
[71.2]: {{javadoc_uri}}/RuntimeTelemetry.Delegate.html#onLongScalar-org.mozilla.geckoview.RuntimeTelemetry.Metric-
[71.3]: {{javadoc_uri}}/RuntimeTelemetry.Delegate.html#onStringScalar-org.mozilla.geckoview.RuntimeTelemetry.Metric-
[71.4]: {{javadoc_uri}}/RuntimeTelemetry.Delegate.html#onHistogram-org.mozilla.geckoview.RuntimeTelemetry.Metric-
[71.5]: {{javadoc_uri}}/RuntimeTelemetry.Metric.html
## v70
- Added API for session context assignment
[`GeckoSessionSettings.Builder.contextId`][70.1] and deletion of data related
@ -328,4 +344,4 @@ exclude: true
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
[65.25]: {{javadoc_uri}}/GeckoResult.html
[api-version]: 2ef7c30341c4cae55cdce87f62c19ae606435430
[api-version]: 0a0ac56ba2b8204077f874e49f4976a12051a18e

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

@ -1308,8 +1308,20 @@ public class GeckoViewActivity extends AppCompatActivity {
private final class ExampleTelemetryDelegate
implements RuntimeTelemetry.Delegate {
@Override
public void onTelemetryReceived(final @NonNull RuntimeTelemetry.Metric metric) {
Log.d(LOGTAG, "onTelemetryReceived " + metric);
public void onHistogram(final @NonNull RuntimeTelemetry.Metric<long[]> histogram) {
Log.d(LOGTAG, "onHistogram " + histogram);
}
@Override
public void onBooleanScalar(final @NonNull RuntimeTelemetry.Metric<Boolean> scalar) {
Log.d(LOGTAG, "onBooleanScalar " + scalar);
}
@Override
public void onLongScalar(final @NonNull RuntimeTelemetry.Metric<Long> scalar) {
Log.d(LOGTAG, "onLongScalar " + scalar);
}
@Override
public void onStringScalar(final @NonNull RuntimeTelemetry.Metric<String> scalar) {
Log.d(LOGTAG, "onStringScalar " + scalar);
}
}
}

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

@ -4615,6 +4615,7 @@ telemetry.test:
kind: uint
notification_emails:
- telemetry-client-dev@mozilla.com
release_channel_collection: opt-out
products:
- 'firefox'
- 'fennec'
@ -4631,6 +4632,7 @@ telemetry.test:
kind: string
notification_emails:
- telemetry-client-dev@mozilla.com
release_channel_collection: opt-out
products:
- 'firefox'
- 'fennec'
@ -4647,6 +4649,7 @@ telemetry.test:
kind: boolean
notification_emails:
- telemetry-client-dev@mozilla.com
release_channel_collection: opt-out
products:
- 'firefox'
- 'fennec'

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

@ -48,23 +48,35 @@ class GeckoTelemetryDelegate final
samples->AppendElement(static_cast<int64_t>(aSamples[i]));
}
mProxy->DispatchTelemetry(
mProxy->DispatchHistogram(
aName,
mozilla::jni::LongArray::New(samples->Elements(), samples->Length()));
}
void ReceiveBoolScalarValue(const nsCString& aName, bool aValue) override {
MOZ_ASSERT_UNREACHABLE("ReceiveBoolScalarValue unimplemented");
if (!mozilla::jni::IsAvailable() || !mProxy) {
return;
}
mProxy->DispatchBooleanScalar(aName, aValue);
}
void ReceiveStringScalarValue(const nsCString& aName,
const nsCString& aValue) override {
MOZ_ASSERT_UNREACHABLE("ReceiveStringScalarValue unimplemented");
if (!mozilla::jni::IsAvailable() || !mProxy) {
return;
}
mProxy->DispatchStringScalar(aName, aValue);
}
void ReceiveUintScalarValue(const nsCString& aName,
uint32_t aValue) override {
MOZ_ASSERT_UNREACHABLE("ReceiveUintScalarValue unimplemented");
if (!mozilla::jni::IsAvailable() || !mProxy) {
return;
}
mProxy->DispatchLongScalar(aName, static_cast<int64_t>(aValue));
}
mozilla::java::RuntimeTelemetry::Proxy::GlobalRef mProxy;