Add an analytics domain to the analysis server.

BUG=
R=brianwilkerson@google.com

Review-Url: https://codereview.chromium.org/2922603002 .
This commit is contained in:
Devon Carew 2017-06-02 14:38:51 -07:00
parent 952687a64f
commit 511963d715
16 changed files with 1045 additions and 8 deletions

View file

@ -2492,6 +2492,7 @@ a:focus, a:hover {
<p>The diagnostic server port.</p>
</dd></dl></dd></dl>
<h2 class="domain"><a name="types">Types</a></h2>
<p>
This section contains descriptions of the data types referenced

View file

@ -4024,6 +4024,478 @@ class AnalysisUpdateOptionsResult implements ResponseResult {
}
}
/**
* analytics.enable params
*
* {
* "value": bool
* }
*
* Clients may not extend, implement or mix-in this class.
*/
class AnalyticsEnableParams implements RequestParams {
bool _value;
/**
* Enable or disable analytics.
*/
bool get value => _value;
/**
* Enable or disable analytics.
*/
void set value(bool value) {
assert(value != null);
this._value = value;
}
AnalyticsEnableParams(bool value) {
this.value = value;
}
factory AnalyticsEnableParams.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object json) {
if (json == null) {
json = {};
}
if (json is Map) {
bool value;
if (json.containsKey("value")) {
value = jsonDecoder.decodeBool(jsonPath + ".value", json["value"]);
} else {
throw jsonDecoder.mismatch(jsonPath, "value");
}
return new AnalyticsEnableParams(value);
} else {
throw jsonDecoder.mismatch(jsonPath, "analytics.enable params", json);
}
}
factory AnalyticsEnableParams.fromRequest(Request request) {
return new AnalyticsEnableParams.fromJson(
new RequestDecoder(request), "params", request.params);
}
@override
Map<String, dynamic> toJson() {
Map<String, dynamic> result = {};
result["value"] = value;
return result;
}
@override
Request toRequest(String id) {
return new Request(id, "analytics.enable", toJson());
}
@override
String toString() => JSON.encode(toJson());
@override
bool operator ==(other) {
if (other is AnalyticsEnableParams) {
return value == other.value;
}
return false;
}
@override
int get hashCode {
int hash = 0;
hash = JenkinsSmiHash.combine(hash, value.hashCode);
return JenkinsSmiHash.finish(hash);
}
}
/**
* analytics.enable result
*
* Clients may not extend, implement or mix-in this class.
*/
class AnalyticsEnableResult implements ResponseResult {
@override
Map<String, dynamic> toJson() => <String, dynamic>{};
@override
Response toResponse(String id) {
return new Response(id, result: null);
}
@override
bool operator ==(other) {
if (other is AnalyticsEnableResult) {
return true;
}
return false;
}
@override
int get hashCode {
return 237990792;
}
}
/**
* analytics.isEnabled params
*
* Clients may not extend, implement or mix-in this class.
*/
class AnalyticsIsEnabledParams implements RequestParams {
@override
Map<String, dynamic> toJson() => <String, dynamic>{};
@override
Request toRequest(String id) {
return new Request(id, "analytics.isEnabled", null);
}
@override
bool operator ==(other) {
if (other is AnalyticsIsEnabledParams) {
return true;
}
return false;
}
@override
int get hashCode {
return 57215544;
}
}
/**
* analytics.isEnabled result
*
* {
* "enabled": bool
* }
*
* Clients may not extend, implement or mix-in this class.
*/
class AnalyticsIsEnabledResult implements ResponseResult {
bool _enabled;
/**
* Whether sending analytics is enabled or not.
*/
bool get enabled => _enabled;
/**
* Whether sending analytics is enabled or not.
*/
void set enabled(bool value) {
assert(value != null);
this._enabled = value;
}
AnalyticsIsEnabledResult(bool enabled) {
this.enabled = enabled;
}
factory AnalyticsIsEnabledResult.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object json) {
if (json == null) {
json = {};
}
if (json is Map) {
bool enabled;
if (json.containsKey("enabled")) {
enabled =
jsonDecoder.decodeBool(jsonPath + ".enabled", json["enabled"]);
} else {
throw jsonDecoder.mismatch(jsonPath, "enabled");
}
return new AnalyticsIsEnabledResult(enabled);
} else {
throw jsonDecoder.mismatch(jsonPath, "analytics.isEnabled result", json);
}
}
factory AnalyticsIsEnabledResult.fromResponse(Response response) {
return new AnalyticsIsEnabledResult.fromJson(
new ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
"result",
response.result);
}
@override
Map<String, dynamic> toJson() {
Map<String, dynamic> result = {};
result["enabled"] = enabled;
return result;
}
@override
Response toResponse(String id) {
return new Response(id, result: toJson());
}
@override
String toString() => JSON.encode(toJson());
@override
bool operator ==(other) {
if (other is AnalyticsIsEnabledResult) {
return enabled == other.enabled;
}
return false;
}
@override
int get hashCode {
int hash = 0;
hash = JenkinsSmiHash.combine(hash, enabled.hashCode);
return JenkinsSmiHash.finish(hash);
}
}
/**
* analytics.sendEvent params
*
* {
* "action": String
* }
*
* Clients may not extend, implement or mix-in this class.
*/
class AnalyticsSendEventParams implements RequestParams {
String _action;
/**
* The value used to indicate which action was performed.
*/
String get action => _action;
/**
* The value used to indicate which action was performed.
*/
void set action(String value) {
assert(value != null);
this._action = value;
}
AnalyticsSendEventParams(String action) {
this.action = action;
}
factory AnalyticsSendEventParams.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object json) {
if (json == null) {
json = {};
}
if (json is Map) {
String action;
if (json.containsKey("action")) {
action = jsonDecoder.decodeString(jsonPath + ".action", json["action"]);
} else {
throw jsonDecoder.mismatch(jsonPath, "action");
}
return new AnalyticsSendEventParams(action);
} else {
throw jsonDecoder.mismatch(jsonPath, "analytics.sendEvent params", json);
}
}
factory AnalyticsSendEventParams.fromRequest(Request request) {
return new AnalyticsSendEventParams.fromJson(
new RequestDecoder(request), "params", request.params);
}
@override
Map<String, dynamic> toJson() {
Map<String, dynamic> result = {};
result["action"] = action;
return result;
}
@override
Request toRequest(String id) {
return new Request(id, "analytics.sendEvent", toJson());
}
@override
String toString() => JSON.encode(toJson());
@override
bool operator ==(other) {
if (other is AnalyticsSendEventParams) {
return action == other.action;
}
return false;
}
@override
int get hashCode {
int hash = 0;
hash = JenkinsSmiHash.combine(hash, action.hashCode);
return JenkinsSmiHash.finish(hash);
}
}
/**
* analytics.sendEvent result
*
* Clients may not extend, implement or mix-in this class.
*/
class AnalyticsSendEventResult implements ResponseResult {
@override
Map<String, dynamic> toJson() => <String, dynamic>{};
@override
Response toResponse(String id) {
return new Response(id, result: null);
}
@override
bool operator ==(other) {
if (other is AnalyticsSendEventResult) {
return true;
}
return false;
}
@override
int get hashCode {
return 227063188;
}
}
/**
* analytics.sendTiming params
*
* {
* "event": String
* "millis": int
* }
*
* Clients may not extend, implement or mix-in this class.
*/
class AnalyticsSendTimingParams implements RequestParams {
String _event;
int _millis;
/**
* The name of the event.
*/
String get event => _event;
/**
* The name of the event.
*/
void set event(String value) {
assert(value != null);
this._event = value;
}
/**
* The duration of the event in milliseconds.
*/
int get millis => _millis;
/**
* The duration of the event in milliseconds.
*/
void set millis(int value) {
assert(value != null);
this._millis = value;
}
AnalyticsSendTimingParams(String event, int millis) {
this.event = event;
this.millis = millis;
}
factory AnalyticsSendTimingParams.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object json) {
if (json == null) {
json = {};
}
if (json is Map) {
String event;
if (json.containsKey("event")) {
event = jsonDecoder.decodeString(jsonPath + ".event", json["event"]);
} else {
throw jsonDecoder.mismatch(jsonPath, "event");
}
int millis;
if (json.containsKey("millis")) {
millis = jsonDecoder.decodeInt(jsonPath + ".millis", json["millis"]);
} else {
throw jsonDecoder.mismatch(jsonPath, "millis");
}
return new AnalyticsSendTimingParams(event, millis);
} else {
throw jsonDecoder.mismatch(jsonPath, "analytics.sendTiming params", json);
}
}
factory AnalyticsSendTimingParams.fromRequest(Request request) {
return new AnalyticsSendTimingParams.fromJson(
new RequestDecoder(request), "params", request.params);
}
@override
Map<String, dynamic> toJson() {
Map<String, dynamic> result = {};
result["event"] = event;
result["millis"] = millis;
return result;
}
@override
Request toRequest(String id) {
return new Request(id, "analytics.sendTiming", toJson());
}
@override
String toString() => JSON.encode(toJson());
@override
bool operator ==(other) {
if (other is AnalyticsSendTimingParams) {
return event == other.event && millis == other.millis;
}
return false;
}
@override
int get hashCode {
int hash = 0;
hash = JenkinsSmiHash.combine(hash, event.hashCode);
hash = JenkinsSmiHash.combine(hash, millis.hashCode);
return JenkinsSmiHash.finish(hash);
}
}
/**
* analytics.sendTiming result
*
* Clients may not extend, implement or mix-in this class.
*/
class AnalyticsSendTimingResult implements ResponseResult {
@override
Map<String, dynamic> toJson() => <String, dynamic>{};
@override
Response toResponse(String id) {
return new Response(id, result: null);
}
@override
bool operator ==(other) {
if (other is AnalyticsSendTimingResult) {
return true;
}
return false;
}
@override
int get hashCode {
return 875010924;
}
}
/**
* completion.getSuggestions params
*

View file

@ -76,11 +76,25 @@ const String CONTENT = 'content';
const String CORRECTION = 'correction';
const String DART_DOC = 'dartdoc';
const String DEFAULT = 'default';
const String DIAGNOSTIC_GET_DIAGNOSTICS = 'diagnostic.getDiagnostics';
const String DIAGNOSTIC_GET_SERVER_PORT = 'diagnostic.getServerPort';
const String DISPLAY_NAME = 'displayName';
const String EDIT_FORMAT = 'edit.format';
const String EDIT_GET_ASSISTS = 'edit.getAssists';
const String EDIT_SORT_MEMBERS = 'edit.sortMembers';
const String EDITS = 'edits';
//
// Diagnostic methods
//
const String DIAGNOSTIC_GET_DIAGNOSTICS = 'diagnostic.getDiagnostics';
const String DIAGNOSTIC_GET_SERVER_PORT = 'diagnostic.getServerPort';
//
// Analytics methods
//
const String ANALYTICS_IS_ENABLED = 'analytics.isEnabled';
const String ANALYTICS_ENABLE = 'analytics.enable';
const String ANALYTICS_SEND_EVENT = 'analytics.sendEvent';
const String ANALYTICS_SEND_TIMING = 'analytics.sendTiming';
//
// Execution methods
@ -95,12 +109,6 @@ const String EDIT_GET_STATEMENT_COMPLETION = "edit.getStatementCompletion";
//
const String EDIT_ORGANIZE_DIRECTIVES = 'edit.organizeDirectives';
//
// Diagnostics methods
//
const String EDIT_SORT_MEMBERS = 'edit.sortMembers';
const String EDITS = 'edits';
//
// Analysis option names
//

View file

@ -0,0 +1,60 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:core';
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/constants.dart';
/// Instances of the class [AnalyticsDomainHandler] implement a [RequestHandler]
/// that handles requests in the `analytics` domain.
class AnalyticsDomainHandler implements RequestHandler {
final AnalysisServer server;
bool enabled = false;
AnalyticsDomainHandler(this.server);
// TODO(devoncarew): This implementation is currently mocked out.
Response handleEnable(Request request) {
// TODO(devoncarew): Implement.
AnalyticsEnableParams params =
new AnalyticsEnableParams.fromRequest(request);
enabled = params.value;
return new AnalyticsEnableResult().toResponse(request.id);
}
Response handleIsEnabled(Request request) {
// TODO(devoncarew): Implement.
return new AnalyticsIsEnabledResult(enabled).toResponse(request.id);
}
@override
Response handleRequest(Request request) {
String requestName = request.method;
if (requestName == ANALYTICS_IS_ENABLED) {
return handleIsEnabled(request);
} else if (requestName == ANALYTICS_ENABLE) {
return handleEnable(request);
} else if (requestName == ANALYTICS_SEND_EVENT) {
return handleSendEvent(request);
} else if (requestName == ANALYTICS_SEND_TIMING) {
return handleSendTiming(request);
}
return null;
}
Response handleSendEvent(Request request) {
// TODO(devoncarew): Implement.
return new AnalyticsSendEventResult().toResponse(request.id);
}
Response handleSendTiming(Request request) {
// TODO(devoncarew): Implement.
return new AnalyticsSendTimingResult().toResponse(request.id);
}
}

View file

@ -15,6 +15,7 @@ import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_analysis.dart';
import 'package:analysis_server/src/domain_analytics.dart';
import 'package:analysis_server/src/domain_completion.dart';
import 'package:analysis_server/src/domain_diagnostic.dart';
import 'package:analysis_server/src/domain_execution.dart';
@ -306,6 +307,9 @@ class ServerPlugin implements Plugin {
(AnalysisServer server) => new ExecutionDomainHandler(server));
registerExtension(domainId,
(AnalysisServer server) => new DiagnosticDomainHandler(server));
registerExtension(domainId,
(AnalysisServer server) => new AnalyticsDomainHandler(server));
//
// Register fix contributors.
//

View file

@ -0,0 +1,33 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../support/integration_tests.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(EnableTest);
});
}
@reflectiveTest
class EnableTest extends AbstractAnalysisServerIntegrationTest {
test_call_enable() async {
standardAnalysisSetup();
// Toggle the value twice, and verify the changes.
AnalyticsIsEnabledResult result1 = await sendAnalyticsIsEnabled();
await sendAnalyticsEnable(!result1.enabled);
AnalyticsIsEnabledResult result2 = await sendAnalyticsIsEnabled();
expect(result2.enabled, !result1.enabled);
await sendAnalyticsEnable(result1.enabled);
result2 = await sendAnalyticsIsEnabled();
expect(result2.enabled, result1.enabled);
}
}

View file

@ -0,0 +1,26 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../support/integration_tests.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(IsEnabledTest);
});
}
@reflectiveTest
class IsEnabledTest extends AbstractAnalysisServerIntegrationTest {
test_isEnabled() async {
standardAnalysisSetup();
AnalyticsIsEnabledResult result = await sendAnalyticsIsEnabled();
// Very lightweight validation of the returned data.
expect(result, isNotNull);
}
}

View file

@ -0,0 +1,31 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../support/integration_tests.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(SendEventTest);
});
}
@reflectiveTest
class SendEventTest extends AbstractAnalysisServerIntegrationTest {
test_send_event() async {
standardAnalysisSetup();
// Disable analytics.
AnalyticsIsEnabledResult result1 = await sendAnalyticsIsEnabled();
await sendAnalyticsEnable(false);
// Send an event.
await sendAnalyticsSendEvent('test-action');
// Restore the original value.
await sendAnalyticsEnable(result1.enabled);
}
}

View file

@ -0,0 +1,31 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../support/integration_tests.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(SendTimingTest);
});
}
@reflectiveTest
class SendTimingTest extends AbstractAnalysisServerIntegrationTest {
test_send_timing() async {
standardAnalysisSetup();
// Disable analytics.
AnalyticsIsEnabledResult result1 = await sendAnalyticsIsEnabled();
await sendAnalyticsEnable(false);
// Send an event.
await sendAnalyticsSendTiming('test-action', 100);
// Restore the original value.
await sendAnalyticsEnable(result1.enabled);
}
}

View file

@ -0,0 +1,19 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'enable_test.dart' as enable_test;
import 'is_enabled_test.dart' as is_enabled_test;
import 'send_event_test.dart' as send_event_test;
import 'send_timing_test.dart' as send_timing_test;
main() {
defineReflectiveSuite(() {
enable_test.main();
is_enabled_test.main();
send_event_test.main();
send_timing_test.main();
}, name: 'analytics');
}

View file

@ -49,3 +49,9 @@ server calls. This file is validated by `coverage_test.dart`.
- [x] server.getVersion
- [x] server.shutdown
- [x] server.setSubscriptions
## analytics domain
- [x] analytics.isEnabled
- [x] analytics.enable
- [x] analytics.sendEvent
- [x] analytics.sendTiming

View file

@ -1736,6 +1736,111 @@ abstract class IntegrationTestMixin {
decoder, 'result', result);
}
/**
* Query whether analytics is enabled.
*
* This flag controls whether the analysis server sends any analytics data to
* the cloud. If disabled, the analysis server does not send any analytics
* data, and any data sent to it by clients (from sendEvent and sendTiming)
* will be ignored.
*
* The value of this flag can be changed by other tools outside of the
* analysis server's process. When you query the flag, you get the value of
* the flag at a given moment. Clients should not use the value returned to
* decide whether or not to send the sendEvent and sendTiming requests. Those
* requests should be used unconditionally and server will determine whether
* or not it is appropriate to forward the information to the cloud at the
* time each request is received.
*
* Returns
*
* enabled: bool
*
* Whether sending analytics is enabled or not.
*/
Future<AnalyticsIsEnabledResult> sendAnalyticsIsEnabled() async {
var result = await server.send("analytics.isEnabled", null);
ResponseDecoder decoder = new ResponseDecoder(null);
return new AnalyticsIsEnabledResult.fromJson(decoder, 'result', result);
}
/**
* Enable or disable the sending of analytics data. Note that there are other
* ways for users to change this setting, so clients cannot assume that they
* have complete control over this setting. In particular, there is no
* guarantee that the result returned by the isEnabled request will match the
* last value set via this request.
*
* Parameters
*
* value: bool
*
* Enable or disable analytics.
*/
Future sendAnalyticsEnable(bool value) async {
var params = new AnalyticsEnableParams(value).toJson();
var result = await server.send("analytics.enable", params);
outOfTestExpect(result, isNull);
return null;
}
/**
* Send information about client events.
*
* Ask the analysis server to include the fact that an action was performed
* in the client as part of the analytics data being sent. The data will only
* be included if the sending of analytics data is enabled at the time the
* request is processed. The action that was performed is indicated by the
* value of the action field.
*
* The value of the action field should not include the identity of the
* client. The analytics data sent by server will include the client id
* passed in using the --client-id command-line argument. The request will be
* ignored if the client id was not provided when server was started.
*
* Parameters
*
* action: String
*
* The value used to indicate which action was performed.
*/
Future sendAnalyticsSendEvent(String action) async {
var params = new AnalyticsSendEventParams(action).toJson();
var result = await server.send("analytics.sendEvent", params);
outOfTestExpect(result, isNull);
return null;
}
/**
* Send timing information for client events (e.g. code completions).
*
* Ask the analysis server to include the fact that a timed event occurred as
* part of the analytics data being sent. The data will only be included if
* the sending of analytics data is enabled at the time the request is
* processed.
*
* The value of the event field should not include the identity of the
* client. The analytics data sent by server will include the client id
* passed in using the --client-id command-line argument. The request will be
* ignored if the client id was not provided when server was started.
*
* Parameters
*
* event: String
*
* The name of the event.
*
* millis: int
*
* The duration of the event in milliseconds.
*/
Future sendAnalyticsSendTiming(String event, int millis) async {
var params = new AnalyticsSendTimingParams(event, millis).toJson();
var result = await server.send("analytics.sendTiming", params);
outOfTestExpect(result, isNull);
return null;
}
/**
* Initialize the fields in InttestMixin, and ensure that notifications will
* be handled.

View file

@ -1561,6 +1561,68 @@ final Matcher isAnalysisUpdateOptionsParams = new LazyMatcher(() =>
*/
final Matcher isAnalysisUpdateOptionsResult = isNull;
/**
* analytics.enable params
*
* {
* "value": bool
* }
*/
final Matcher isAnalyticsEnableParams = new LazyMatcher(
() => new MatchesJsonObject("analytics.enable params", {"value": isBool}));
/**
* analytics.enable result
*/
final Matcher isAnalyticsEnableResult = isNull;
/**
* analytics.isEnabled params
*/
final Matcher isAnalyticsIsEnabledParams = isNull;
/**
* analytics.isEnabled result
*
* {
* "enabled": bool
* }
*/
final Matcher isAnalyticsIsEnabledResult = new LazyMatcher(() =>
new MatchesJsonObject("analytics.isEnabled result", {"enabled": isBool}));
/**
* analytics.sendEvent params
*
* {
* "action": String
* }
*/
final Matcher isAnalyticsSendEventParams = new LazyMatcher(() =>
new MatchesJsonObject("analytics.sendEvent params", {"action": isString}));
/**
* analytics.sendEvent result
*/
final Matcher isAnalyticsSendEventResult = isNull;
/**
* analytics.sendTiming params
*
* {
* "event": String
* "millis": int
* }
*/
final Matcher isAnalyticsSendTimingParams = new LazyMatcher(() =>
new MatchesJsonObject(
"analytics.sendTiming params", {"event": isString, "millis": isInt}));
/**
* analytics.sendTiming result
*/
final Matcher isAnalyticsSendTimingResult = isNull;
/**
* completion.getSuggestions params
*

View file

@ -5,6 +5,7 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'analysis/test_all.dart' as analysis_test_all;
import 'analytics//test_all.dart' as analytics_test_all;
import 'completion/test_all.dart' as completion_test_all;
import 'coverage_test.dart' as coverage_test;
import 'diagnostic/test_all.dart' as diagnostic_test_all;
@ -19,6 +20,7 @@ import 'server/test_all.dart' as server_test_all;
main() {
defineReflectiveSuite(() {
analysis_test_all.main();
analytics_test_all.main();
completion_test_all.main();
diagnostic_test_all.main();
edit_test_all.main();

View file

@ -284,6 +284,71 @@ public interface AnalysisServer {
*/
public void analysis_updateOptions(AnalysisOptions options);
/**
* {@code analytics.enable}
*
* Enable or disable the sending of analytics data. Note that there are other ways for users to
* change this setting, so clients cannot assume that they have complete control over this setting.
* In particular, there is no guarantee that the result returned by the isEnabled request will
* match the last value set via this request.
*
* @param value Enable or disable analytics.
*/
public void analytics_enable(boolean value);
/**
* {@code analytics.isEnabled}
*
* Query whether analytics is enabled.
*
* This flag controls whether the analysis server sends any analytics data to the cloud. If
* disabled, the analysis server does not send any analytics data, and any data sent to it by
* clients (from sendEvent and sendTiming) will be ignored.
*
* The value of this flag can be changed by other tools outside of the analysis server's process.
* When you query the flag, you get the value of the flag at a given moment. Clients should not use
* the value returned to decide whether or not to send the sendEvent and sendTiming requests. Those
* requests should be used unconditionally and server will determine whether or not it is
* appropriate to forward the information to the cloud at the time each request is received.
*/
public void analytics_isEnabled(IsEnabledConsumer consumer);
/**
* {@code analytics.sendEvent}
*
* Send information about client events.
*
* Ask the analysis server to include the fact that an action was performed in the client as part
* of the analytics data being sent. The data will only be included if the sending of analytics
* data is enabled at the time the request is processed. The action that was performed is indicated
* by the value of the action field.
*
* The value of the action field should not include the identity of the client. The analytics data
* sent by server will include the client id passed in using the --client-id command-line argument.
* The request will be ignored if the client id was not provided when server was started.
*
* @param action The value used to indicate which action was performed.
*/
public void analytics_sendEvent(String action);
/**
* {@code analytics.sendTiming}
*
* Send timing information for client events (e.g. code completions).
*
* Ask the analysis server to include the fact that a timed event occurred as part of the analytics
* data being sent. The data will only be included if the sending of analytics data is enabled at
* the time the request is processed.
*
* The value of the event field should not include the identity of the client. The analytics data
* sent by server will include the client id passed in using the --client-id command-line argument.
* The request will be ignored if the client id was not provided when server was started.
*
* @param event The name of the event.
* @param millis The duration of the event in milliseconds.
*/
public void analytics_sendTiming(String event, int millis);
/**
* {@code completion.getSuggestions}
*

View file

@ -2212,6 +2212,118 @@
</result>
</request>
</domain>
<domain name="analytics" experimental="true">
<p>
The analytics domain contains APIs related to reporting analytics.
</p>
<p>
This API allows clients to expose a UI option to enable and disable the
analysis server's reporting of analytics. This value is shared with other
tools and can change outside of this API; because of this, clients should
use the analysis server's flag as the system of record. Clients can choose
to send in additional analytics (see <tt>sendEvent</tt> and
<tt>sendTiming</tt>) if they so choose. Dart command-line tools provide a
disclaimer similar to:
<tt>
Dart SDK tools anonymously report feature usage statistics and basic crash
reports to help improve Dart tools over time. See Google's privacy policy:
https://www.google.com/intl/en/policies/privacy/.
</tt>
</p>
<p>
The analysis server will send it's own analytics data (for example, operations
performed, operating system type, SDK version). No data (from the analysis
server or from clients) will be sent if analytics is disabled.
</p>
<request method="isEnabled">
<p>Query whether analytics is enabled.</p>
<p>
This flag controls whether the analysis server sends any analytics data to
the cloud. If disabled, the analysis server does not send any analytics
data, and any data sent to it by clients (from <tt>sendEvent</tt> and
<tt>sendTiming</tt>) will be ignored.
</p>
<p>
The value of this flag can be changed by other tools outside of the
analysis server's process. When you query the flag, you get the value of
the flag at a given moment. Clients should not use the value returned to
decide whether or not to send the <tt>sendEvent</tt> and <tt>sendTiming</tt>
requests. Those requests should be used unconditionally and server will
determine whether or not it is appropriate to forward the information to
the cloud at the time each request is received.
</p>
<result>
<field name="enabled">
<ref>bool</ref>
<p>Whether sending analytics is enabled or not.</p>
</field>
</result>
</request>
<request method="enable">
<p>
Enable or disable the sending of analytics data. Note that there are other
ways for users to change this setting, so clients cannot assume that they
have complete control over this setting. In particular, there is no
guarantee that the result returned by the <tt>isEnabled</tt> request will
match the last value set via this request.
</p>
<params>
<field name="value">
<ref>bool</ref>
<p>Enable or disable analytics.</p>
</field>
</params>
</request>
<request method="sendEvent">
<p>Send information about client events.</p>
<p>
Ask the analysis server to include the fact that an action was performed
in the client as part of the analytics data being sent. The data will only
be included if the sending of analytics data is enabled at the time the
request is processed. The action that was performed is indicated by the
value of the <tt>action</tt> field.
</p>
<p>
The value of the action field should not include the identity of the
client. The analytics data sent by server will include the client id
passed in using the <tt>--client-id</tt> command-line argument. The
request will be ignored if the client id was not provided when server was
started.
</p>
<params>
<field name="action">
<ref>String</ref>
<p>The value used to indicate which action was performed.</p>
</field>
</params>
</request>
<request method="sendTiming">
<p>Send timing information for client events (e.g. code completions).</p>
<p>
Ask the analysis server to include the fact that a timed event occurred as
part of the analytics data being sent. The data will only be included if
the sending of analytics data is enabled at the time the request is
processed.
</p>
<p>
The value of the event field should not include the identity of the
client. The analytics data sent by server will include the client id
passed in using the <tt>--client-id</tt> command-line argument. The
request will be ignored if the client id was not provided when server was
started.
</p>
<params>
<field name="event">
<ref>String</ref>
<p>The name of the event.</p>
</field>
<field name="millis">
<ref>int</ref>
<p>The duration of the event in milliseconds.</p>
</field>
</params>
</request>
</domain>
<types>
<h2 class="domain"><a name="types">Types</a></h2>
<p>