From 66ada54280ee41a654c72809e1ad3fd1e401f780 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 22 Apr 2019 15:02:52 -0700 Subject: [PATCH 01/40] Java side of FirebasePerformance rewrite --- .../FirebasePerformancePlugin.java | 154 +----------------- .../FlutterFirebasePerformance.java | 62 +++++++ .../FlutterHttpMetric.java | 113 +++++++++++++ .../firebaseperformance/FlutterTrace.java | 134 +++++++++++++++ 4 files changed, 313 insertions(+), 150 deletions(-) create mode 100644 packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java create mode 100644 packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java create mode 100644 packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FirebasePerformancePlugin.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FirebasePerformancePlugin.java index cd8d4960fd16..ad115a499d2f 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FirebasePerformancePlugin.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FirebasePerformancePlugin.java @@ -4,161 +4,15 @@ package io.flutter.plugins.firebaseperformance; -import android.util.SparseArray; -import com.google.firebase.perf.FirebasePerformance; -import com.google.firebase.perf.metrics.HttpMetric; -import com.google.firebase.perf.metrics.Trace; -import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.MethodChannel.MethodCallHandler; -import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.PluginRegistry.Registrar; -import java.util.Map; /** FirebasePerformancePlugin */ -public class FirebasePerformancePlugin implements MethodCallHandler { - private FirebasePerformance firebasePerformance; - - private final SparseArray traces = new SparseArray<>(); - private final SparseArray httpMetrics = new SparseArray<>(); +public class FirebasePerformancePlugin { + private static final String CHANNEL_NAME = "plugins.flutter.io/firebase_performance"; public static void registerWith(Registrar registrar) { - final MethodChannel channel = - new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_performance"); - channel.setMethodCallHandler(new FirebasePerformancePlugin()); - } - - private FirebasePerformancePlugin() { - firebasePerformance = FirebasePerformance.getInstance(); - } - - @Override - public void onMethodCall(MethodCall call, Result result) { - switch (call.method) { - case "FirebasePerformance#isPerformanceCollectionEnabled": - result.success(firebasePerformance.isPerformanceCollectionEnabled()); - break; - case "FirebasePerformance#setPerformanceCollectionEnabled": - final boolean enabled = (boolean) call.arguments; - firebasePerformance.setPerformanceCollectionEnabled(enabled); - result.success(null); - break; - case "Trace#start": - handleTraceStart(call, result); - break; - case "Trace#stop": - handleTraceStop(call, result); - break; - case "HttpMetric#start": - handleHttpMetricStart(call, result); - break; - case "HttpMetric#stop": - handleHttpMetricStop(call, result); - break; - default: - result.notImplemented(); - } - } - - private void handleTraceStart(MethodCall call, Result result) { - Integer handle = call.argument("handle"); - String name = call.argument("name"); - - Trace trace = firebasePerformance.newTrace(name); - - traces.put(handle, trace); - - trace.start(); - result.success(null); - } - - private void handleTraceStop(MethodCall call, Result result) { - Integer handle = call.argument("handle"); - Trace trace = traces.get(handle); - - Map counters = call.argument("counters"); - for (Map.Entry entry : counters.entrySet()) { - trace.incrementCounter(entry.getKey(), entry.getValue()); - } - - Map attributes = call.argument("attributes"); - for (Map.Entry entry : attributes.entrySet()) { - trace.putAttribute(entry.getKey(), entry.getValue()); - } - - trace.stop(); - traces.remove(handle); - result.success(null); - } - - private void handleHttpMetricStart(MethodCall call, Result result) { - Integer handle = call.argument("handle"); - String url = call.argument("url"); - - int httpMethod = call.argument("httpMethod"); - String httpMethodStr; - switch (httpMethod) { - case 0: - httpMethodStr = FirebasePerformance.HttpMethod.CONNECT; - break; - case 1: - httpMethodStr = FirebasePerformance.HttpMethod.DELETE; - break; - case 2: - httpMethodStr = FirebasePerformance.HttpMethod.GET; - break; - case 3: - httpMethodStr = FirebasePerformance.HttpMethod.HEAD; - break; - case 4: - httpMethodStr = FirebasePerformance.HttpMethod.OPTIONS; - break; - case 5: - httpMethodStr = FirebasePerformance.HttpMethod.PATCH; - break; - case 6: - httpMethodStr = FirebasePerformance.HttpMethod.POST; - break; - case 7: - httpMethodStr = FirebasePerformance.HttpMethod.PUT; - break; - case 8: - httpMethodStr = FirebasePerformance.HttpMethod.TRACE; - break; - default: - httpMethodStr = null; - break; - } - - HttpMetric metric = firebasePerformance.newHttpMetric(url, httpMethodStr); - - httpMetrics.put(handle, metric); - - metric.start(); - result.success(null); - } - - private void handleHttpMetricStop(MethodCall call, Result result) { - Integer handle = call.argument("handle"); - HttpMetric metric = httpMetrics.get(handle); - - Integer httpResponseCode = call.argument("httpResponseCode"); - Number requestPayloadSize = call.argument("requestPayloadSize"); - String responseContentType = call.argument("responseContentType"); - Number responsePayloadSize = call.argument("responsePayloadSize"); - - if (requestPayloadSize != null) metric.setRequestPayloadSize(requestPayloadSize.longValue()); - if (httpResponseCode != null) metric.setHttpResponseCode(httpResponseCode); - if (responseContentType != null) metric.setResponseContentType(responseContentType); - if (responsePayloadSize != null) metric.setResponsePayloadSize(responsePayloadSize.longValue()); - - Map attributes = call.argument("attributes"); - for (Map.Entry entry : attributes.entrySet()) { - metric.putAttribute(entry.getKey(), entry.getValue()); - } - - metric.stop(); - httpMetrics.remove(handle); - result.success(null); + final MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL_NAME); + channel.setMethodCallHandler(FlutterFirebasePerformance.getInstance(registrar.messenger())); } } diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java new file mode 100644 index 000000000000..bc3da7ea53f9 --- /dev/null +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java @@ -0,0 +1,62 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.firebaseperformance; + +import com.google.firebase.perf.FirebasePerformance; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; + +public class FlutterFirebasePerformance implements MethodChannel.MethodCallHandler { + private final BinaryMessenger binaryMessenger; + private final FirebasePerformance performance; + + static FlutterFirebasePerformance getInstance(BinaryMessenger messenger) { + return new FlutterFirebasePerformance(messenger); + } + + private FlutterFirebasePerformance(BinaryMessenger messenger) { + this.binaryMessenger = messenger; + this.performance = FirebasePerformance.getInstance(); + } + + @Override + public void onMethodCall(MethodCall call, MethodChannel.Result result) { + switch (call.method) { + case "FirebasePerformance#isPerformanceCollectionEnabled": + isPerformanceCollectionEnabled(result); + break; + case "FirebasePerformance#setPerformanceCollectionEnabled": + setPerformanceCollectionEnabled(call.arguments, result); + break; + case "FirebasePerformance#newTrace": + newTrace(call.arguments, result); + break; + case "FirebasePerformance#newHttpMetric": + newHttpMetric(call.arguments, result); + break; + default: + result.notImplemented(); + } + } + + private void isPerformanceCollectionEnabled(MethodChannel.Result result) { + result.success(performance.isPerformanceCollectionEnabled()); + } + + private void setPerformanceCollectionEnabled(Object arguments, MethodChannel.Result result) { + final boolean enabled = (Boolean) arguments; + performance.setPerformanceCollectionEnabled(enabled); + result.success(null); + } + + private void newTrace(Object arguments, MethodChannel.Result result) { + new FlutterTrace(performance, binaryMessenger, arguments, result); + } + + private void newHttpMetric(Object arguments, MethodChannel.Result result) { + new FlutterHttpMetric(performance, binaryMessenger, arguments, result); + } +} diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java new file mode 100644 index 000000000000..1d2e8a3729af --- /dev/null +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java @@ -0,0 +1,113 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.firebaseperformance; + +import com.google.firebase.perf.FirebasePerformance; +import com.google.firebase.perf.metrics.HttpMetric; +import java.util.Map; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; + +public class FlutterHttpMetric implements MethodChannel.MethodCallHandler { + private final HttpMetric httpMetric; + + FlutterHttpMetric( + FirebasePerformance performance, + BinaryMessenger messenger, + Object arguments, + MethodChannel.Result result) { + @SuppressWarnings("unchecked") + final Map args = (Map) arguments; + + final String channelName = (String) args.get("channelName"); + final String url = (String) args.get("url"); + final String httpMethod = (String) args.get("httpMethod"); + + this.httpMetric = performance.newHttpMetric(url, httpMethod); + + final MethodChannel channel = new MethodChannel(messenger, channelName); + channel.setMethodCallHandler(this); + + result.success(null); + } + + @Override + public void onMethodCall(MethodCall call, MethodChannel.Result result) { + switch (call.method) { + case "HttpMetric#start": + start(result); + break; + case "HttpMetric#stop": + stop(call.arguments, result); + break; + case "PerformanceAttributes#putAttribute": + putAttribute(call.arguments, result); + break; + case "PerformanceAttributes#removeAttribute": + removeAttribute(call.arguments, result); + break; + case "PerformanceAttributes#getAttributes": + getAttributes(result); + break; + default: + result.notImplemented(); + } + } + + private void start(MethodChannel.Result result) { + httpMetric.start(); + result.success(null); + } + + private void stop(Object arguments, MethodChannel.Result result) { + @SuppressWarnings("unchecked") + final Map args = (Map) arguments; + + final Integer httpResponseCode = (Integer) args.get("httpResponseCode"); + final Number requestPayloadSize = (Number) args.get("requestPayloadSize"); + final String responseContentType = (String) args.get("responseContentType"); + final Number responsePayloadSize = (Number) args.get("responsePayloadSize"); + + if (requestPayloadSize != null) { + httpMetric.setRequestPayloadSize(requestPayloadSize.longValue()); + } + if (responsePayloadSize != null) { + httpMetric.setResponsePayloadSize(responsePayloadSize.longValue()); + } + + if (httpResponseCode != null) httpMetric.setHttpResponseCode(httpResponseCode); + if (responseContentType != null) httpMetric.setResponseContentType(responseContentType); + + httpMetric.stop(); + result.success(null); + } + + private void putAttribute(Object arguments, MethodChannel.Result result) { + @SuppressWarnings("unchecked") + final Map args = (Map) arguments; + + final String attribute = (String) args.get("attribute"); + final String value = (String) args.get("value"); + + httpMetric.putAttribute(attribute, value); + + result.success(null); + } + + private void removeAttribute(Object arguments, MethodChannel.Result result) { + @SuppressWarnings("unchecked") + final Map args = (Map) arguments; + + final String attribute = (String) args.get("attribute"); + httpMetric.removeAttribute(attribute); + + result.success(null); + } + + private void getAttributes(MethodChannel.Result result) { + result.success(httpMetric.getAttributes()); + } +} diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java new file mode 100644 index 000000000000..3ccbfdd07b14 --- /dev/null +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java @@ -0,0 +1,134 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.firebaseperformance; + +import com.google.firebase.perf.FirebasePerformance; +import com.google.firebase.perf.metrics.Trace; +import java.util.Map; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; + +public class FlutterTrace implements MethodChannel.MethodCallHandler { + private final Trace trace; + + FlutterTrace( + FirebasePerformance performance, + BinaryMessenger messenger, + Object arguments, + MethodChannel.Result result) { + @SuppressWarnings("unchecked") + final Map args = (Map) arguments; + + final String traceName = (String) args.get("traceName"); + final String channelName = (String) args.get("channelName"); + + this.trace = performance.newTrace(traceName); + + final MethodChannel channel = new MethodChannel(messenger, channelName); + channel.setMethodCallHandler(this); + + result.success(null); + } + + @Override + public void onMethodCall(MethodCall call, MethodChannel.Result result) { + switch (call.method) { + case "Trace#start": + start(result); + break; + case "Trace#stop": + stop(result); + break; + case "Trace#putMetric": + putMetric(call.arguments, result); + break; + case "Trace#incrementMetric": + incrementMetric(call.arguments, result); + break; + case "Trace#getMetric": + getMetric(call.arguments, result); + break; + case "PerformanceAttributes#putAttribute": + putAttribute(call.arguments, result); + break; + case "PerformanceAttributes#removeAttribute": + removeAttribute(call.arguments, result); + break; + case "PerformanceAttributes#getAttributes": + getAttributes(result); + break; + default: + result.notImplemented(); + } + } + + private void start(MethodChannel.Result result) { + trace.start(); + result.success(null); + } + + private void stop(MethodChannel.Result result) { + trace.stop(); + result.success(null); + } + + private void putMetric(Object arguments, MethodChannel.Result result) { + @SuppressWarnings("unchecked") + final Map args = (Map) arguments; + + final String name = (String) args.get("name"); + final Number value = (Number) args.get("value"); + trace.putMetric(name, value.longValue()); + + result.success(null); + } + + private void incrementMetric(Object arguments, MethodChannel.Result result) { + @SuppressWarnings("unchecked") + final Map args = (Map) arguments; + + final String name = (String) args.get("name"); + final Number value = (Number) args.get("value"); + trace.incrementMetric(name, value.longValue()); + + result.success(null); + } + + private void getMetric(Object arguments, MethodChannel.Result result) { + @SuppressWarnings("unchecked") + final Map args = (Map) arguments; + + final String name = (String) args.get("name"); + + result.success(trace.getLongMetric(name)); + } + + private void putAttribute(Object arguments, MethodChannel.Result result) { + @SuppressWarnings("unchecked") + final Map args = (Map) arguments; + + final String attribute = (String) args.get("attribute"); + final String value = (String) args.get("value"); + + trace.putAttribute(attribute, value); + + result.success(null); + } + + private void removeAttribute(Object arguments, MethodChannel.Result result) { + @SuppressWarnings("unchecked") + final Map args = (Map) arguments; + + final String attribute = (String) args.get("attribute"); + trace.removeAttribute(attribute); + + result.success(null); + } + + private void getAttributes(MethodChannel.Result result) { + result.success(trace.getAttributes()); + } +} From 784ebc178e06a7f6c7fc2930c744eec0fd2634c1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 22 Apr 2019 15:07:28 -0700 Subject: [PATCH 02/40] Performance rewrite dart side --- .../example/lib/main.dart | 2 +- .../lib/firebase_performance.dart | 1 - .../lib/src/firebase_performance.dart | 62 ++++----- .../lib/src/http_metric.dart | 71 ++--------- .../lib/src/performance_attributes.dart | 39 +++--- .../firebase_performance/lib/src/trace.dart | 118 ++++++------------ 6 files changed, 103 insertions(+), 190 deletions(-) diff --git a/packages/firebase_performance/example/lib/main.dart b/packages/firebase_performance/example/lib/main.dart index b9c46614748b..d81e951faaf0 100644 --- a/packages/firebase_performance/example/lib/main.dart +++ b/packages/firebase_performance/example/lib/main.dart @@ -77,7 +77,7 @@ class _MyAppState extends State { }); final Trace trace = _performance.newTrace("test"); - trace.incrementCounter("counter1", 16); + trace.putMetric("counter1", 16); trace.putAttribute("favorite_color", "blue"); await trace.start(); diff --git a/packages/firebase_performance/lib/firebase_performance.dart b/packages/firebase_performance/lib/firebase_performance.dart index 17dbcfc07863..8f8a2e7a4348 100644 --- a/packages/firebase_performance/lib/firebase_performance.dart +++ b/packages/firebase_performance/lib/firebase_performance.dart @@ -5,7 +5,6 @@ library firebase_performance; import 'dart:async'; -import 'dart:collection'; import 'package:flutter/services.dart'; import 'package:flutter/foundation.dart'; diff --git a/packages/firebase_performance/lib/src/firebase_performance.dart b/packages/firebase_performance/lib/src/firebase_performance.dart index 381236d44dc7..165ed0851f87 100644 --- a/packages/firebase_performance/lib/src/firebase_performance.dart +++ b/packages/firebase_performance/lib/src/firebase_performance.dart @@ -13,9 +13,6 @@ enum HttpMethod { Connect, Delete, Get, Head, Options, Patch, Post, Put, Trace } class FirebasePerformance { FirebasePerformance._(); - static int _traceCount = 0; - static int _httpMetricCount = 0; - @visibleForTesting static const MethodChannel channel = MethodChannel('plugins.flutter.io/firebase_performance'); @@ -23,30 +20,28 @@ class FirebasePerformance { /// Singleton of [FirebasePerformance]. static final FirebasePerformance instance = FirebasePerformance._(); + static int _channelCount = 0; + /// Determines whether performance monitoring is enabled or disabled. /// /// True if performance monitoring is enabled and false if performance /// monitoring is disabled. This is for dynamic enable/disable state. This /// does not reflect whether instrumentation is enabled/disabled. - Future isPerformanceCollectionEnabled() async { - final bool isEnabled = await channel - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - .invokeMethod('FirebasePerformance#isPerformanceCollectionEnabled'); - return isEnabled; + Future isPerformanceCollectionEnabled() { + return channel.invokeMethod( + 'FirebasePerformance#isPerformanceCollectionEnabled', + ); } - /// Enables or disables performance monitoring. + /// Enables or disables performance monitoring asynchronously. /// /// This setting is persisted and applied on future invocations of your /// application. By default, performance monitoring is enabled. Future setPerformanceCollectionEnabled(bool enable) async { - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - await channel.invokeMethod( - 'FirebasePerformance#setPerformanceCollectionEnabled', enable); + return channel.invokeMethod( + 'FirebasePerformance#setPerformanceCollectionEnabled', + enable, + ); } /// Creates a [Trace] object with given [name]. @@ -55,22 +50,33 @@ class FirebasePerformance { /// underscore _ character, max length of [Trace.maxTraceNameLength] /// characters. Trace newTrace(String name) { - return Trace._(_traceCount++, name); + final String channelName = + '${FirebasePerformance.channel.name}/$Trace/${_channelCount++}'; + + FirebasePerformance.channel.invokeMethod( + '$FirebasePerformance#newTrace', + {'channelName': channelName, 'traceName': name}, + ); + + final MethodChannel channel = MethodChannel(channelName); + return Trace._(channel); } /// Creates [HttpMetric] for collecting performance for one request/response. HttpMetric newHttpMetric(String url, HttpMethod httpMethod) { - return HttpMetric._(_httpMetricCount++, url, httpMethod); - } + final String channelName = + '${FirebasePerformance.channel.name}/$HttpMetric/${_channelCount++}'; - /// Creates a [Trace] object with given [name] and start the trace. - /// - /// The [name] requires no leading or trailing whitespace, no leading - /// underscore _ character, max length of [Trace.maxTraceNameLength] - /// characters. - static Future startTrace(String name) async { - final Trace trace = instance.newTrace(name); - await trace.start(); - return trace; + FirebasePerformance.channel.invokeMethod( + '$FirebasePerformance#newHttpMetric', + { + 'channelName': channelName, + 'url': url, + 'httpMethod': httpMethod.toString(), + }, + ); + + final MethodChannel channel = MethodChannel(channelName); + return HttpMetric._(channel); } } diff --git a/packages/firebase_performance/lib/src/http_metric.dart b/packages/firebase_performance/lib/src/http_metric.dart index a2e221b368e1..7ee889c21742 100644 --- a/packages/firebase_performance/lib/src/http_metric.dart +++ b/packages/firebase_performance/lib/src/http_metric.dart @@ -16,14 +16,9 @@ part of firebase_performance; /// You can confirm that Performance Monitoring results appear in the Firebase /// console. Results should appear within 12 hours. class HttpMetric extends PerformanceAttributes { - HttpMetric._(this._handle, this._url, this._httpMethod); + HttpMetric._(this._channel); - final int _handle; - final String _url; - final HttpMethod _httpMethod; - - bool _hasStarted = false; - bool _hasStopped = false; + final MethodChannel _channel; /// HttpResponse code of the request. int httpResponseCode; @@ -37,75 +32,33 @@ class HttpMetric extends PerformanceAttributes { /// Size of the response payload. int responsePayloadSize; - /// Starts this httpmetric. - /// - /// Can only be called once, otherwise assertion error is thrown. + @override + MethodChannel get _methodChannel => null; + + /// Starts this [HttpMetric] asynchronously. /// /// Using ```await``` with this method is only necessary when accurate timing /// is relevant. Future start() { - assert(!_hasStarted); - - _hasStarted = true; - return FirebasePerformance.channel - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - .invokeMethod('HttpMetric#start', { - 'handle': _handle, - 'url': _url, - 'httpMethod': _httpMethod.index, - }); + return _channel.invokeMethod('$Trace#start'); } /// Stops this httpMetric. /// - /// Can only be called once and only after start(), otherwise assertion error - /// is thrown. Data collected is automatically sent to the associated - /// Firebase console after stop() is called. + /// Can only be called once and only after start(), Data collected is + /// automatically sent to the associate Firebase console after stop() is + /// called. You can confirm that Performance Monitoring results appear in the + /// Firebase console. Results should appear within 12 hours. /// /// Not necessary to use ```await``` with this method. Future stop() { - assert(!_hasStopped); - assert(_hasStarted); - final Map data = { - 'handle': _handle, 'httpResponseCode': httpResponseCode, 'requestPayloadSize': requestPayloadSize, 'responseContentType': responseContentType, 'responsePayloadSize': responsePayloadSize, - 'attributes': _attributes, }; - _hasStopped = true; - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - return FirebasePerformance.channel.invokeMethod('HttpMetric#stop', data); - } - - /// Sets a String [value] for the specified [attribute]. - /// - /// If the httpmetric has been stopped, this method throws an assertion - /// error. - /// - /// See [PerformanceAttributes.putAttribute]. - @override - void putAttribute(String attribute, String value) { - assert(!_hasStopped); - super.putAttribute(attribute, value); - } - - /// Removes an already added [attribute]. - /// - /// If the httpmetric has been stopped, this method throws an assertion - /// error. - /// - /// See [PerformanceAttributes.removeAttribute]. - @override - void removeAttribute(String attribute) { - assert(!_hasStopped); - super.removeAttribute(attribute); + return _channel.invokeMethod('$Trace#stop', data); } } diff --git a/packages/firebase_performance/lib/src/performance_attributes.dart b/packages/firebase_performance/lib/src/performance_attributes.dart index 0543242fdeb2..87237e7cac34 100644 --- a/packages/firebase_performance/lib/src/performance_attributes.dart +++ b/packages/firebase_performance/lib/src/performance_attributes.dart @@ -4,10 +4,7 @@ part of firebase_performance; -/// Abstract class that allows adding/removing attributes to any object. -/// -/// Enforces constraints for adding attributes and values required by -/// FirebasePerformance API. See [putAttribute]. +/// Abstract class that allows adding/removing attributes to an object. abstract class PerformanceAttributes { /// Maximum allowed length of a key passed to [putAttribute]. static const int maxAttributeKeyLength = 40; @@ -18,10 +15,7 @@ abstract class PerformanceAttributes { /// Maximum allowed number of attributes that can be added. static const int maxCustomAttributes = 5; - final Map _attributes = {}; - - /// Copy of all the attributes added. - Map get attributes => Map.from(_attributes); + MethodChannel get _methodChannel; /// Sets a String [value] for the specified [attribute]. /// @@ -32,22 +26,25 @@ abstract class PerformanceAttributes { /// Name of the attribute has max length of [maxAttributeKeyLength] /// characters. Value of the attribute has max length of /// [maxAttributeValueLength] characters. - void putAttribute(String attribute, String value) { - assert(attribute != null); - assert(!attribute.startsWith(RegExp(r'[_\s]'))); - assert(!attribute.contains(RegExp(r'[_\s]$'))); - assert(attribute.length <= maxAttributeKeyLength); - assert(value.length <= maxAttributeValueLength); - assert(_attributes.length < maxCustomAttributes); - - _attributes[attribute] = value; + Future putAttribute(String attribute, String value) { + return _methodChannel.invokeMethod( + 'PerformanceAttributes#putAttribute', + {'attribute': attribute, 'value': value}, + ); } /// Removes an already added [attribute]. - void removeAttribute(String attribute) { - _attributes.remove(attribute); + Future removeAttribute(String attribute) { + return _methodChannel.invokeMethod( + 'PerformanceAttributes#putAttribute', + attribute, + ); } - /// Returns the value of an [attribute]. - String getAttribute(String attribute) => _attributes[attribute]; + /// All [attribute]s added. + Future> getAttributes() { + return _methodChannel.invokeMapMethod( + 'PerformanceAttributes#getAttributes', + ); + } } diff --git a/packages/firebase_performance/lib/src/trace.dart b/packages/firebase_performance/lib/src/trace.dart index 6ff6ab996ee9..3187115a26b3 100644 --- a/packages/firebase_performance/lib/src/trace.dart +++ b/packages/firebase_performance/lib/src/trace.dart @@ -19,111 +19,69 @@ part of firebase_performance; /// You can confirm that Performance Monitoring results appear in the Firebase /// console. Results should appear within 12 hours. class Trace extends PerformanceAttributes { - Trace._(this._handle, this._name) { - assert(_name != null); - assert(!_name.startsWith(RegExp(r'[_\s]'))); - assert(!_name.contains(RegExp(r'[_\s]$'))); - assert(_name.length <= maxTraceNameLength); - } + Trace._(this._channel); /// Maximum allowed length of the name of a [Trace]. static const int maxTraceNameLength = 100; - final int _handle; - final String _name; - - bool _hasStarted = false; - bool _hasStopped = false; + final MethodChannel _channel; - final HashMap _counters = HashMap(); + @override + MethodChannel get _methodChannel => _channel; - /// Starts this trace. + /// Starts this [Trace] asynchronously. /// - /// Can only be called once, otherwise assertion error is thrown. + /// Can only be called once. /// /// Using ```await``` with this method is only necessary when accurate timing /// is relevant. Future start() { - assert(!_hasStarted); - - _hasStarted = true; - return FirebasePerformance.channel - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - .invokeMethod('Trace#start', { - 'handle': _handle, - 'name': _name, - }); + return _channel.invokeMethod('$Trace#start'); } - /// Stops this trace. + /// Stops this [Trace] asynchronously. /// - /// Can only be called once and only after start(), otherwise assertion error - /// is thrown. Data collected is automatically sent to the associated Firebase - /// console after stop() is called. + /// Can only be called once and only after start() Data collected is + /// automatically sent to the associated Firebase console after stop() is + /// called. /// /// Not necessary to use ```await``` with this method. Future stop() { - assert(!_hasStopped); - assert(_hasStarted); - - final Map data = { - 'handle': _handle, - 'name': _name, - 'counters': _counters, - 'attributes': _attributes, - }; - - _hasStopped = true; - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - return FirebasePerformance.channel.invokeMethod('Trace#stop', data); + return _channel.invokeMethod('$Trace#stop'); } - /// Increments the counter with the given [name] by [incrementBy]. + /// Increments the metric with the given name asynchronously. /// - /// The counter is incremented by 1 if [incrementBy] was not passed. If a - /// counter does not already exist, a new one will be created. If the trace - /// has not been started or has already been stopped, an assertion error is - /// thrown. - /// - /// The name of the counter requires no leading or - /// trailing whitespace, no leading underscore _ character, and max length of - /// 32 characters. - void incrementCounter(String name, [int incrementBy = 1]) { - assert(!_hasStopped); - assert(name != null); - assert(!name.startsWith(RegExp(r'[_\s]'))); - assert(!name.contains(RegExp(r'[_\s]$'))); - assert(name.length <= 32); - - _counters.putIfAbsent(name, () => 0); - _counters[name] += incrementBy; + /// If the metric does not exist, a new one will be created. If the trace has + /// not been started or has already been stopped, returns immediately without + /// taking action. + Future incrementMetric(String name, int value) { + return _channel.invokeMethod( + '$Trace#incrementMetric', + {'name': name, 'value': value}, + ); } - /// Sets a String [value] for the specified [attribute]. - /// - /// If the trace has been stopped, this method throws an assertion - /// error. + /// Sets the value of the metric with the given name asynchronously. /// - /// See [PerformanceAttributes.putAttribute]. - @override - void putAttribute(String attribute, String value) { - assert(!_hasStopped); - super.putAttribute(attribute, value); + /// If a metric with the given name doesn't exist, a new one will be created. + /// If the trace has not been started or has already been stopped, returns + /// immediately without taking action. + Future putMetric(String name, int value) { + return _channel.invokeMethod( + '$Trace#putMetric', + {'name': name, 'value': value}, + ); } - /// Removes an already added [attribute]. - /// - /// If the trace has been stopped, this method throws an assertion - /// error. + /// Gets the value of the metric with the given name asynchronously. /// - /// See [PerformanceAttributes.removeAttribute]. - @override - void removeAttribute(String attribute) { - assert(!_hasStopped); - super.removeAttribute(attribute); + /// If a metric with the given name doesn't exist, it is NOT created and a 0 + /// is returned. + Future getMetric(String name) { + return _channel.invokeMethod( + '$Trace#getMetric', + {'name': name}, + ); } } From b3d698cfda941c9c1e5e9de427a24d07ac03ffb0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 22 Apr 2019 15:21:57 -0700 Subject: [PATCH 03/40] Undo changes --- packages/firebase_performance/lib/src/trace.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/firebase_performance/lib/src/trace.dart b/packages/firebase_performance/lib/src/trace.dart index 3187115a26b3..b4fc363bc1b6 100644 --- a/packages/firebase_performance/lib/src/trace.dart +++ b/packages/firebase_performance/lib/src/trace.dart @@ -9,7 +9,7 @@ part of firebase_performance; /// A trace is a report of performance data associated with some of the /// code in your app. You can have multiple custom traces, and it is /// possible to have more than one custom trace running at a time. Each custom -/// trace can have multiple counters and attributes added to help measure +/// trace can have multiple metrics and attributes added to help measure /// performance related events. A trace also measures the time between calling /// start() and stop(). /// @@ -74,7 +74,7 @@ class Trace extends PerformanceAttributes { ); } - /// Gets the value of the metric with the given name asynchronously. + /// Gets the value of the metric with the given name. /// /// If a metric with the given name doesn't exist, it is NOT created and a 0 /// is returned. From cfa200cd3de8d4541a6901c6231a93ef2917d961 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 22 Apr 2019 15:27:03 -0700 Subject: [PATCH 04/40] Formatting and suppressing warnings --- .../flutter/plugins/firebaseperformance/FlutterHttpMetric.java | 3 ++- .../io/flutter/plugins/firebaseperformance/FlutterTrace.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java index 1d2e8a3729af..9f6c41f67a54 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java @@ -6,11 +6,12 @@ import com.google.firebase.perf.FirebasePerformance; import com.google.firebase.perf.metrics.HttpMetric; -import java.util.Map; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; +import java.util.Map; +@SuppressWarnings("ConstantConditions") public class FlutterHttpMetric implements MethodChannel.MethodCallHandler { private final HttpMetric httpMetric; diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java index 3ccbfdd07b14..7488204e8d11 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java @@ -6,11 +6,12 @@ import com.google.firebase.perf.FirebasePerformance; import com.google.firebase.perf.metrics.Trace; -import java.util.Map; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; +import java.util.Map; +@SuppressWarnings("ConstantConditions") public class FlutterTrace implements MethodChannel.MethodCallHandler { private final Trace trace; From e3aa0e91b578590d34f5b496dc06665b53bbef6c Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 23 Apr 2019 12:00:56 -0700 Subject: [PATCH 05/40] Update metric take individual parameters --- .../FlutterFirebasePerformance.java | 20 ++--- .../FlutterHttpMetric.java | 85 ++++++++++--------- .../firebaseperformance/FlutterTrace.java | 63 +++++--------- 3 files changed, 79 insertions(+), 89 deletions(-) diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java index bc3da7ea53f9..9e66cf732f50 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -29,13 +29,13 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) { isPerformanceCollectionEnabled(result); break; case "FirebasePerformance#setPerformanceCollectionEnabled": - setPerformanceCollectionEnabled(call.arguments, result); + setPerformanceCollectionEnabled(call, result); break; case "FirebasePerformance#newTrace": - newTrace(call.arguments, result); + newTrace(call, result); break; case "FirebasePerformance#newHttpMetric": - newHttpMetric(call.arguments, result); + newHttpMetric(call, result); break; default: result.notImplemented(); @@ -46,17 +46,17 @@ private void isPerformanceCollectionEnabled(MethodChannel.Result result) { result.success(performance.isPerformanceCollectionEnabled()); } - private void setPerformanceCollectionEnabled(Object arguments, MethodChannel.Result result) { - final boolean enabled = (Boolean) arguments; + private void setPerformanceCollectionEnabled(MethodCall call, MethodChannel.Result result) { + final boolean enabled = (Boolean) call.arguments; performance.setPerformanceCollectionEnabled(enabled); result.success(null); } - private void newTrace(Object arguments, MethodChannel.Result result) { - new FlutterTrace(performance, binaryMessenger, arguments, result); + private void newTrace(MethodCall call, MethodChannel.Result result) { + new FlutterTrace(performance, binaryMessenger, call, result); } - private void newHttpMetric(Object arguments, MethodChannel.Result result) { - new FlutterHttpMetric(performance, binaryMessenger, arguments, result); + private void newHttpMetric(MethodCall call, MethodChannel.Result result) { + new FlutterHttpMetric(performance, binaryMessenger, call, result); } } diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java index 9f6c41f67a54..2ef6163bc620 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,7 +9,6 @@ import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; -import java.util.Map; @SuppressWarnings("ConstantConditions") public class FlutterHttpMetric implements MethodChannel.MethodCallHandler { @@ -18,14 +17,11 @@ public class FlutterHttpMetric implements MethodChannel.MethodCallHandler { FlutterHttpMetric( FirebasePerformance performance, BinaryMessenger messenger, - Object arguments, + MethodCall call, MethodChannel.Result result) { - @SuppressWarnings("unchecked") - final Map args = (Map) arguments; - - final String channelName = (String) args.get("channelName"); - final String url = (String) args.get("url"); - final String httpMethod = (String) args.get("httpMethod"); + final String channelName = call.argument("channelName"); + final String url = call.argument("url"); + final String httpMethod = call.argument("httpMethod"); this.httpMetric = performance.newHttpMetric(url, httpMethod); @@ -42,13 +38,25 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) { start(result); break; case "HttpMetric#stop": - stop(call.arguments, result); + stop(result); + break; + case "HttpMetric#httpResponseCode": + setHttpResponseCode(call, result); + break; + case "HttpMetric#requestPayloadSize": + setRequestPayloadSize(call, result); + break; + case "HttpMetric#responseContentType": + setResponseContentType(call, result); + break; + case "HttpMetric#responsePayloadSize": + setResponsePayloadSize(call, result); break; case "PerformanceAttributes#putAttribute": - putAttribute(call.arguments, result); + putAttribute(call, result); break; case "PerformanceAttributes#removeAttribute": - removeAttribute(call.arguments, result); + removeAttribute(call, result); break; case "PerformanceAttributes#getAttributes": getAttributes(result); @@ -63,46 +71,47 @@ private void start(MethodChannel.Result result) { result.success(null); } - private void stop(Object arguments, MethodChannel.Result result) { - @SuppressWarnings("unchecked") - final Map args = (Map) arguments; + private void stop(MethodChannel.Result result) { + httpMetric.stop(); + result.success(null); + } - final Integer httpResponseCode = (Integer) args.get("httpResponseCode"); - final Number requestPayloadSize = (Number) args.get("requestPayloadSize"); - final String responseContentType = (String) args.get("responseContentType"); - final Number responsePayloadSize = (Number) args.get("responsePayloadSize"); + private void setHttpResponseCode(MethodCall call, MethodChannel.Result result) { + final Integer httpResponseCode = call.argument("httpResponseCode"); + httpMetric.setHttpResponseCode(httpResponseCode); + result.success(null); + } - if (requestPayloadSize != null) { - httpMetric.setRequestPayloadSize(requestPayloadSize.longValue()); - } - if (responsePayloadSize != null) { - httpMetric.setResponsePayloadSize(responsePayloadSize.longValue()); - } + private void setRequestPayloadSize(MethodCall call, MethodChannel.Result result) { + final Number payloadSize = call.argument("requestPayloadSize"); + httpMetric.setRequestPayloadSize(payloadSize.longValue()); + result.success(null); + } - if (httpResponseCode != null) httpMetric.setHttpResponseCode(httpResponseCode); - if (responseContentType != null) httpMetric.setResponseContentType(responseContentType); + private void setResponseContentType(MethodCall call, MethodChannel.Result result) { + final String contentType = call.argument("responseContentType"); + httpMetric.setResponseContentType(contentType); + result.success(null); + } - httpMetric.stop(); + private void setResponsePayloadSize(MethodCall call, MethodChannel.Result result) { + final Number payloadSize = call.argument("responsePayloadSize"); + httpMetric.setResponsePayloadSize(payloadSize.longValue()); result.success(null); } - private void putAttribute(Object arguments, MethodChannel.Result result) { - @SuppressWarnings("unchecked") - final Map args = (Map) arguments; - final String attribute = (String) args.get("attribute"); - final String value = (String) args.get("value"); + private void putAttribute(MethodCall call, MethodChannel.Result result) { + final String attribute = call.argument("attribute"); + final String value = call.argument("value"); httpMetric.putAttribute(attribute, value); result.success(null); } - private void removeAttribute(Object arguments, MethodChannel.Result result) { - @SuppressWarnings("unchecked") - final Map args = (Map) arguments; - - final String attribute = (String) args.get("attribute"); + private void removeAttribute(MethodCall call, MethodChannel.Result result) { + final String attribute = call.argument("attribute"); httpMetric.removeAttribute(attribute); result.success(null); diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java index 7488204e8d11..566e99c5d179 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java @@ -1,4 +1,4 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,7 +9,6 @@ import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; -import java.util.Map; @SuppressWarnings("ConstantConditions") public class FlutterTrace implements MethodChannel.MethodCallHandler { @@ -18,13 +17,10 @@ public class FlutterTrace implements MethodChannel.MethodCallHandler { FlutterTrace( FirebasePerformance performance, BinaryMessenger messenger, - Object arguments, + MethodCall call, MethodChannel.Result result) { - @SuppressWarnings("unchecked") - final Map args = (Map) arguments; - - final String traceName = (String) args.get("traceName"); - final String channelName = (String) args.get("channelName"); + final String traceName = call.argument("traceName"); + final String channelName = call.argument("channelName"); this.trace = performance.newTrace(traceName); @@ -44,19 +40,19 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) { stop(result); break; case "Trace#putMetric": - putMetric(call.arguments, result); + putMetric(call, result); break; case "Trace#incrementMetric": - incrementMetric(call.arguments, result); + incrementMetric(call, result); break; case "Trace#getMetric": - getMetric(call.arguments, result); + getMetric(call, result); break; case "PerformanceAttributes#putAttribute": - putAttribute(call.arguments, result); + putAttribute(call, result); break; case "PerformanceAttributes#removeAttribute": - removeAttribute(call.arguments, result); + removeAttribute(call, result); break; case "PerformanceAttributes#getAttributes": getAttributes(result); @@ -76,54 +72,39 @@ private void stop(MethodChannel.Result result) { result.success(null); } - private void putMetric(Object arguments, MethodChannel.Result result) { - @SuppressWarnings("unchecked") - final Map args = (Map) arguments; - - final String name = (String) args.get("name"); - final Number value = (Number) args.get("value"); + private void putMetric(MethodCall call, MethodChannel.Result result) { + final String name = call.argument("name"); + final Number value = call.argument("value"); trace.putMetric(name, value.longValue()); result.success(null); } - private void incrementMetric(Object arguments, MethodChannel.Result result) { - @SuppressWarnings("unchecked") - final Map args = (Map) arguments; - - final String name = (String) args.get("name"); - final Number value = (Number) args.get("value"); + private void incrementMetric(MethodCall call, MethodChannel.Result result) { + final String name = call.argument("name"); + final Number value = call.argument("value"); trace.incrementMetric(name, value.longValue()); result.success(null); } - private void getMetric(Object arguments, MethodChannel.Result result) { - @SuppressWarnings("unchecked") - final Map args = (Map) arguments; - - final String name = (String) args.get("name"); + private void getMetric(MethodCall call, MethodChannel.Result result) { + final String name = call.argument("name"); result.success(trace.getLongMetric(name)); } - private void putAttribute(Object arguments, MethodChannel.Result result) { - @SuppressWarnings("unchecked") - final Map args = (Map) arguments; - - final String attribute = (String) args.get("attribute"); - final String value = (String) args.get("value"); + private void putAttribute(MethodCall call, MethodChannel.Result result) { + final String attribute = call.argument("attribute"); + final String value = call.argument("value"); trace.putAttribute(attribute, value); result.success(null); } - private void removeAttribute(Object arguments, MethodChannel.Result result) { - @SuppressWarnings("unchecked") - final Map args = (Map) arguments; - - final String attribute = (String) args.get("attribute"); + private void removeAttribute(MethodCall call, MethodChannel.Result result) { + final String attribute = call.argument("attribute"); trace.removeAttribute(attribute); result.success(null); From db5acb6432f29f2a88b8c48dbf06ac797f425858 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 23 Apr 2019 12:19:08 -0700 Subject: [PATCH 06/40] Update HttpMetric --- .../lib/src/firebase_performance.dart | 2 +- .../lib/src/http_metric.dart | 51 ++++++++++++------- .../lib/src/performance_attributes.dart | 6 +-- .../firebase_performance/lib/src/trace.dart | 5 +- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/packages/firebase_performance/lib/src/firebase_performance.dart b/packages/firebase_performance/lib/src/firebase_performance.dart index 165ed0851f87..f1640665ca64 100644 --- a/packages/firebase_performance/lib/src/firebase_performance.dart +++ b/packages/firebase_performance/lib/src/firebase_performance.dart @@ -47,7 +47,7 @@ class FirebasePerformance { /// Creates a [Trace] object with given [name]. /// /// The [name] requires no leading or trailing whitespace, no leading - /// underscore _ character, max length of [Trace.maxTraceNameLength] + /// underscore _ character, and max length of [Trace.maxTraceNameLength] /// characters. Trace newTrace(String name) { final String channelName = diff --git a/packages/firebase_performance/lib/src/http_metric.dart b/packages/firebase_performance/lib/src/http_metric.dart index 7ee889c21742..eb614139cd17 100644 --- a/packages/firebase_performance/lib/src/http_metric.dart +++ b/packages/firebase_performance/lib/src/http_metric.dart @@ -6,9 +6,9 @@ part of firebase_performance; /// Metric used to collect data for network requests/responses. /// -/// It is possible to have more than one httpmetric running at a time. +/// It is possible to have more than one [HttpMetric] running at a time. /// Attributes can also be added to help measure performance related events. A -/// httpmetric also measures the time between calling start() and stop(). +/// [HttpMetric] also measures the time between calling start() and stop(). /// /// Data collected is automatically sent to the associated Firebase console /// after stop() is called. @@ -20,30 +20,50 @@ class HttpMetric extends PerformanceAttributes { final MethodChannel _channel; + @override + MethodChannel get _methodChannel => _channel; + /// HttpResponse code of the request. - int httpResponseCode; + set httpResponseCode(int httpResponseCode) { + _channel.invokeMethod( + '$HttpMetric#httpResponseCode', + httpResponseCode, + ); + } /// Size of the request payload. - int requestPayloadSize; + set requestPayloadSize(int requestPayloadSize) { + _channel.invokeMethod( + '$HttpMetric#requestPayloadSize', + requestPayloadSize, + ); + } /// Content type of the response such as text/html, application/json, etc... - String responseContentType; + set responseContentType(String responseContentType) { + _channel.invokeMethod( + '$HttpMetric#responseContentType', + responseContentType, + ); + } /// Size of the response payload. - int responsePayloadSize; - - @override - MethodChannel get _methodChannel => null; + set responsePayloadSize(int responsePayloadSize) { + _channel.invokeMethod( + '$HttpMetric#responsePayloadSize', + responsePayloadSize, + ); + } /// Starts this [HttpMetric] asynchronously. /// /// Using ```await``` with this method is only necessary when accurate timing /// is relevant. Future start() { - return _channel.invokeMethod('$Trace#start'); + return _channel.invokeMethod('$HttpMetric#start'); } - /// Stops this httpMetric. + /// Stops this [HttpMetric]. /// /// Can only be called once and only after start(), Data collected is /// automatically sent to the associate Firebase console after stop() is @@ -52,13 +72,6 @@ class HttpMetric extends PerformanceAttributes { /// /// Not necessary to use ```await``` with this method. Future stop() { - final Map data = { - 'httpResponseCode': httpResponseCode, - 'requestPayloadSize': requestPayloadSize, - 'responseContentType': responseContentType, - 'responsePayloadSize': responsePayloadSize, - }; - - return _channel.invokeMethod('$Trace#stop', data); + return _channel.invokeMethod('$HttpMetric#stop'); } } diff --git a/packages/firebase_performance/lib/src/performance_attributes.dart b/packages/firebase_performance/lib/src/performance_attributes.dart index 87237e7cac34..b9247e73b1b0 100644 --- a/packages/firebase_performance/lib/src/performance_attributes.dart +++ b/packages/firebase_performance/lib/src/performance_attributes.dart @@ -28,7 +28,7 @@ abstract class PerformanceAttributes { /// [maxAttributeValueLength] characters. Future putAttribute(String attribute, String value) { return _methodChannel.invokeMethod( - 'PerformanceAttributes#putAttribute', + '$PerformanceAttributes#putAttribute', {'attribute': attribute, 'value': value}, ); } @@ -36,7 +36,7 @@ abstract class PerformanceAttributes { /// Removes an already added [attribute]. Future removeAttribute(String attribute) { return _methodChannel.invokeMethod( - 'PerformanceAttributes#putAttribute', + '$PerformanceAttributes#putAttribute', attribute, ); } @@ -44,7 +44,7 @@ abstract class PerformanceAttributes { /// All [attribute]s added. Future> getAttributes() { return _methodChannel.invokeMapMethod( - 'PerformanceAttributes#getAttributes', + '$PerformanceAttributes#getAttributes', ); } } diff --git a/packages/firebase_performance/lib/src/trace.dart b/packages/firebase_performance/lib/src/trace.dart index b4fc363bc1b6..5298ea5dde06 100644 --- a/packages/firebase_performance/lib/src/trace.dart +++ b/packages/firebase_performance/lib/src/trace.dart @@ -4,7 +4,7 @@ part of firebase_performance; -/// Trace allows you to set the beginning and end of a custom trace in your app. +/// [Trace] allows you to set the beginning and end of a custom trace in your app. /// /// A trace is a report of performance data associated with some of the /// code in your app. You can have multiple custom traces, and it is @@ -43,7 +43,8 @@ class Trace extends PerformanceAttributes { /// /// Can only be called once and only after start() Data collected is /// automatically sent to the associated Firebase console after stop() is - /// called. + /// called. You can confirm that Performance Monitoring results appear in the + /// Firebase console. Results should appear within 12 hours. /// /// Not necessary to use ```await``` with this method. Future stop() { From 588c7fb01a19b988cc5209f04486f5b4291d99c1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 23 Apr 2019 12:41:19 -0700 Subject: [PATCH 07/40] Unregister MethodCallHandler --- .../plugins/firebaseperformance/FlutterHttpMetric.java | 4 +++- .../io/flutter/plugins/firebaseperformance/FlutterTrace.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java index 2ef6163bc620..0a71239b89fc 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java @@ -13,6 +13,7 @@ @SuppressWarnings("ConstantConditions") public class FlutterHttpMetric implements MethodChannel.MethodCallHandler { private final HttpMetric httpMetric; + private final MethodChannel channel; FlutterHttpMetric( FirebasePerformance performance, @@ -25,7 +26,7 @@ public class FlutterHttpMetric implements MethodChannel.MethodCallHandler { this.httpMetric = performance.newHttpMetric(url, httpMethod); - final MethodChannel channel = new MethodChannel(messenger, channelName); + this.channel = new MethodChannel(messenger, channelName); channel.setMethodCallHandler(this); result.success(null); @@ -73,6 +74,7 @@ private void start(MethodChannel.Result result) { private void stop(MethodChannel.Result result) { httpMetric.stop(); + channel.setMethodCallHandler(null); result.success(null); } diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java index 566e99c5d179..9b3b4c8f58e2 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java @@ -13,6 +13,7 @@ @SuppressWarnings("ConstantConditions") public class FlutterTrace implements MethodChannel.MethodCallHandler { private final Trace trace; + private final MethodChannel channel; FlutterTrace( FirebasePerformance performance, @@ -24,7 +25,7 @@ public class FlutterTrace implements MethodChannel.MethodCallHandler { this.trace = performance.newTrace(traceName); - final MethodChannel channel = new MethodChannel(messenger, channelName); + this.channel = new MethodChannel(messenger, channelName); channel.setMethodCallHandler(this); result.success(null); @@ -69,6 +70,7 @@ private void start(MethodChannel.Result result) { private void stop(MethodChannel.Result result) { trace.stop(); + channel.setMethodCallHandler(null); result.success(null); } From 55d69991a55e53446d3352e9f76e78a5e2c6ac39 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 23 Apr 2019 12:52:06 -0700 Subject: [PATCH 08/40] Parse HttpMethod --- .../FlutterHttpMetric.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java index 0a71239b89fc..d3073f37b52f 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java @@ -12,6 +12,31 @@ @SuppressWarnings("ConstantConditions") public class FlutterHttpMetric implements MethodChannel.MethodCallHandler { + private static String parseHttpMethod(String httpMethod) { + switch (httpMethod) { + case "HttpMethod.Connect": + return FirebasePerformance.HttpMethod.CONNECT; + case "HttpMethod.Delete": + return FirebasePerformance.HttpMethod.DELETE; + case "HttpMethod.Get": + return FirebasePerformance.HttpMethod.GET; + case "HttpMethod.Head": + return FirebasePerformance.HttpMethod.HEAD; + case "HttpMethod.Options": + return FirebasePerformance.HttpMethod.OPTIONS; + case "HttpMethod.Patch": + return FirebasePerformance.HttpMethod.PATCH; + case "HttpMethod.Post": + return FirebasePerformance.HttpMethod.POST; + case "HttpMethod.Put": + return FirebasePerformance.HttpMethod.PUT; + case "HttpMethod.Trace": + return FirebasePerformance.HttpMethod.TRACE; + default: + throw new IllegalArgumentException(String.format("No HttpMethod for: %s", httpMethod)); + } + } + private final HttpMetric httpMetric; private final MethodChannel channel; @@ -24,7 +49,7 @@ public class FlutterHttpMetric implements MethodChannel.MethodCallHandler { final String url = call.argument("url"); final String httpMethod = call.argument("httpMethod"); - this.httpMetric = performance.newHttpMetric(url, httpMethod); + this.httpMetric = performance.newHttpMetric(url, parseHttpMethod(httpMethod)); this.channel = new MethodChannel(messenger, channelName); channel.setMethodCallHandler(this); From 236da2c737cb5e903c2dfb1780fe557c7f44c623 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 23 Apr 2019 13:37:14 -0700 Subject: [PATCH 09/40] Fix MethodChannel Unit tests --- .../lib/src/http_metric.dart | 19 +- .../lib/src/performance_attributes.dart | 11 +- .../firebase_performance/lib/src/trace.dart | 17 +- .../test/firebase_performance_test.dart | 359 +++++++----------- 4 files changed, 165 insertions(+), 241 deletions(-) diff --git a/packages/firebase_performance/lib/src/http_metric.dart b/packages/firebase_performance/lib/src/http_metric.dart index eb614139cd17..aeabb8024c95 100644 --- a/packages/firebase_performance/lib/src/http_metric.dart +++ b/packages/firebase_performance/lib/src/http_metric.dart @@ -16,16 +16,17 @@ part of firebase_performance; /// You can confirm that Performance Monitoring results appear in the Firebase /// console. Results should appear within 12 hours. class HttpMetric extends PerformanceAttributes { - HttpMetric._(this._channel); + HttpMetric._(this.channel); - final MethodChannel _channel; + @visibleForTesting + final MethodChannel channel; @override - MethodChannel get _methodChannel => _channel; + MethodChannel get methodChannel => channel; /// HttpResponse code of the request. set httpResponseCode(int httpResponseCode) { - _channel.invokeMethod( + channel.invokeMethod( '$HttpMetric#httpResponseCode', httpResponseCode, ); @@ -33,7 +34,7 @@ class HttpMetric extends PerformanceAttributes { /// Size of the request payload. set requestPayloadSize(int requestPayloadSize) { - _channel.invokeMethod( + channel.invokeMethod( '$HttpMetric#requestPayloadSize', requestPayloadSize, ); @@ -41,7 +42,7 @@ class HttpMetric extends PerformanceAttributes { /// Content type of the response such as text/html, application/json, etc... set responseContentType(String responseContentType) { - _channel.invokeMethod( + channel.invokeMethod( '$HttpMetric#responseContentType', responseContentType, ); @@ -49,7 +50,7 @@ class HttpMetric extends PerformanceAttributes { /// Size of the response payload. set responsePayloadSize(int responsePayloadSize) { - _channel.invokeMethod( + channel.invokeMethod( '$HttpMetric#responsePayloadSize', responsePayloadSize, ); @@ -60,7 +61,7 @@ class HttpMetric extends PerformanceAttributes { /// Using ```await``` with this method is only necessary when accurate timing /// is relevant. Future start() { - return _channel.invokeMethod('$HttpMetric#start'); + return channel.invokeMethod('$HttpMetric#start'); } /// Stops this [HttpMetric]. @@ -72,6 +73,6 @@ class HttpMetric extends PerformanceAttributes { /// /// Not necessary to use ```await``` with this method. Future stop() { - return _channel.invokeMethod('$HttpMetric#stop'); + return channel.invokeMethod('$HttpMetric#stop'); } } diff --git a/packages/firebase_performance/lib/src/performance_attributes.dart b/packages/firebase_performance/lib/src/performance_attributes.dart index b9247e73b1b0..b74869e11878 100644 --- a/packages/firebase_performance/lib/src/performance_attributes.dart +++ b/packages/firebase_performance/lib/src/performance_attributes.dart @@ -15,7 +15,8 @@ abstract class PerformanceAttributes { /// Maximum allowed number of attributes that can be added. static const int maxCustomAttributes = 5; - MethodChannel get _methodChannel; + @visibleForTesting + MethodChannel get methodChannel; /// Sets a String [value] for the specified [attribute]. /// @@ -27,7 +28,7 @@ abstract class PerformanceAttributes { /// characters. Value of the attribute has max length of /// [maxAttributeValueLength] characters. Future putAttribute(String attribute, String value) { - return _methodChannel.invokeMethod( + return methodChannel.invokeMethod( '$PerformanceAttributes#putAttribute', {'attribute': attribute, 'value': value}, ); @@ -35,15 +36,15 @@ abstract class PerformanceAttributes { /// Removes an already added [attribute]. Future removeAttribute(String attribute) { - return _methodChannel.invokeMethod( - '$PerformanceAttributes#putAttribute', + return methodChannel.invokeMethod( + '$PerformanceAttributes#removeAttribute', attribute, ); } /// All [attribute]s added. Future> getAttributes() { - return _methodChannel.invokeMapMethod( + return methodChannel.invokeMapMethod( '$PerformanceAttributes#getAttributes', ); } diff --git a/packages/firebase_performance/lib/src/trace.dart b/packages/firebase_performance/lib/src/trace.dart index 5298ea5dde06..cda5c066fecc 100644 --- a/packages/firebase_performance/lib/src/trace.dart +++ b/packages/firebase_performance/lib/src/trace.dart @@ -19,15 +19,16 @@ part of firebase_performance; /// You can confirm that Performance Monitoring results appear in the Firebase /// console. Results should appear within 12 hours. class Trace extends PerformanceAttributes { - Trace._(this._channel); + Trace._(this.channel); /// Maximum allowed length of the name of a [Trace]. static const int maxTraceNameLength = 100; - final MethodChannel _channel; + @visibleForTesting + final MethodChannel channel; @override - MethodChannel get _methodChannel => _channel; + MethodChannel get methodChannel => channel; /// Starts this [Trace] asynchronously. /// @@ -36,7 +37,7 @@ class Trace extends PerformanceAttributes { /// Using ```await``` with this method is only necessary when accurate timing /// is relevant. Future start() { - return _channel.invokeMethod('$Trace#start'); + return channel.invokeMethod('$Trace#start'); } /// Stops this [Trace] asynchronously. @@ -48,7 +49,7 @@ class Trace extends PerformanceAttributes { /// /// Not necessary to use ```await``` with this method. Future stop() { - return _channel.invokeMethod('$Trace#stop'); + return channel.invokeMethod('$Trace#stop'); } /// Increments the metric with the given name asynchronously. @@ -57,7 +58,7 @@ class Trace extends PerformanceAttributes { /// not been started or has already been stopped, returns immediately without /// taking action. Future incrementMetric(String name, int value) { - return _channel.invokeMethod( + return channel.invokeMethod( '$Trace#incrementMetric', {'name': name, 'value': value}, ); @@ -69,7 +70,7 @@ class Trace extends PerformanceAttributes { /// If the trace has not been started or has already been stopped, returns /// immediately without taking action. Future putMetric(String name, int value) { - return _channel.invokeMethod( + return channel.invokeMethod( '$Trace#putMetric', {'name': name, 'value': value}, ); @@ -80,7 +81,7 @@ class Trace extends PerformanceAttributes { /// If a metric with the given name doesn't exist, it is NOT created and a 0 /// is returned. Future getMetric(String name) { - return _channel.invokeMethod( + return channel.invokeMethod( '$Trace#getMetric', {'name': name}, ); diff --git a/packages/firebase_performance/test/firebase_performance_test.dart b/packages/firebase_performance/test/firebase_performance_test.dart index bf2b42e50499..cf45623f5f41 100644 --- a/packages/firebase_performance/test/firebase_performance_test.dart +++ b/packages/firebase_performance/test/firebase_performance_test.dart @@ -7,15 +7,10 @@ import 'package:flutter/services.dart'; import 'package:firebase_performance/firebase_performance.dart'; import 'package:flutter_test/flutter_test.dart'; -class MockPerformanceAttributes extends PerformanceAttributes {} - void main() { group('$FirebasePerformance', () { final FirebasePerformance performance = FirebasePerformance.instance; final List log = []; - bool performanceCollectionEnable = true; - int currentTraceHandle; - int currentHttpMetricHandle; setUp(() { FirebasePerformance.channel @@ -23,20 +18,7 @@ void main() { log.add(methodCall); switch (methodCall.method) { case 'FirebasePerformance#isPerformanceCollectionEnabled': - return performanceCollectionEnable; - case 'FirebasePerformance#setPerformanceCollectionEnabled': - performanceCollectionEnable = methodCall.arguments; - return null; - case 'Trace#start': - currentTraceHandle = methodCall.arguments['handle']; - return null; - case 'Trace#stop': - return null; - case 'HttpMetric#start': - currentHttpMetricHandle = methodCall.arguments['handle']; - return null; - case 'HttpMetric#stop': - return null; + return true; default: return null; } @@ -47,7 +29,7 @@ void main() { test('isPerformanceCollectionEnabled', () async { final bool enabled = await performance.isPerformanceCollectionEnabled(); - expect(performanceCollectionEnable, enabled); + expect(enabled, isTrue); expect(log, [ isMethodCall( 'FirebasePerformance#isPerformanceCollectionEnabled', @@ -58,10 +40,7 @@ void main() { test('setPerformanceCollectionEnabled', () async { await performance.setPerformanceCollectionEnabled(true); - performanceCollectionEnable = true; - await performance.setPerformanceCollectionEnabled(false); - performanceCollectionEnable = false; expect(log, [ isMethodCall( @@ -77,188 +56,121 @@ void main() { test('newTrace', () async { final Trace trace = performance.newTrace('test-trace'); - await trace.start(); + + await pumpEventQueue(); expect(log, [ isMethodCall( - 'Trace#start', - arguments: { - 'handle': currentTraceHandle, - 'name': 'test-trace', + 'FirebasePerformance#newTrace', + arguments: { + 'channelName': trace.channel.name, + 'traceName': 'test-trace', }, ), ]); }); test('newHttpMetric', () async { + final String url = 'https://google.com'; + final HttpMetric metric = performance.newHttpMetric( - 'https://google.com', + url, HttpMethod.Connect, ); - await metric.start(); - expect(log, [ - isMethodCall( - 'HttpMetric#start', - arguments: { - 'handle': currentTraceHandle, - 'url': 'https://google.com', - 'httpMethod': HttpMethod.Connect.index, - }, - ), - ]); - }); - - test('startTrace', () async { - await FirebasePerformance.startTrace('startTrace-test'); + await pumpEventQueue(); expect(log, [ isMethodCall( - 'Trace#start', - arguments: { - 'handle': currentTraceHandle, - 'name': 'startTrace-test', + 'FirebasePerformance#newHttpMetric', + arguments: { + 'channelName': metric.channel.name, + 'url': url, + 'httpMethod': HttpMethod.Connect.toString(), }, ), ]); }); test('$HttpMethod', () async { - expect(HttpMethod.Connect.index, 0); - expect(HttpMethod.Delete.index, 1); - expect(HttpMethod.Get.index, 2); - expect(HttpMethod.Head.index, 3); - expect(HttpMethod.Options.index, 4); - expect(HttpMethod.Patch.index, 5); - expect(HttpMethod.Post.index, 6); - expect(HttpMethod.Put.index, 7); - expect(HttpMethod.Trace.index, 8); + final String url = 'https://google.com'; + + for (HttpMethod method in HttpMethod.values) { + final HttpMetric metric = performance.newHttpMetric( + 'https://google.com', + method, + ); + + await pumpEventQueue(); + + expect(log, [ + isMethodCall( + 'FirebasePerformance#newHttpMetric', + arguments: { + 'channelName': metric.channel.name, + 'url': url, + 'httpMethod': method.toString(), + }, + ), + ]); + + log.clear(); + } }); group('$Trace', () { Trace testTrace; + final List traceLog = []; setUp(() { testTrace = performance.newTrace('test'); + testTrace.channel + .setMockMethodCallHandler((MethodCall methodCall) async { + traceLog.add(methodCall); + switch (methodCall.method) { + case 'FirebasePerformance#isPerformanceCollectionEnabled': + return true; + default: + return null; + } + }); + traceLog.clear(); }); test('start', () async { + await pumpEventQueue(); + await testTrace.start(); - expect(log, [ - isMethodCall( - 'Trace#start', - arguments: { - 'handle': currentTraceHandle, - 'name': 'test', - }, - ), + expect(traceLog, [ + isMethodCall('Trace#start', arguments: null), ]); }); test('stop', () async { - await testTrace.start(); + await pumpEventQueue(); + await testTrace.stop(); - expect(log, [ - isMethodCall('Trace#start', arguments: { - 'handle': currentTraceHandle, - 'name': 'test', - }), - isMethodCall( - 'Trace#stop', - arguments: { - 'handle': currentTraceHandle, - 'name': 'test', - 'metrics': {}, - 'attributes': {}, - }, - ), - ]); - }); - - test('incrementCounter', () async { - final Trace trace = performance.newTrace('test'); - - // ignore: deprecated_member_use_from_same_package - trace.incrementCounter('counter1'); - - // ignore: deprecated_member_use_from_same_package - trace.incrementCounter('counter2'); - // ignore: deprecated_member_use_from_same_package - trace.incrementCounter('counter2'); - - // ignore: deprecated_member_use_from_same_package - trace.incrementCounter('counter3', 5); - // ignore: deprecated_member_use_from_same_package - trace.incrementCounter('counter3', 5); - - // ignore: deprecated_member_use_from_same_package - trace.incrementCounter('counter4', -5); - - await trace.start(); - await trace.stop(); - - expect(log, [ - isMethodCall( - 'Trace#start', - arguments: { - 'handle': currentTraceHandle, - 'name': 'test', - }, - ), - isMethodCall( - 'Trace#stop', - arguments: { - 'handle': currentTraceHandle, - 'name': 'test', - 'metrics': { - 'counter1': 1, - 'counter2': 2, - 'counter3': 10, - 'counter4': -5, - }, - 'attributes': {}, - }, - ), + expect(traceLog, [ + isMethodCall('Trace#stop', arguments: null), ]); }); test('incrementMetric', () async { - final Trace trace = performance.newTrace('test'); - trace.incrementMetric('metric1', 1); - - trace.incrementMetric('metric2', 1); - trace.incrementMetric('metric2', 1); - - trace.incrementMetric('metric3', 5); - trace.incrementMetric('metric3', 5); + await pumpEventQueue(); - trace.incrementMetric('metric4', -5); + final String name = 'counter1'; + final int value = 45; - await trace.start(); - await trace.stop(); + testTrace.incrementMetric(name, value); - expect(log, [ + expect(traceLog, [ isMethodCall( - 'Trace#start', - arguments: { - 'handle': currentTraceHandle, - 'name': 'test', - }, - ), - isMethodCall( - 'Trace#stop', + 'Trace#incrementMetric', arguments: { - 'handle': currentTraceHandle, - 'name': 'test', - 'metrics': { - 'metric1': 1, - 'metric2': 2, - 'metric3': 10, - 'metric4': -5, - }, - 'attributes': {}, + 'name': name, + 'value': value, }, ), ]); @@ -267,106 +179,115 @@ void main() { group('$HttpMetric', () { HttpMetric testMetric; + final List httpMetricLog = []; setUp(() { testMetric = performance.newHttpMetric( 'https://google.com', HttpMethod.Get, ); + testMetric.channel + .setMockMethodCallHandler((MethodCall methodCall) async { + httpMetricLog.add(methodCall); + switch (methodCall.method) { + case 'FirebasePerformance#isPerformanceCollectionEnabled': + return true; + default: + return null; + } + }); + httpMetricLog.clear(); }); test('start', () async { + await pumpEventQueue(); + await testMetric.start(); - expect(log, [ - isMethodCall( - 'HttpMetric#start', - arguments: { - 'handle': currentHttpMetricHandle, - 'url': 'https://google.com', - 'httpMethod': HttpMethod.Get.index, - }, - ), + expect(httpMetricLog, [ + isMethodCall('HttpMetric#start', arguments: null), ]); }); test('stop', () async { - testMetric.httpResponseCode = 1; - testMetric.requestPayloadSize = 5000000; - testMetric.responseContentType = 'text/html'; - testMetric.responsePayloadSize = 1992304820934820; + await pumpEventQueue(); - await testMetric.start(); await testMetric.stop(); - expect(log, [ - isMethodCall( - 'HttpMetric#start', - arguments: { - 'handle': currentHttpMetricHandle, - 'url': 'https://google.com', - 'httpMethod': HttpMethod.Get.index, - }, - ), - isMethodCall( - 'HttpMetric#stop', - arguments: { - 'handle': currentHttpMetricHandle, - 'httpResponseCode': 1, - 'requestPayloadSize': 5000000, - 'responseContentType': 'text/html', - 'responsePayloadSize': 1992304820934820, - 'attributes': {}, - }, - ), + expect(httpMetricLog, [ + isMethodCall('HttpMetric#stop', arguments: null), ]); }); }); group('$PerformanceAttributes', () { - PerformanceAttributes attributes; + final PerformanceAttributes attributes = MockPerformanceAttributes(); + final List attributeLog = []; + final Map getAttributesResult = { + 'a1': 'hello', + 'a2': 'friend', + }; setUp(() { - attributes = MockPerformanceAttributes(); + MockPerformanceAttributes._channel + .setMockMethodCallHandler((MethodCall methodCall) async { + attributeLog.add(methodCall); + if (methodCall.method == 'PerformanceAttributes#getAttributes') { + return getAttributesResult; + } + + return null; + }); + attributeLog.clear(); }); test('putAttribute', () async { - attributes.putAttribute('attr1', 'apple'); - attributes.putAttribute('attr2', 'are'); - expect(attributes.attributes, { - 'attr1': 'apple', - 'attr2': 'are', - }); + final String attribute = 'attr1'; + final String value = 'apple'; + await attributes.putAttribute(attribute, value); - attributes.putAttribute('attr1', 'delicious'); - expect(attributes.attributes, { - 'attr1': 'delicious', - 'attr2': 'are', - }); + expect(attributeLog, [ + isMethodCall( + 'PerformanceAttributes#putAttribute', + arguments: { + 'attribute': attribute, + 'value': value, + }, + ), + ]); }); test('removeAttribute', () async { - attributes.putAttribute('attr1', 'apple'); - attributes.putAttribute('attr2', 'are'); - attributes.removeAttribute('no-attr'); - expect(attributes.attributes, { - 'attr1': 'apple', - 'attr2': 'are', - }); + final String attribute = 'attr1'; + await attributes.removeAttribute(attribute); - attributes.removeAttribute('attr1'); - expect(attributes.attributes, { - 'attr2': 'are', - }); + expect(attributeLog, [ + isMethodCall( + 'PerformanceAttributes#removeAttribute', + arguments: attribute, + ), + ]); }); - test('getAttribute', () { - attributes.putAttribute('attr1', 'apple'); - attributes.putAttribute('attr2', 'are'); - expect(attributes.getAttribute('attr1'), 'apple'); + test('getAttributes', () async { + final Map result = await attributes.getAttributes(); + + expect(attributeLog, [ + isMethodCall( + 'PerformanceAttributes#getAttributes', + arguments: null, + ), + ]); - expect(attributes.getAttribute('attr3'), isNull); + expect(result, getAttributesResult); }); }); }); } + +class MockPerformanceAttributes extends PerformanceAttributes { + static MethodChannel _channel = const MethodChannel('testMethodChannel'); + + @override + MethodChannel get methodChannel => _channel; +} From 08d976f2dbef722552286ad3548eb02d28dbf92b Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 23 Apr 2019 14:39:24 -0700 Subject: [PATCH 10/40] Extra space --- .../flutter/plugins/firebaseperformance/FlutterHttpMetric.java | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java index d3073f37b52f..927a94719fea 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java @@ -127,7 +127,6 @@ private void setResponsePayloadSize(MethodCall call, MethodChannel.Result result result.success(null); } - private void putAttribute(MethodCall call, MethodChannel.Result result) { final String attribute = call.argument("attribute"); final String value = call.argument("value"); From 8a8ab7725817205f3389551a789d5d7053e6ad6a Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 23 Apr 2019 15:01:59 -0700 Subject: [PATCH 11/40] Remove awaits and ayncs --- .../test/firebase_performance_test.dart | 101 ++++++++---------- 1 file changed, 46 insertions(+), 55 deletions(-) diff --git a/packages/firebase_performance/test/firebase_performance_test.dart b/packages/firebase_performance/test/firebase_performance_test.dart index cf45623f5f41..42b8f67e7c24 100644 --- a/packages/firebase_performance/test/firebase_performance_test.dart +++ b/packages/firebase_performance/test/firebase_performance_test.dart @@ -11,6 +11,7 @@ void main() { group('$FirebasePerformance', () { final FirebasePerformance performance = FirebasePerformance.instance; final List log = []; + bool isPerformanceCollectionEnabledResult; setUp(() { FirebasePerformance.channel @@ -18,7 +19,7 @@ void main() { log.add(methodCall); switch (methodCall.method) { case 'FirebasePerformance#isPerformanceCollectionEnabled': - return true; + return isPerformanceCollectionEnabledResult; default: return null; } @@ -27,20 +28,29 @@ void main() { }); test('isPerformanceCollectionEnabled', () async { + isPerformanceCollectionEnabledResult = true; final bool enabled = await performance.isPerformanceCollectionEnabled(); - expect(enabled, isTrue); + + isPerformanceCollectionEnabledResult = false; + final bool disabled = await performance.isPerformanceCollectionEnabled(); + expect(disabled, isFalse); + expect(log, [ isMethodCall( 'FirebasePerformance#isPerformanceCollectionEnabled', arguments: null, ), + isMethodCall( + 'FirebasePerformance#isPerformanceCollectionEnabled', + arguments: null, + ), ]); }); - test('setPerformanceCollectionEnabled', () async { - await performance.setPerformanceCollectionEnabled(true); - await performance.setPerformanceCollectionEnabled(false); + test('setPerformanceCollectionEnabled', () { + performance.setPerformanceCollectionEnabled(true); + performance.setPerformanceCollectionEnabled(false); expect(log, [ isMethodCall( @@ -54,11 +64,9 @@ void main() { ]); }); - test('newTrace', () async { + test('newTrace', () { final Trace trace = performance.newTrace('test-trace'); - await pumpEventQueue(); - expect(log, [ isMethodCall( 'FirebasePerformance#newTrace', @@ -70,7 +78,7 @@ void main() { ]); }); - test('newHttpMetric', () async { + test('newHttpMetric', () { final String url = 'https://google.com'; final HttpMetric metric = performance.newHttpMetric( @@ -78,8 +86,6 @@ void main() { HttpMethod.Connect, ); - await pumpEventQueue(); - expect(log, [ isMethodCall( 'FirebasePerformance#newHttpMetric', @@ -92,30 +98,25 @@ void main() { ]); }); - test('$HttpMethod', () async { + test('$HttpMethod', () { final String url = 'https://google.com'; + final HttpMethod method = HttpMethod.Connect; - for (HttpMethod method in HttpMethod.values) { - final HttpMetric metric = performance.newHttpMetric( - 'https://google.com', - method, - ); - - await pumpEventQueue(); - - expect(log, [ - isMethodCall( - 'FirebasePerformance#newHttpMetric', - arguments: { - 'channelName': metric.channel.name, - 'url': url, - 'httpMethod': method.toString(), - }, - ), - ]); + final HttpMetric metric = performance.newHttpMetric( + 'https://google.com', + method, + ); - log.clear(); - } + expect(log, [ + isMethodCall( + 'FirebasePerformance#newHttpMetric', + arguments: { + 'channelName': metric.channel.name, + 'url': url, + 'httpMethod': method.toString(), + }, + ), + ]); }); group('$Trace', () { @@ -137,29 +138,23 @@ void main() { traceLog.clear(); }); - test('start', () async { - await pumpEventQueue(); - - await testTrace.start(); + test('start', () { + testTrace.start(); expect(traceLog, [ isMethodCall('Trace#start', arguments: null), ]); }); - test('stop', () async { - await pumpEventQueue(); - - await testTrace.stop(); + test('stop', () { + testTrace.stop(); expect(traceLog, [ isMethodCall('Trace#stop', arguments: null), ]); }); - test('incrementMetric', () async { - await pumpEventQueue(); - + test('incrementMetric', () { final String name = 'counter1'; final int value = 45; @@ -199,20 +194,16 @@ void main() { httpMetricLog.clear(); }); - test('start', () async { - await pumpEventQueue(); - - await testMetric.start(); + test('start', () { + testMetric.start(); expect(httpMetricLog, [ isMethodCall('HttpMetric#start', arguments: null), ]); }); - test('stop', () async { - await pumpEventQueue(); - - await testMetric.stop(); + test('stop', () { + testMetric.stop(); expect(httpMetricLog, [ isMethodCall('HttpMetric#stop', arguments: null), @@ -241,10 +232,10 @@ void main() { attributeLog.clear(); }); - test('putAttribute', () async { + test('putAttribute', () { final String attribute = 'attr1'; final String value = 'apple'; - await attributes.putAttribute(attribute, value); + attributes.putAttribute(attribute, value); expect(attributeLog, [ isMethodCall( @@ -257,9 +248,9 @@ void main() { ]); }); - test('removeAttribute', () async { + test('removeAttribute', () { final String attribute = 'attr1'; - await attributes.removeAttribute(attribute); + attributes.removeAttribute(attribute); expect(attributeLog, [ isMethodCall( From 3c3ed91e6cc27c89e8c37e151529c85ce1d9aea9 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 23 Apr 2019 15:02:44 -0700 Subject: [PATCH 12/40] Remove mentions of asynchronous --- .../lib/src/firebase_performance.dart | 2 +- packages/firebase_performance/lib/src/http_metric.dart | 2 +- packages/firebase_performance/lib/src/trace.dart | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/firebase_performance/lib/src/firebase_performance.dart b/packages/firebase_performance/lib/src/firebase_performance.dart index f1640665ca64..5b9e044b47e1 100644 --- a/packages/firebase_performance/lib/src/firebase_performance.dart +++ b/packages/firebase_performance/lib/src/firebase_performance.dart @@ -33,7 +33,7 @@ class FirebasePerformance { ); } - /// Enables or disables performance monitoring asynchronously. + /// Enables or disables performance monitoring. /// /// This setting is persisted and applied on future invocations of your /// application. By default, performance monitoring is enabled. diff --git a/packages/firebase_performance/lib/src/http_metric.dart b/packages/firebase_performance/lib/src/http_metric.dart index aeabb8024c95..67b3ba1b40ab 100644 --- a/packages/firebase_performance/lib/src/http_metric.dart +++ b/packages/firebase_performance/lib/src/http_metric.dart @@ -56,7 +56,7 @@ class HttpMetric extends PerformanceAttributes { ); } - /// Starts this [HttpMetric] asynchronously. + /// Starts this [HttpMetric]. /// /// Using ```await``` with this method is only necessary when accurate timing /// is relevant. diff --git a/packages/firebase_performance/lib/src/trace.dart b/packages/firebase_performance/lib/src/trace.dart index cda5c066fecc..936f9204d55c 100644 --- a/packages/firebase_performance/lib/src/trace.dart +++ b/packages/firebase_performance/lib/src/trace.dart @@ -30,7 +30,7 @@ class Trace extends PerformanceAttributes { @override MethodChannel get methodChannel => channel; - /// Starts this [Trace] asynchronously. + /// Starts this [Trace]. /// /// Can only be called once. /// @@ -40,7 +40,7 @@ class Trace extends PerformanceAttributes { return channel.invokeMethod('$Trace#start'); } - /// Stops this [Trace] asynchronously. + /// Stops this [Trace]. /// /// Can only be called once and only after start() Data collected is /// automatically sent to the associated Firebase console after stop() is @@ -52,7 +52,7 @@ class Trace extends PerformanceAttributes { return channel.invokeMethod('$Trace#stop'); } - /// Increments the metric with the given name asynchronously. + /// Increments the metric with the given name. /// /// If the metric does not exist, a new one will be created. If the trace has /// not been started or has already been stopped, returns immediately without @@ -64,7 +64,7 @@ class Trace extends PerformanceAttributes { ); } - /// Sets the value of the metric with the given name asynchronously. + /// Sets the value of the metric with the given name. /// /// If a metric with the given name doesn't exist, a new one will be created. /// If the trace has not been started or has already been stopped, returns From bd971abcb02f25cc535d9017747a1eb4a272b2f7 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 23 Apr 2019 16:56:29 -0700 Subject: [PATCH 13/40] cache state --- .../lib/src/firebase_performance.dart | 2 +- .../lib/src/http_metric.dart | 20 +++++++++++ .../lib/src/performance_attributes.dart | 24 +++++++++++++- .../firebase_performance/lib/src/trace.dart | 26 +++++++++++++++ .../test/firebase_performance_test.dart | 33 +++++++++---------- 5 files changed, 86 insertions(+), 19 deletions(-) diff --git a/packages/firebase_performance/lib/src/firebase_performance.dart b/packages/firebase_performance/lib/src/firebase_performance.dart index 5b9e044b47e1..d4843dcf245a 100644 --- a/packages/firebase_performance/lib/src/firebase_performance.dart +++ b/packages/firebase_performance/lib/src/firebase_performance.dart @@ -37,7 +37,7 @@ class FirebasePerformance { /// /// This setting is persisted and applied on future invocations of your /// application. By default, performance monitoring is enabled. - Future setPerformanceCollectionEnabled(bool enable) async { + Future setPerformanceCollectionEnabled(bool enable) { return channel.invokeMethod( 'FirebasePerformance#setPerformanceCollectionEnabled', enable, diff --git a/packages/firebase_performance/lib/src/http_metric.dart b/packages/firebase_performance/lib/src/http_metric.dart index 67b3ba1b40ab..c7669571b5c1 100644 --- a/packages/firebase_performance/lib/src/http_metric.dart +++ b/packages/firebase_performance/lib/src/http_metric.dart @@ -21,11 +21,19 @@ class HttpMetric extends PerformanceAttributes { @visibleForTesting final MethodChannel channel; + @override + bool _hasStarted = false; + + @override + bool _hasStopped = false; + @override MethodChannel get methodChannel => channel; /// HttpResponse code of the request. set httpResponseCode(int httpResponseCode) { + if (_hasStopped) return; + channel.invokeMethod( '$HttpMetric#httpResponseCode', httpResponseCode, @@ -34,6 +42,8 @@ class HttpMetric extends PerformanceAttributes { /// Size of the request payload. set requestPayloadSize(int requestPayloadSize) { + if (_hasStopped) return; + channel.invokeMethod( '$HttpMetric#requestPayloadSize', requestPayloadSize, @@ -42,6 +52,8 @@ class HttpMetric extends PerformanceAttributes { /// Content type of the response such as text/html, application/json, etc... set responseContentType(String responseContentType) { + if (_hasStopped) return; + channel.invokeMethod( '$HttpMetric#responseContentType', responseContentType, @@ -50,6 +62,8 @@ class HttpMetric extends PerformanceAttributes { /// Size of the response payload. set responsePayloadSize(int responsePayloadSize) { + if (_hasStopped) return; + channel.invokeMethod( '$HttpMetric#responsePayloadSize', responsePayloadSize, @@ -61,6 +75,9 @@ class HttpMetric extends PerformanceAttributes { /// Using ```await``` with this method is only necessary when accurate timing /// is relevant. Future start() { + if (_hasStarted || _hasStopped) return Future.value(null); + + _hasStarted = true; return channel.invokeMethod('$HttpMetric#start'); } @@ -73,6 +90,9 @@ class HttpMetric extends PerformanceAttributes { /// /// Not necessary to use ```await``` with this method. Future stop() { + if (_hasStopped) return Future.value(null); + + _hasStopped = true; return channel.invokeMethod('$HttpMetric#stop'); } } diff --git a/packages/firebase_performance/lib/src/performance_attributes.dart b/packages/firebase_performance/lib/src/performance_attributes.dart index b74869e11878..09411e2d9079 100644 --- a/packages/firebase_performance/lib/src/performance_attributes.dart +++ b/packages/firebase_performance/lib/src/performance_attributes.dart @@ -15,8 +15,12 @@ abstract class PerformanceAttributes { /// Maximum allowed number of attributes that can be added. static const int maxCustomAttributes = 5; + final Map _attributes = {}; + @visibleForTesting MethodChannel get methodChannel; + bool get _hasStarted; + bool get _hasStopped; /// Sets a String [value] for the specified [attribute]. /// @@ -28,6 +32,15 @@ abstract class PerformanceAttributes { /// characters. Value of the attribute has max length of /// [maxAttributeValueLength] characters. Future putAttribute(String attribute, String value) { + if (!_hasStarted || + _hasStopped || + attribute.length > maxAttributeKeyLength || + value.length > maxAttributeValueLength || + _attributes.length == 5) { + return Future.value(null); + } + + _attributes[attribute] = value; return methodChannel.invokeMethod( '$PerformanceAttributes#putAttribute', {'attribute': attribute, 'value': value}, @@ -36,14 +49,23 @@ abstract class PerformanceAttributes { /// Removes an already added [attribute]. Future removeAttribute(String attribute) { + if (!_hasStarted || _hasStopped) return Future.value(null); + + _attributes.remove(attribute); return methodChannel.invokeMethod( '$PerformanceAttributes#removeAttribute', attribute, ); } - /// All [attribute]s added. + /// All attributes added. Future> getAttributes() { + if (_hasStopped) { + return Future>.value(Map.unmodifiable( + _attributes, + )); + } + return methodChannel.invokeMapMethod( '$PerformanceAttributes#getAttributes', ); diff --git a/packages/firebase_performance/lib/src/trace.dart b/packages/firebase_performance/lib/src/trace.dart index 936f9204d55c..fc406199f900 100644 --- a/packages/firebase_performance/lib/src/trace.dart +++ b/packages/firebase_performance/lib/src/trace.dart @@ -27,6 +27,14 @@ class Trace extends PerformanceAttributes { @visibleForTesting final MethodChannel channel; + final Map _metrics = {}; + + @override + bool _hasStarted = false; + + @override + bool _hasStopped = false; + @override MethodChannel get methodChannel => channel; @@ -37,6 +45,9 @@ class Trace extends PerformanceAttributes { /// Using ```await``` with this method is only necessary when accurate timing /// is relevant. Future start() { + if (_hasStarted || _hasStopped) return Future.value(null); + + _hasStarted = true; return channel.invokeMethod('$Trace#start'); } @@ -49,6 +60,9 @@ class Trace extends PerformanceAttributes { /// /// Not necessary to use ```await``` with this method. Future stop() { + if (_hasStopped) return Future.value(null); + + _hasStopped = true; return channel.invokeMethod('$Trace#stop'); } @@ -58,6 +72,11 @@ class Trace extends PerformanceAttributes { /// not been started or has already been stopped, returns immediately without /// taking action. Future incrementMetric(String name, int value) { + if (!_hasStarted || _hasStopped || _metrics[name] == null) { + return Future.value(null); + } + + _metrics[name] += value; return channel.invokeMethod( '$Trace#incrementMetric', {'name': name, 'value': value}, @@ -70,6 +89,9 @@ class Trace extends PerformanceAttributes { /// If the trace has not been started or has already been stopped, returns /// immediately without taking action. Future putMetric(String name, int value) { + if (!_hasStarted || _hasStopped) return Future.value(null); + + _metrics[name] = value; return channel.invokeMethod( '$Trace#putMetric', {'name': name, 'value': value}, @@ -81,6 +103,10 @@ class Trace extends PerformanceAttributes { /// If a metric with the given name doesn't exist, it is NOT created and a 0 /// is returned. Future getMetric(String name) { + if (_hasStopped) { + return Future.value(_metrics[name] ?? 0); + } + return channel.invokeMethod( '$Trace#getMetric', {'name': name}, diff --git a/packages/firebase_performance/test/firebase_performance_test.dart b/packages/firebase_performance/test/firebase_performance_test.dart index 42b8f67e7c24..2dd5fe122998 100644 --- a/packages/firebase_performance/test/firebase_performance_test.dart +++ b/packages/firebase_performance/test/firebase_performance_test.dart @@ -157,16 +157,18 @@ void main() { test('incrementMetric', () { final String name = 'counter1'; final int value = 45; + final int increment = 3; - testTrace.incrementMetric(name, value); + testTrace.start(); + testTrace.putMetric(name, value); + traceLog.clear(); + + testTrace.incrementMetric(name, increment); expect(traceLog, [ isMethodCall( 'Trace#incrementMetric', - arguments: { - 'name': name, - 'value': value, - }, + arguments: {'name': name, 'value': increment}, ), ]); }); @@ -212,7 +214,7 @@ void main() { }); group('$PerformanceAttributes', () { - final PerformanceAttributes attributes = MockPerformanceAttributes(); + Trace attributeTrace; final List attributeLog = []; final Map getAttributesResult = { 'a1': 'hello', @@ -220,7 +222,8 @@ void main() { }; setUp(() { - MockPerformanceAttributes._channel + attributeTrace = performance.newTrace('trace'); + attributeTrace.channel .setMockMethodCallHandler((MethodCall methodCall) async { attributeLog.add(methodCall); if (methodCall.method == 'PerformanceAttributes#getAttributes') { @@ -229,13 +232,16 @@ void main() { return null; }); + + attributeTrace.start(); attributeLog.clear(); }); test('putAttribute', () { final String attribute = 'attr1'; final String value = 'apple'; - attributes.putAttribute(attribute, value); + + attributeTrace.putAttribute(attribute, value); expect(attributeLog, [ isMethodCall( @@ -250,7 +256,7 @@ void main() { test('removeAttribute', () { final String attribute = 'attr1'; - attributes.removeAttribute(attribute); + attributeTrace.removeAttribute(attribute); expect(attributeLog, [ isMethodCall( @@ -261,7 +267,7 @@ void main() { }); test('getAttributes', () async { - final Map result = await attributes.getAttributes(); + final Map result = await attributeTrace.getAttributes(); expect(attributeLog, [ isMethodCall( @@ -275,10 +281,3 @@ void main() { }); }); } - -class MockPerformanceAttributes extends PerformanceAttributes { - static MethodChannel _channel = const MethodChannel('testMethodChannel'); - - @override - MethodChannel get methodChannel => _channel; -} From 849d62566aa2cb3246acff8a7d14ca008a24b8c2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 24 Apr 2019 11:46:02 -0700 Subject: [PATCH 14/40] Comments/Testings/Variables/Misc --- .../test_driver/firebase_performance.dart | 3 ++ .../lib/src/firebase_performance.dart | 11 +++++ .../lib/src/http_metric.dart | 47 ++++++++++++++++--- .../lib/src/performance_attributes.dart | 11 +++-- .../firebase_performance/lib/src/trace.dart | 26 +++++----- 5 files changed, 71 insertions(+), 27 deletions(-) diff --git a/packages/firebase_performance/example/test_driver/firebase_performance.dart b/packages/firebase_performance/example/test_driver/firebase_performance.dart index fcabfe11f239..295a5da94ad2 100644 --- a/packages/firebase_performance/example/test_driver/firebase_performance.dart +++ b/packages/firebase_performance/example/test_driver/firebase_performance.dart @@ -25,6 +25,8 @@ void main() { expect(disabled, isFalse); }); + // TODO(bparrishMines): Rewrite integration test when iOS portion is written. + /* test('metric', () async { final Trace trace = performance.newTrace('test'); trace.putAttribute('testAttribute', 'foo'); @@ -37,5 +39,6 @@ void main() { expect(trace.getAttribute('testAttribute2'), null); expect(trace.getAttribute('testMetric'), null); }); + */ }); } diff --git a/packages/firebase_performance/lib/src/firebase_performance.dart b/packages/firebase_performance/lib/src/firebase_performance.dart index d4843dcf245a..9a74c3d3632d 100644 --- a/packages/firebase_performance/lib/src/firebase_performance.dart +++ b/packages/firebase_performance/lib/src/firebase_performance.dart @@ -79,4 +79,15 @@ class FirebasePerformance { final MethodChannel channel = MethodChannel(channelName); return HttpMetric._(channel); } + + /// Creates a [Trace] object with given [name] and starts the trace. + /// + /// The [name] requires no leading or trailing whitespace, no leading + /// underscore _ character, max length of [Trace.maxTraceNameLength] + /// characters. + static Future startTrace(String name) async { + final Trace trace = instance.newTrace(name); + await trace.start(); + return trace; + } } diff --git a/packages/firebase_performance/lib/src/http_metric.dart b/packages/firebase_performance/lib/src/http_metric.dart index c7669571b5c1..12ec1dd895f8 100644 --- a/packages/firebase_performance/lib/src/http_metric.dart +++ b/packages/firebase_performance/lib/src/http_metric.dart @@ -18,22 +18,41 @@ part of firebase_performance; class HttpMetric extends PerformanceAttributes { HttpMetric._(this.channel); - @visibleForTesting - final MethodChannel channel; - @override bool _hasStarted = false; @override bool _hasStopped = false; + int _httpResponseCode; + int _requestPayloadSize; + String _responseContentType; + int _responsePayloadSize; + + @visibleForTesting @override - MethodChannel get methodChannel => channel; + final MethodChannel channel; + + /// HttpResponse code of the request. + int get httpResponseCode => _httpResponseCode; + + /// Size of the request payload. + int get requestPayloadSize => _requestPayloadSize; + + /// Content type of the response such as text/html, application/json, etc... + String get responseContentType => _responseContentType; + + /// Size of the response payload. + int get responsePayloadSize => _responsePayloadSize; /// HttpResponse code of the request. + /// + /// If the [HttpMetric] has already been stopped, returns immediately without + /// taking action. set httpResponseCode(int httpResponseCode) { if (_hasStopped) return; + _httpResponseCode = httpResponseCode; channel.invokeMethod( '$HttpMetric#httpResponseCode', httpResponseCode, @@ -41,9 +60,13 @@ class HttpMetric extends PerformanceAttributes { } /// Size of the request payload. + /// + /// If the [HttpMetric] has already been stopped, returns immediately without + /// taking action. set requestPayloadSize(int requestPayloadSize) { if (_hasStopped) return; + _requestPayloadSize = requestPayloadSize; channel.invokeMethod( '$HttpMetric#requestPayloadSize', requestPayloadSize, @@ -51,9 +74,13 @@ class HttpMetric extends PerformanceAttributes { } /// Content type of the response such as text/html, application/json, etc... + /// + /// If the [HttpMetric] has already been stopped, returns immediately without + /// taking action. set responseContentType(String responseContentType) { if (_hasStopped) return; + _responseContentType = responseContentType; channel.invokeMethod( '$HttpMetric#responseContentType', responseContentType, @@ -61,9 +88,13 @@ class HttpMetric extends PerformanceAttributes { } /// Size of the response payload. + /// + /// If the [HttpMetric] has already been stopped, returns immediately without + /// taking action. set responsePayloadSize(int responsePayloadSize) { if (_hasStopped) return; + _responsePayloadSize = responsePayloadSize; channel.invokeMethod( '$HttpMetric#responsePayloadSize', responsePayloadSize, @@ -72,10 +103,12 @@ class HttpMetric extends PerformanceAttributes { /// Starts this [HttpMetric]. /// - /// Using ```await``` with this method is only necessary when accurate timing + /// Can only be called once. + /// + /// Using `await` with this method is only necessary when accurate timing /// is relevant. Future start() { - if (_hasStarted || _hasStopped) return Future.value(null); + if (_hasStopped) return Future.value(null); _hasStarted = true; return channel.invokeMethod('$HttpMetric#start'); @@ -88,7 +121,7 @@ class HttpMetric extends PerformanceAttributes { /// called. You can confirm that Performance Monitoring results appear in the /// Firebase console. Results should appear within 12 hours. /// - /// Not necessary to use ```await``` with this method. + /// Not necessary to use `await` with this method. Future stop() { if (_hasStopped) return Future.value(null); diff --git a/packages/firebase_performance/lib/src/performance_attributes.dart b/packages/firebase_performance/lib/src/performance_attributes.dart index 09411e2d9079..de2f6452c41d 100644 --- a/packages/firebase_performance/lib/src/performance_attributes.dart +++ b/packages/firebase_performance/lib/src/performance_attributes.dart @@ -17,11 +17,12 @@ abstract class PerformanceAttributes { final Map _attributes = {}; - @visibleForTesting - MethodChannel get methodChannel; bool get _hasStarted; bool get _hasStopped; + @visibleForTesting + MethodChannel get channel; + /// Sets a String [value] for the specified [attribute]. /// /// Updates the value of the attribute if the attribute already exists. @@ -41,7 +42,7 @@ abstract class PerformanceAttributes { } _attributes[attribute] = value; - return methodChannel.invokeMethod( + return channel.invokeMethod( '$PerformanceAttributes#putAttribute', {'attribute': attribute, 'value': value}, ); @@ -52,7 +53,7 @@ abstract class PerformanceAttributes { if (!_hasStarted || _hasStopped) return Future.value(null); _attributes.remove(attribute); - return methodChannel.invokeMethod( + return channel.invokeMethod( '$PerformanceAttributes#removeAttribute', attribute, ); @@ -66,7 +67,7 @@ abstract class PerformanceAttributes { )); } - return methodChannel.invokeMapMethod( + return channel.invokeMapMethod( '$PerformanceAttributes#getAttributes', ); } diff --git a/packages/firebase_performance/lib/src/trace.dart b/packages/firebase_performance/lib/src/trace.dart index fc406199f900..484e2e3fba37 100644 --- a/packages/firebase_performance/lib/src/trace.dart +++ b/packages/firebase_performance/lib/src/trace.dart @@ -24,9 +24,6 @@ class Trace extends PerformanceAttributes { /// Maximum allowed length of the name of a [Trace]. static const int maxTraceNameLength = 100; - @visibleForTesting - final MethodChannel channel; - final Map _metrics = {}; @override @@ -35,17 +32,18 @@ class Trace extends PerformanceAttributes { @override bool _hasStopped = false; + @visibleForTesting @override - MethodChannel get methodChannel => channel; + final MethodChannel channel; /// Starts this [Trace]. /// /// Can only be called once. /// - /// Using ```await``` with this method is only necessary when accurate timing + /// Using `await` with this method is only necessary when accurate timing /// is relevant. Future start() { - if (_hasStarted || _hasStopped) return Future.value(null); + if (_hasStopped) return Future.value(null); _hasStarted = true; return channel.invokeMethod('$Trace#start'); @@ -58,7 +56,7 @@ class Trace extends PerformanceAttributes { /// called. You can confirm that Performance Monitoring results appear in the /// Firebase console. Results should appear within 12 hours. /// - /// Not necessary to use ```await``` with this method. + /// Not necessary to use `await` with this method. Future stop() { if (_hasStopped) return Future.value(null); @@ -66,9 +64,9 @@ class Trace extends PerformanceAttributes { return channel.invokeMethod('$Trace#stop'); } - /// Increments the metric with the given name. + /// Increments the metric with the given [name]. /// - /// If the metric does not exist, a new one will be created. If the trace has + /// If the metric does not exist, a new one will be created. If the [Trace] has /// not been started or has already been stopped, returns immediately without /// taking action. Future incrementMetric(String name, int value) { @@ -83,10 +81,10 @@ class Trace extends PerformanceAttributes { ); } - /// Sets the value of the metric with the given name. + /// Sets the [value] of the metric with the given [name]. /// /// If a metric with the given name doesn't exist, a new one will be created. - /// If the trace has not been started or has already been stopped, returns + /// If the [Trace] has not been started or has already been stopped, returns /// immediately without taking action. Future putMetric(String name, int value) { if (!_hasStarted || _hasStopped) return Future.value(null); @@ -98,14 +96,12 @@ class Trace extends PerformanceAttributes { ); } - /// Gets the value of the metric with the given name. + /// Gets the value of the metric with the given [name]. /// /// If a metric with the given name doesn't exist, it is NOT created and a 0 /// is returned. Future getMetric(String name) { - if (_hasStopped) { - return Future.value(_metrics[name] ?? 0); - } + if (_hasStopped) return Future.value(_metrics[name] ?? 0); return channel.invokeMethod( '$Trace#getMetric', From b08ad05bb12f46165f4b0f569f518fb2acca4a06 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 24 Apr 2019 12:08:26 -0700 Subject: [PATCH 15/40] Change putMetric to setMetric to match iOS API. Also add name variable --- .../lib/src/firebase_performance.dart | 2 +- packages/firebase_performance/lib/src/trace.dart | 9 ++++++--- .../test/firebase_performance_test.dart | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/firebase_performance/lib/src/firebase_performance.dart b/packages/firebase_performance/lib/src/firebase_performance.dart index 9a74c3d3632d..571e6b8063bd 100644 --- a/packages/firebase_performance/lib/src/firebase_performance.dart +++ b/packages/firebase_performance/lib/src/firebase_performance.dart @@ -59,7 +59,7 @@ class FirebasePerformance { ); final MethodChannel channel = MethodChannel(channelName); - return Trace._(channel); + return Trace._(channel, name); } /// Creates [HttpMetric] for collecting performance for one request/response. diff --git a/packages/firebase_performance/lib/src/trace.dart b/packages/firebase_performance/lib/src/trace.dart index 484e2e3fba37..20e240385eb7 100644 --- a/packages/firebase_performance/lib/src/trace.dart +++ b/packages/firebase_performance/lib/src/trace.dart @@ -19,7 +19,7 @@ part of firebase_performance; /// You can confirm that Performance Monitoring results appear in the Firebase /// console. Results should appear within 12 hours. class Trace extends PerformanceAttributes { - Trace._(this.channel); + Trace._(this.channel, this.name); /// Maximum allowed length of the name of a [Trace]. static const int maxTraceNameLength = 100; @@ -36,6 +36,9 @@ class Trace extends PerformanceAttributes { @override final MethodChannel channel; + /// Name representing this [Trace] on the Firebase Console. + final String name; + /// Starts this [Trace]. /// /// Can only be called once. @@ -86,12 +89,12 @@ class Trace extends PerformanceAttributes { /// If a metric with the given name doesn't exist, a new one will be created. /// If the [Trace] has not been started or has already been stopped, returns /// immediately without taking action. - Future putMetric(String name, int value) { + Future setMetric(String name, int value) { if (!_hasStarted || _hasStopped) return Future.value(null); _metrics[name] = value; return channel.invokeMethod( - '$Trace#putMetric', + '$Trace#setMetric', {'name': name, 'value': value}, ); } diff --git a/packages/firebase_performance/test/firebase_performance_test.dart b/packages/firebase_performance/test/firebase_performance_test.dart index 2dd5fe122998..7ce36bb65294 100644 --- a/packages/firebase_performance/test/firebase_performance_test.dart +++ b/packages/firebase_performance/test/firebase_performance_test.dart @@ -160,7 +160,7 @@ void main() { final int increment = 3; testTrace.start(); - testTrace.putMetric(name, value); + testTrace.setMetric(name, value); traceLog.clear(); testTrace.incrementMetric(name, increment); From 353641e9261dbc4aa4f4b6b65605636318aac6e1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 24 Apr 2019 12:24:28 -0700 Subject: [PATCH 16/40] Change method name to setMetric --- .../flutter/plugins/firebaseperformance/FlutterTrace.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java index 9b3b4c8f58e2..e544ffbc8c77 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java @@ -40,8 +40,8 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) { case "Trace#stop": stop(result); break; - case "Trace#putMetric": - putMetric(call, result); + case "Trace#setMetric": + setMetric(call, result); break; case "Trace#incrementMetric": incrementMetric(call, result); @@ -74,7 +74,7 @@ private void stop(MethodChannel.Result result) { result.success(null); } - private void putMetric(MethodCall call, MethodChannel.Result result) { + private void setMetric(MethodCall call, MethodChannel.Result result) { final String name = call.argument("name"); final Number value = call.argument("value"); trace.putMetric(name, value.longValue()); From 0295e2edbbbb0b1791105321ad3adf092051208d Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 24 Apr 2019 16:43:47 -0700 Subject: [PATCH 17/40] Start of perf iOS --- .../ios/Classes/FLTFirebasePerformance.m | 55 +++++++++++++++++++ .../ios/Classes/FirebasePerformancePlugin.h | 13 +++++ .../ios/Classes/FirebasePerformancePlugin.m | 8 +-- 3 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m diff --git a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m new file mode 100644 index 000000000000..53f7bf3989c9 --- /dev/null +++ b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m @@ -0,0 +1,55 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "FirebasePerformancePlugin.h" + +@interface FLTFirebasePerformance () +@property id binaryMessenger; +@end + +@implementation FLTFirebasePerformance ++ (void)registerWithRegistrar:(nonnull NSObject *)registrar {} + +- (instancetype _Nonnull)initWithMessenger:(NSObject *_Nonnull)messenger { + self = [self init]; + if (self) { + _binaryMessenger = messenger; + } + + return self; +} + +- (instancetype)init { + self = [super init]; + if (self) { + if (![FIRApp appNamed:@"__FIRAPP_DEFAULT"]) { + NSLog(@"Configuring the default Firebase app..."); + [FIRApp configure]; + NSLog(@"Configured the default Firebase app %@.", [FIRApp defaultApp].name); + } + } + + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { + if ([@"FirebasePerformance#isPerformanceCollectionEnabled" isEqualToString:call.method]) { + result(@([[FIRPerformance sharedInstance] isDataCollectionEnabled])); + } else if ([@"FirebasePerformance#setPerformanceCollectionEnabled" isEqualToString:call.method]) { + NSNumber *enable = call.arguments; + [[FIRPerformance sharedInstance] setDataCollectionEnabled:[enable boolValue]]; + result(nil); + } else if ([@"Trace#start" isEqualToString:call.method]) { + [self handleTraceStart:call result:result]; + } else if ([@"Trace#stop" isEqualToString:call.method]) { + [self handleTraceStop:call result:result]; + } else if ([@"HttpMetric#start" isEqualToString:call.method]) { + [self handleHttpMetricStart:call result:result]; + } else if ([@"HttpMetric#stop" isEqualToString:call.method]) { + [self handleHttpMetricStop:call result:result]; + } else { + result(FlutterMethodNotImplemented); + } +} +@end diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h index d71c5351ac8d..ddc56dc80188 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h @@ -1,4 +1,17 @@ +#import #import @interface FLTFirebasePerformancePlugin : NSObject @end + +@interface FLTFirebasePerformance : NSObject +- (instancetype _Nonnull)initWithMessenger:(NSObject *_Nonnull)messenger; +@end + +@interface FLTTrace : NSObject +- (instancetype _Nonnull)initWithTrace:(FIRTrace *_Nonnull)trace; +@end + +@interface FLTHttpMetric : NSObject +- (instancetype _Nonnull)initWithHttpMetric:(FIRHTTPMetric *_Nonnull)metric; +@end diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m index 25073643815e..4a635b771ea9 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m @@ -4,8 +4,6 @@ #import "FirebasePerformancePlugin.h" -#import - @interface FLTFirebasePerformancePlugin () @property(nonatomic, retain) NSMutableDictionary *traces; @property(nonatomic, retain) NSMutableDictionary *httpMetrics; @@ -37,6 +35,7 @@ - (instancetype)init { } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { + /* if ([@"FirebasePerformance#isPerformanceCollectionEnabled" isEqualToString:call.method]) { result(@([[FIRPerformance sharedInstance] isDataCollectionEnabled])); } else if ([@"FirebasePerformance#setPerformanceCollectionEnabled" isEqualToString:call.method]) { @@ -54,8 +53,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } else { result(FlutterMethodNotImplemented); } + */ } - +/* - (void)handleTraceStart:(FlutterMethodCall *)call result:(FlutterResult)result { NSNumber *handle = call.arguments[@"handle"]; NSString *name = call.arguments[@"name"]; @@ -156,5 +156,5 @@ - (void)handleHttpMetricStop:(FlutterMethodCall *)call result:(FlutterResult)res [_httpMetrics removeObjectForKey:handle]; result(nil); } - +*/ @end From f581dd91b9aff0a3ea84a8d96d3c09c72eab3f90 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Thu, 25 Apr 2019 14:55:39 -0700 Subject: [PATCH 18/40] Firebase Performance iOS finish --- .../ios/Classes/FLTFirebasePerformance.m | 98 ++++++++++-- .../ios/Classes/FLTHttpMetric.m | 116 ++++++++++++++ .../ios/Classes/FLTTrace.m | 103 ++++++++++++ .../ios/Classes/FirebasePerformancePlugin.h | 10 +- .../ios/Classes/FirebasePerformancePlugin.m | 148 +----------------- 5 files changed, 311 insertions(+), 164 deletions(-) create mode 100644 packages/firebase_performance/ios/Classes/FLTHttpMetric.m create mode 100644 packages/firebase_performance/ios/Classes/FLTTrace.m diff --git a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m index 53f7bf3989c9..62879def378f 100644 --- a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m +++ b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m @@ -1,20 +1,22 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #import "FirebasePerformancePlugin.h" @interface FLTFirebasePerformance () -@property id binaryMessenger; +@property id registrar; +@property FIRPerformance *performance; @end @implementation FLTFirebasePerformance + (void)registerWithRegistrar:(nonnull NSObject *)registrar {} -- (instancetype _Nonnull)initWithMessenger:(NSObject *_Nonnull)messenger { +- (instancetype _Nonnull)initWithRegistrar:(NSObject *_Nonnull)registrar { self = [self init]; if (self) { - _binaryMessenger = messenger; + _performance = [FIRPerformance sharedInstance]; + _registrar = registrar; } return self; @@ -35,21 +37,85 @@ - (instancetype)init { - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { if ([@"FirebasePerformance#isPerformanceCollectionEnabled" isEqualToString:call.method]) { - result(@([[FIRPerformance sharedInstance] isDataCollectionEnabled])); + [self isPerformanceCollectionEnabled:result]; } else if ([@"FirebasePerformance#setPerformanceCollectionEnabled" isEqualToString:call.method]) { - NSNumber *enable = call.arguments; - [[FIRPerformance sharedInstance] setDataCollectionEnabled:[enable boolValue]]; - result(nil); - } else if ([@"Trace#start" isEqualToString:call.method]) { - [self handleTraceStart:call result:result]; - } else if ([@"Trace#stop" isEqualToString:call.method]) { - [self handleTraceStop:call result:result]; - } else if ([@"HttpMetric#start" isEqualToString:call.method]) { - [self handleHttpMetricStart:call result:result]; - } else if ([@"HttpMetric#stop" isEqualToString:call.method]) { - [self handleHttpMetricStop:call result:result]; + [self setPerformanceCollectionEnabled:call result:result]; + } else if ([@"FirebasePerformance#newTrace" isEqualToString:call.method]) { + [self newTrace:call result:result]; + } else if ([@"FirebasePerformance#newHttpMetric" isEqualToString:call.method]) { + [self newHttpMetric:call result:result]; } else { result(FlutterMethodNotImplemented); } } + +- (void)isPerformanceCollectionEnabled:(FlutterResult)result { + result(@([_performance isDataCollectionEnabled])); +} + +- (void)setPerformanceCollectionEnabled:(FlutterMethodCall *)call result:(FlutterResult)result { + NSNumber *enable = call.arguments; + [_performance setDataCollectionEnabled:[enable boolValue]]; + result(nil); +} + +- (void)newTrace:(FlutterMethodCall *)call result:(FlutterResult)result { + NSString *traceName = call.arguments[@"traceName"]; + FIRTrace *trace = [_performance traceWithName:traceName]; + + NSString *channelName = call.arguments[@"channelName"]; + FlutterMethodChannel* channel = [FlutterMethodChannel + methodChannelWithName:channelName + binaryMessenger:[_registrar messenger]]; + + FLTTrace *delegate = [[FLTTrace alloc] initWithTrace:trace registrar:_registrar channel:channel]; + [_registrar addMethodCallDelegate:delegate channel:channel]; + result(nil); +} + +- (void)newHttpMetric:(FlutterMethodCall *)call result:(FlutterResult)result { + NSString *httpMethod = call.arguments[@"httpMethod"]; + FIRHTTPMethod method = [FLTFirebasePerformance parseHttpMethod:httpMethod]; + + NSString *urlString = call.arguments[@"url"]; + NSURL *url = [NSURL URLWithString:urlString]; + + FIRHTTPMetric *metric = [[FIRHTTPMetric alloc] initWithURL:url HTTPMethod:method]; + + NSString *channelName = call.arguments[@"channelName"]; + FlutterMethodChannel *channel = [FlutterMethodChannel + methodChannelWithName:channelName + binaryMessenger:[_registrar messenger]]; + + FLTHttpMetric *delegate = [[FLTHttpMetric alloc] initWithHTTPMetric:metric + registrar:_registrar + channel:channel]; + [_registrar addMethodCallDelegate:delegate channel:channel]; + result(nil); +} + ++ (FIRHTTPMethod)parseHttpMethod:(NSString *)method { + if ([@"HttpMethod.Connect" isEqualToString:method]) { + return FIRHTTPMethodCONNECT; + } else if ([@"HttpMethod.Delete" isEqualToString:method]) { + return FIRHTTPMethodDELETE; + } else if ([@"HttpMethod.Get" isEqualToString:method]) { + return FIRHTTPMethodGET; + } else if ([@"HttpMethod.Head" isEqualToString:method]) { + return FIRHTTPMethodHEAD; + } else if ([@"HttpMethod.Options" isEqualToString:method]) { + return FIRHTTPMethodOPTIONS; + } else if ([@"HttpMethod.Patch" isEqualToString:method]) { + return FIRHTTPMethodPATCH; + } else if ([@"HttpMethod.Post" isEqualToString:method]) { + return FIRHTTPMethodPOST; + } else if ([@"HttpMethod.Put" isEqualToString:method]) { + return FIRHTTPMethodPUT; + } else if ([@"HttpMethod.Trace" isEqualToString:method]) { + return FIRHTTPMethodTRACE; + } + + NSString *reason = [NSString stringWithFormat:@"Invalid HttpMethod: %@", method]; + @throw [[NSException alloc] initWithName:NSInvalidArgumentException reason:reason userInfo:nil]; +} @end diff --git a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m new file mode 100644 index 000000000000..5d6ca4df6552 --- /dev/null +++ b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m @@ -0,0 +1,116 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "FirebasePerformancePlugin.h" + +@interface FLTHttpMetric () +@property FIRHTTPMetric *metric; +@property id registrar; +@property FlutterMethodChannel *channel; +@end + +@implementation FLTHttpMetric ++ (void)registerWithRegistrar:(nonnull NSObject *)registrar {} + +- (instancetype _Nonnull)initWithHTTPMetric:(FIRHTTPMetric *)metric + registrar:(NSObject *_Nonnull)registrar + channel:(FlutterMethodChannel *)channel { + self = [self init]; + if (self) { + _metric = metric; + _registrar = registrar; + _channel = channel; + } + + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { + if ([@"HttpMetric#start" isEqualToString:call.method]) { + [self start:result]; + } else if ([@"HttpMetric#stop" isEqualToString:call.method]) { + [self stop:result]; + } else if ([@"HttpMetric#httpResponseCode" isEqualToString:call.method]) { + [self setHttpResponseCode:call result:result]; + } else if ([@"HttpMetric#requestPayloadSize" isEqualToString:call.method]) { + [self requestPayloadSize:call result:result]; + } else if ([@"HttpMetric#responseContentType" isEqualToString:call.method]) { + [self responseContentType:call result:result]; + } else if ([@"HttpMetric#responsePayloadSize" isEqualToString:call.method]) { + [self responsePayloadSize:call result:result]; + } else if ([@"HttpMetric#putAttribute" isEqualToString:call.method]) { + [self putAttribute:call result:result]; + } else if ([@"HttpMetric#removeAttribute" isEqualToString:call.method]) { + [self removeAttribute:call result:result]; + } else if ([@"HttpMetric#getAttributes" isEqualToString:call.method]) { + [self getAttributes:result]; + } else { + result(FlutterMethodNotImplemented); + } +} + +- (void)start:(FlutterResult)result { + [_metric start]; + result(nil); +} + +- (void)stop:(FlutterResult)result { + [_metric stop]; + [_registrar addMethodCallDelegate:nil channel:nil]; + result(nil); +} + +- (void)setHttpResponseCode:(FlutterMethodCall *)call result:(FlutterResult)result { + NSNumber *responseCode = call.arguments[@"httpResponseCode"]; + + if (![responseCode isEqual:[NSNull null]]) _metric.responseCode = [responseCode integerValue]; + result(nil); +} + +- (void)requestPayloadSize:(FlutterMethodCall *)call result:(FlutterResult)result { + NSNumber *requestPayloadSize = call.arguments[@"requestPayloadSize"]; + + if (![requestPayloadSize isEqual:[NSNull null]]) { + _metric.requestPayloadSize = [requestPayloadSize longValue]; + } + result(nil); +} + +- (void)responseContentType:(FlutterMethodCall *)call result:(FlutterResult)result { + NSString *responseContentType = call.arguments[@"responseContentType"]; + + if (![responseContentType isEqual:[NSNull null]]) { + _metric.responseContentType = responseContentType; + } + result(nil); +} + +- (void)responsePayloadSize:(FlutterMethodCall *)call result:(FlutterResult)result { + NSNumber *responsePayloadSize = call.arguments[@"responsePayloadSize"]; + + if (![responsePayloadSize isEqual:[NSNull null]]) { + _metric.responsePayloadSize = [responsePayloadSize longValue]; + } + result(nil); +} + +- (void)putAttribute:(FlutterMethodCall *)call result:(FlutterResult)result { + NSString *name = call.arguments[@"name"]; + NSString *value = call.arguments[@"value"]; + + [_metric setValue:value forAttribute:name]; + result(nil); +} + +- (void)removeAttribute:(FlutterMethodCall *)call result:(FlutterResult)result { + NSString *name = call.arguments[@"name"]; + + [_metric removeAttribute:name]; + result(nil); +} + +- (void)getAttributes:(FlutterResult)result { + result(_metric.attributes); +} +@end diff --git a/packages/firebase_performance/ios/Classes/FLTTrace.m b/packages/firebase_performance/ios/Classes/FLTTrace.m new file mode 100644 index 000000000000..72e94a17638c --- /dev/null +++ b/packages/firebase_performance/ios/Classes/FLTTrace.m @@ -0,0 +1,103 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "FirebasePerformancePlugin.h" + +@interface FLTTrace () +@property FIRTrace *trace; +@property id registrar; +@property FlutterMethodChannel *channel; +@end + +@implementation FLTTrace ++ (void)registerWithRegistrar:(nonnull NSObject *)registrar {} + +- (instancetype _Nonnull)initWithTrace:(FIRTrace *)trace + registrar:(NSObject *_Nonnull)registrar + channel:(FlutterMethodChannel *)channel { + self = [self init]; + if (self) { + _registrar = registrar; + _channel = channel; + _trace = trace; + } + + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { + if ([@"Trace#start" isEqualToString:call.method]) { + [self start:result]; + } else if ([@"Trace#stop" isEqualToString:call.method]) { + [self stop:result]; + } else if ([@"Trace#setMetric" isEqualToString:call.method]) { + [self setMetric:call result:result]; + } else if ([@"Trace#incrementMetric" isEqualToString:call.method]) { + [self incrementMetric:call result:result]; + } else if ([@"Trace#getMetric" isEqualToString:call.method]) { + [self getMetric:call result:result]; + } else if ([@"Trace#putAttribute" isEqualToString:call.method]) { + [self putAttribute:call result:result]; + } else if ([@"Trace#removeAttribute" isEqualToString:call.method]) { + [self removeAttribute:call result:result]; + } else if ([@"Trace#getAttributes" isEqualToString:call.method]) { + [self getAttributes:result]; + } else { + result(FlutterMethodNotImplemented); + } +} + +- (void)start:(FlutterResult)result { + [_trace start]; + result(nil); +} + +- (void)stop:(FlutterResult)result { + [_trace stop]; + [_registrar addMethodCallDelegate:nil channel:_channel]; + result(nil); +} + +- (void)setMetric:(FlutterMethodCall *)call result:(FlutterResult)result { + NSString *name = call.arguments[@"name"]; + NSNumber *value = call.arguments[@"value"]; + + [_trace setIntValue:value.longValue forMetric:name]; + result(nil); +} + +- (void)incrementMetric:(FlutterMethodCall *)call result:(FlutterResult)result { + NSString *name = call.arguments[@"name"]; + NSNumber *value = call.arguments[@"value"]; + + [_trace incrementMetric:name byInt:value.longValue]; + result(nil); +} + +- (void)getMetric:(FlutterMethodCall *)call result:(FlutterResult)result { + NSString *name = call.arguments[@"name"]; + + int64_t metric = [_trace valueForIntMetric:name]; + result(@(metric)); +} + +- (void)putAttribute:(FlutterMethodCall *)call result:(FlutterResult)result { + NSString *name = call.arguments[@"name"]; + NSString *value = call.arguments[@"value"]; + + [_trace setValue:value forAttribute:name]; + result(nil); +} + +- (void)removeAttribute:(FlutterMethodCall *)call result:(FlutterResult)result { + NSString *name = call.arguments[@"name"]; + + [_trace removeAttribute:name]; + result(nil); +} + +- (void)getAttributes:(FlutterResult)result { + result(_trace.attributes); +} +@end diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h index ddc56dc80188..8eda01fb8dad 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h @@ -5,13 +5,17 @@ @end @interface FLTFirebasePerformance : NSObject -- (instancetype _Nonnull)initWithMessenger:(NSObject *_Nonnull)messenger; +- (instancetype _Nonnull)initWithRegistrar:(NSObject *_Nonnull)registrar; @end @interface FLTTrace : NSObject -- (instancetype _Nonnull)initWithTrace:(FIRTrace *_Nonnull)trace; +- (instancetype _Nonnull)initWithTrace:(FIRTrace *_Nonnull)trace + registrar:(NSObject *_Nonnull)registrar + channel:(FlutterMethodChannel *_Nonnull)channel; @end @interface FLTHttpMetric : NSObject -- (instancetype _Nonnull)initWithHttpMetric:(FIRHTTPMetric *_Nonnull)metric; +- (instancetype _Nonnull)initWithHTTPMetric:(FIRHTTPMetric *_Nonnull)metric + registrar:(NSObject *_Nonnull)registrar + channel:(FlutterMethodChannel *_Nonnull)channel; @end diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m index 4a635b771ea9..e96ef47e288a 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m @@ -4,157 +4,15 @@ #import "FirebasePerformancePlugin.h" -@interface FLTFirebasePerformancePlugin () -@property(nonatomic, retain) NSMutableDictionary *traces; -@property(nonatomic, retain) NSMutableDictionary *httpMetrics; -@end - @implementation FLTFirebasePerformancePlugin + (void)registerWithRegistrar:(NSObject *)registrar { FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_performance" binaryMessenger:[registrar messenger]]; - FLTFirebasePerformancePlugin *instance = [[FLTFirebasePerformancePlugin alloc] init]; - [registrar addMethodCallDelegate:instance channel:channel]; -} - -- (instancetype)init { - self = [super init]; - if (self) { - if (![FIRApp appNamed:@"__FIRAPP_DEFAULT"]) { - NSLog(@"Configuring the default Firebase app..."); - [FIRApp configure]; - NSLog(@"Configured the default Firebase app %@.", [FIRApp defaultApp].name); - } - - _traces = [[NSMutableDictionary alloc] init]; - _httpMetrics = [[NSMutableDictionary alloc] init]; - } - - return self; -} - -- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { - /* - if ([@"FirebasePerformance#isPerformanceCollectionEnabled" isEqualToString:call.method]) { - result(@([[FIRPerformance sharedInstance] isDataCollectionEnabled])); - } else if ([@"FirebasePerformance#setPerformanceCollectionEnabled" isEqualToString:call.method]) { - NSNumber *enable = call.arguments; - [[FIRPerformance sharedInstance] setDataCollectionEnabled:[enable boolValue]]; - result(nil); - } else if ([@"Trace#start" isEqualToString:call.method]) { - [self handleTraceStart:call result:result]; - } else if ([@"Trace#stop" isEqualToString:call.method]) { - [self handleTraceStop:call result:result]; - } else if ([@"HttpMetric#start" isEqualToString:call.method]) { - [self handleHttpMetricStart:call result:result]; - } else if ([@"HttpMetric#stop" isEqualToString:call.method]) { - [self handleHttpMetricStop:call result:result]; - } else { - result(FlutterMethodNotImplemented); - } - */ -} -/* -- (void)handleTraceStart:(FlutterMethodCall *)call result:(FlutterResult)result { - NSNumber *handle = call.arguments[@"handle"]; - NSString *name = call.arguments[@"name"]; - - FIRTrace *trace = [[FIRPerformance sharedInstance] traceWithName:name]; - [_traces setObject:trace forKey:handle]; - [trace start]; - result(nil); -} - -- (void)handleTraceStop:(FlutterMethodCall *)call result:(FlutterResult)result { - NSNumber *handle = call.arguments[@"handle"]; - FIRTrace *trace = [_traces objectForKey:handle]; - NSDictionary *metrics = call.arguments[@"metrics"]; - [metrics enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSNumber *value, BOOL *stop) { - [trace setIntValue:[value longLongValue] forMetric:key]; - }]; - - NSDictionary *attributes = call.arguments[@"attributes"]; - [attributes enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL *stop) { - [trace setValue:value forAttribute:key]; - }]; - - [trace stop]; - [_traces removeObjectForKey:handle]; - result(nil); -} - -- (void)handleHttpMetricStart:(FlutterMethodCall *)call result:(FlutterResult)result { - NSNumber *handle = call.arguments[@"handle"]; - NSURL *url = [NSURL URLWithString:call.arguments[@"url"]]; - - NSNumber *httpMethod = call.arguments[@"httpMethod"]; - FIRHTTPMethod method; - switch ([httpMethod intValue]) { - case 0: - method = FIRHTTPMethodCONNECT; - break; - case 1: - method = FIRHTTPMethodDELETE; - break; - case 2: - method = FIRHTTPMethodGET; - break; - case 3: - method = FIRHTTPMethodHEAD; - break; - case 4: - method = FIRHTTPMethodOPTIONS; - break; - case 5: - method = FIRHTTPMethodPATCH; - break; - case 6: - method = FIRHTTPMethodPOST; - break; - case 7: - method = FIRHTTPMethodPUT; - break; - case 8: - method = FIRHTTPMethodTRACE; - break; - default: - method = [httpMethod intValue]; - break; - } - - FIRHTTPMetric *metric = [[FIRHTTPMetric alloc] initWithURL:url HTTPMethod:method]; - [_httpMetrics setObject:metric forKey:handle]; - [metric start]; - result(nil); + FLTFirebasePerformance *instance = [[FLTFirebasePerformance alloc] initWithRegistrar:registrar]; + [registrar addMethodCallDelegate:instance channel:channel]; } -- (void)handleHttpMetricStop:(FlutterMethodCall *)call result:(FlutterResult)result { - NSNumber *handle = call.arguments[@"handle"]; - FIRHTTPMetric *metric = [_httpMetrics objectForKey:handle]; - - NSNumber *responseCode = call.arguments[@"httpResponseCode"]; - NSNumber *requestPayloadSize = call.arguments[@"requestPayloadSize"]; - NSString *responseContentType = call.arguments[@"responseContentType"]; - NSNumber *responsePayloadSize = call.arguments[@"responsePayloadSize"]; - - if (![responseCode isEqual:[NSNull null]]) metric.responseCode = [responseCode integerValue]; - if (![requestPayloadSize isEqual:[NSNull null]]) - metric.requestPayloadSize = [requestPayloadSize longValue]; - if (![responseContentType isEqual:[NSNull null]]) - metric.responseContentType = responseContentType; - if (![responsePayloadSize isEqual:[NSNull null]]) - metric.responsePayloadSize = [responsePayloadSize longValue]; - - NSDictionary *attributes = call.arguments[@"attributes"]; - [attributes enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL *stop) { - [metric setValue:value forAttribute:key]; - }]; - - [metric stop]; - [_httpMetrics removeObjectForKey:handle]; - result(nil); -} -*/ +- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {} @end From c07c810b6b5d309ead8d0c96ce951c7df6fa131f Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 29 Apr 2019 21:58:19 -0700 Subject: [PATCH 19/40] Redesign of flutter plugin objects --- .../FirebasePerformancePlugin.java | 52 +++++++++++++++- .../FlutterFirebasePerformance.java | 59 ++++++++++++++++--- .../FlutterHttpMetric.java | 54 +++-------------- .../firebaseperformance/FlutterTrace.java | 28 +++------ 4 files changed, 117 insertions(+), 76 deletions(-) diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FirebasePerformancePlugin.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FirebasePerformancePlugin.java index ad115a499d2f..11748c4162bc 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FirebasePerformancePlugin.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FirebasePerformancePlugin.java @@ -4,15 +4,63 @@ package io.flutter.plugins.firebaseperformance; +import android.util.SparseArray; +import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.PluginRegistry.Registrar; /** FirebasePerformancePlugin */ -public class FirebasePerformancePlugin { +public class FirebasePerformancePlugin implements MethodChannel.MethodCallHandler { private static final String CHANNEL_NAME = "plugins.flutter.io/firebase_performance"; + private static final SparseArray handlers = new SparseArray<>(); + public static void registerWith(Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL_NAME); - channel.setMethodCallHandler(FlutterFirebasePerformance.getInstance(registrar.messenger())); + channel.setMethodCallHandler(new FirebasePerformancePlugin()); + } + + @Override + public void onMethodCall(MethodCall call, MethodChannel.Result result) { + switch (call.method) { + case "FirebasePerformance#instance": + FlutterFirebasePerformance.getInstance(call, result); + break; + case "FirebasePerformance#isPerformanceCollectionEnabled": + case "FirebasePerformance#setPerformanceCollectionEnabled": + case "FirebasePerformance#newTrace": + case "FirebasePerformance#newHttpMetric": + case "Trace#start": + case "Trace#stop": + case "Trace#setMetric": + case "Trace#incrementMetric": + case "Trace#getMetric": + case "PerformanceAttributes#putAttribute": + case "PerformanceAttributes#removeAttribute": + case "PerformanceAttributes#getAttributes": + getHandler(call).onMethodCall(call, result); + break; + default: + result.notImplemented(); + } + } + + static void addHandler(final int handle, final MethodChannel.MethodCallHandler handler) { + if (handlers.get(handle) != null) { + final String message = String.format("Object for handle already exists: %s", handle); + throw new IllegalArgumentException(message); + } + + handlers.put(handle, handler); + } + + static void removeHandler(final int handle) { + handlers.remove(handle); + } + + @SuppressWarnings("ConstantConditions") + private static MethodChannel.MethodCallHandler getHandler(final MethodCall call) { + final Integer handle = call.argument("handle"); + return handlers.get(handle); } } diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java index 9e66cf732f50..312363fd46e7 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java @@ -5,20 +5,47 @@ package io.flutter.plugins.firebaseperformance; import com.google.firebase.perf.FirebasePerformance; -import io.flutter.plugin.common.BinaryMessenger; +import com.google.firebase.perf.metrics.HttpMetric; +import com.google.firebase.perf.metrics.Trace; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; public class FlutterFirebasePerformance implements MethodChannel.MethodCallHandler { - private final BinaryMessenger binaryMessenger; + private static String parseHttpMethod(String httpMethod) { + switch (httpMethod) { + case "HttpMethod.Connect": + return FirebasePerformance.HttpMethod.CONNECT; + case "HttpMethod.Delete": + return FirebasePerformance.HttpMethod.DELETE; + case "HttpMethod.Get": + return FirebasePerformance.HttpMethod.GET; + case "HttpMethod.Head": + return FirebasePerformance.HttpMethod.HEAD; + case "HttpMethod.Options": + return FirebasePerformance.HttpMethod.OPTIONS; + case "HttpMethod.Patch": + return FirebasePerformance.HttpMethod.PATCH; + case "HttpMethod.Post": + return FirebasePerformance.HttpMethod.POST; + case "HttpMethod.Put": + return FirebasePerformance.HttpMethod.PUT; + case "HttpMethod.Trace": + return FirebasePerformance.HttpMethod.TRACE; + default: + throw new IllegalArgumentException(String.format("No HttpMethod for: %s", httpMethod)); + } + } + private final FirebasePerformance performance; - static FlutterFirebasePerformance getInstance(BinaryMessenger messenger) { - return new FlutterFirebasePerformance(messenger); + @SuppressWarnings("ConstantConditions") + static void getInstance(MethodCall call, MethodChannel.Result result) { + final Integer handle = call.argument("handle"); + FirebasePerformancePlugin.addHandler(handle, new FlutterFirebasePerformance()); + result.success(null); } - private FlutterFirebasePerformance(BinaryMessenger messenger) { - this.binaryMessenger = messenger; + private FlutterFirebasePerformance() { this.performance = FirebasePerformance.getInstance(); } @@ -52,11 +79,27 @@ private void setPerformanceCollectionEnabled(MethodCall call, MethodChannel.Resu result.success(null); } + @SuppressWarnings("ConstantConditions") private void newTrace(MethodCall call, MethodChannel.Result result) { - new FlutterTrace(performance, binaryMessenger, call, result); + final String name = call.argument("name"); + final Trace trace = performance.newTrace(name); + + final Integer handle = call.argument("handle"); + FirebasePerformancePlugin.addHandler(handle, new FlutterTrace(trace)); + + result.success(null); } + @SuppressWarnings("ConstantConditions") private void newHttpMetric(MethodCall call, MethodChannel.Result result) { - new FlutterHttpMetric(performance, binaryMessenger, call, result); + final String url = call.argument("url"); + final String httpMethod = call.argument("httpMethod"); + + final HttpMetric metric = performance.newHttpMetric(url, parseHttpMethod(httpMethod)); + + final Integer handle = call.argument("handle"); + FirebasePerformancePlugin.addHandler(handle, new FlutterHttpMetric(metric)); + + result.success(null); } } diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java index 927a94719fea..0fdc99998af4 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java @@ -4,57 +4,16 @@ package io.flutter.plugins.firebaseperformance; -import com.google.firebase.perf.FirebasePerformance; import com.google.firebase.perf.metrics.HttpMetric; -import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; @SuppressWarnings("ConstantConditions") public class FlutterHttpMetric implements MethodChannel.MethodCallHandler { - private static String parseHttpMethod(String httpMethod) { - switch (httpMethod) { - case "HttpMethod.Connect": - return FirebasePerformance.HttpMethod.CONNECT; - case "HttpMethod.Delete": - return FirebasePerformance.HttpMethod.DELETE; - case "HttpMethod.Get": - return FirebasePerformance.HttpMethod.GET; - case "HttpMethod.Head": - return FirebasePerformance.HttpMethod.HEAD; - case "HttpMethod.Options": - return FirebasePerformance.HttpMethod.OPTIONS; - case "HttpMethod.Patch": - return FirebasePerformance.HttpMethod.PATCH; - case "HttpMethod.Post": - return FirebasePerformance.HttpMethod.POST; - case "HttpMethod.Put": - return FirebasePerformance.HttpMethod.PUT; - case "HttpMethod.Trace": - return FirebasePerformance.HttpMethod.TRACE; - default: - throw new IllegalArgumentException(String.format("No HttpMethod for: %s", httpMethod)); - } - } - private final HttpMetric httpMetric; - private final MethodChannel channel; - - FlutterHttpMetric( - FirebasePerformance performance, - BinaryMessenger messenger, - MethodCall call, - MethodChannel.Result result) { - final String channelName = call.argument("channelName"); - final String url = call.argument("url"); - final String httpMethod = call.argument("httpMethod"); - this.httpMetric = performance.newHttpMetric(url, parseHttpMethod(httpMethod)); - - this.channel = new MethodChannel(messenger, channelName); - channel.setMethodCallHandler(this); - - result.success(null); + FlutterHttpMetric(final HttpMetric metric) { + this.httpMetric = metric; } @Override @@ -64,7 +23,7 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) { start(result); break; case "HttpMetric#stop": - stop(result); + stop(call, result); break; case "HttpMetric#httpResponseCode": setHttpResponseCode(call, result); @@ -97,9 +56,12 @@ private void start(MethodChannel.Result result) { result.success(null); } - private void stop(MethodChannel.Result result) { + private void stop(MethodCall call, MethodChannel.Result result) { httpMetric.stop(); - channel.setMethodCallHandler(null); + + final Integer handle = call.argument("handle"); + FirebasePerformancePlugin.removeHandler(handle); + result.success(null); } diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java index e544ffbc8c77..63a469cdcd2f 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java @@ -4,31 +4,16 @@ package io.flutter.plugins.firebaseperformance; -import com.google.firebase.perf.FirebasePerformance; import com.google.firebase.perf.metrics.Trace; -import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; @SuppressWarnings("ConstantConditions") public class FlutterTrace implements MethodChannel.MethodCallHandler { private final Trace trace; - private final MethodChannel channel; - FlutterTrace( - FirebasePerformance performance, - BinaryMessenger messenger, - MethodCall call, - MethodChannel.Result result) { - final String traceName = call.argument("traceName"); - final String channelName = call.argument("channelName"); - - this.trace = performance.newTrace(traceName); - - this.channel = new MethodChannel(messenger, channelName); - channel.setMethodCallHandler(this); - - result.success(null); + FlutterTrace(final Trace trace) { + this.trace = trace; } @Override @@ -38,7 +23,7 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) { start(result); break; case "Trace#stop": - stop(result); + stop(call, result); break; case "Trace#setMetric": setMetric(call, result); @@ -68,9 +53,12 @@ private void start(MethodChannel.Result result) { result.success(null); } - private void stop(MethodChannel.Result result) { + private void stop(MethodCall call, MethodChannel.Result result) { trace.stop(); - channel.setMethodCallHandler(null); + + final Integer handle = call.argument("handle"); + FirebasePerformancePlugin.removeHandler(handle); + result.success(null); } From 7800e5d0d616ca971089598bd49b6827eb745fd3 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 29 Apr 2019 22:41:17 -0700 Subject: [PATCH 20/40] 3rd redesign :( --- .../lib/src/firebase_performance.dart | 40 +++++++++------- .../lib/src/http_metric.dart | 46 +++++++++++++------ .../lib/src/performance_attributes.dart | 18 +++++--- .../firebase_performance/lib/src/trace.dart | 27 ++++++----- 4 files changed, 83 insertions(+), 48 deletions(-) diff --git a/packages/firebase_performance/lib/src/firebase_performance.dart b/packages/firebase_performance/lib/src/firebase_performance.dart index 571e6b8063bd..e2498ec172cb 100644 --- a/packages/firebase_performance/lib/src/firebase_performance.dart +++ b/packages/firebase_performance/lib/src/firebase_performance.dart @@ -11,16 +11,24 @@ enum HttpMethod { Connect, Delete, Get, Head, Options, Patch, Post, Put, Trace } /// /// You can get an instance by calling [FirebasePerformance.instance]. class FirebasePerformance { - FirebasePerformance._(); + FirebasePerformance._(this._handle) { + channel.invokeMethod( + 'FirebasePerformance#instance', + {'handle': _handle}, + ); + } + + static int _nextHandle = 0; + + final int _handle; @visibleForTesting static const MethodChannel channel = MethodChannel('plugins.flutter.io/firebase_performance'); /// Singleton of [FirebasePerformance]. - static final FirebasePerformance instance = FirebasePerformance._(); - - static int _channelCount = 0; + static final FirebasePerformance instance = + FirebasePerformance._(_nextHandle++); /// Determines whether performance monitoring is enabled or disabled. /// @@ -29,7 +37,8 @@ class FirebasePerformance { /// does not reflect whether instrumentation is enabled/disabled. Future isPerformanceCollectionEnabled() { return channel.invokeMethod( - 'FirebasePerformance#isPerformanceCollectionEnabled', + '$FirebasePerformance#isPerformanceCollectionEnabled', + {'handle': _handle}, ); } @@ -39,8 +48,8 @@ class FirebasePerformance { /// application. By default, performance monitoring is enabled. Future setPerformanceCollectionEnabled(bool enable) { return channel.invokeMethod( - 'FirebasePerformance#setPerformanceCollectionEnabled', - enable, + '$FirebasePerformance#setPerformanceCollectionEnabled', + {'handle': _handle, 'enable': enable}, ); } @@ -50,34 +59,31 @@ class FirebasePerformance { /// underscore _ character, and max length of [Trace.maxTraceNameLength] /// characters. Trace newTrace(String name) { - final String channelName = - '${FirebasePerformance.channel.name}/$Trace/${_channelCount++}'; + final int handle = _nextHandle++; FirebasePerformance.channel.invokeMethod( '$FirebasePerformance#newTrace', - {'channelName': channelName, 'traceName': name}, + {'handle': _handle, 'traceHandle': handle, 'name': name}, ); - final MethodChannel channel = MethodChannel(channelName); - return Trace._(channel, name); + return Trace._(handle, name); } /// Creates [HttpMetric] for collecting performance for one request/response. HttpMetric newHttpMetric(String url, HttpMethod httpMethod) { - final String channelName = - '${FirebasePerformance.channel.name}/$HttpMetric/${_channelCount++}'; + final int handle = _nextHandle++; FirebasePerformance.channel.invokeMethod( '$FirebasePerformance#newHttpMetric', { - 'channelName': channelName, + 'handle': _handle, + 'httpMetricHandle': handle, 'url': url, 'httpMethod': httpMethod.toString(), }, ); - final MethodChannel channel = MethodChannel(channelName); - return HttpMetric._(channel); + return HttpMetric._(handle, url, httpMethod); } /// Creates a [Trace] object with given [name] and starts the trace. diff --git a/packages/firebase_performance/lib/src/http_metric.dart b/packages/firebase_performance/lib/src/http_metric.dart index 12ec1dd895f8..a9f54830790b 100644 --- a/packages/firebase_performance/lib/src/http_metric.dart +++ b/packages/firebase_performance/lib/src/http_metric.dart @@ -16,7 +16,10 @@ part of firebase_performance; /// You can confirm that Performance Monitoring results appear in the Firebase /// console. Results should appear within 12 hours. class HttpMetric extends PerformanceAttributes { - HttpMetric._(this.channel); + HttpMetric._(this._handle, this.url, this.httpMethod); + + final String url; + final HttpMethod httpMethod; @override bool _hasStarted = false; @@ -29,9 +32,8 @@ class HttpMetric extends PerformanceAttributes { String _responseContentType; int _responsePayloadSize; - @visibleForTesting @override - final MethodChannel channel; + final int _handle; /// HttpResponse code of the request. int get httpResponseCode => _httpResponseCode; @@ -53,9 +55,12 @@ class HttpMetric extends PerformanceAttributes { if (_hasStopped) return; _httpResponseCode = httpResponseCode; - channel.invokeMethod( + FirebasePerformance.channel.invokeMethod( '$HttpMetric#httpResponseCode', - httpResponseCode, + { + 'handle': _handle, + 'httpResponseCode': httpResponseCode, + }, ); } @@ -67,9 +72,12 @@ class HttpMetric extends PerformanceAttributes { if (_hasStopped) return; _requestPayloadSize = requestPayloadSize; - channel.invokeMethod( + FirebasePerformance.channel.invokeMethod( '$HttpMetric#requestPayloadSize', - requestPayloadSize, + { + 'handle': _handle, + 'requestPayloadSize': requestPayloadSize, + }, ); } @@ -81,9 +89,12 @@ class HttpMetric extends PerformanceAttributes { if (_hasStopped) return; _responseContentType = responseContentType; - channel.invokeMethod( + FirebasePerformance.channel.invokeMethod( '$HttpMetric#responseContentType', - responseContentType, + { + 'handle': _handle, + 'responseContentType': responseContentType, + }, ); } @@ -95,9 +106,12 @@ class HttpMetric extends PerformanceAttributes { if (_hasStopped) return; _responsePayloadSize = responsePayloadSize; - channel.invokeMethod( + FirebasePerformance.channel.invokeMethod( '$HttpMetric#responsePayloadSize', - responsePayloadSize, + { + 'handle': _handle, + 'responsePayloadSize': responsePayloadSize, + }, ); } @@ -111,7 +125,10 @@ class HttpMetric extends PerformanceAttributes { if (_hasStopped) return Future.value(null); _hasStarted = true; - return channel.invokeMethod('$HttpMetric#start'); + return FirebasePerformance.channel.invokeMethod( + '$HttpMetric#start', + {'handle': _handle}, + ); } /// Stops this [HttpMetric]. @@ -126,6 +143,9 @@ class HttpMetric extends PerformanceAttributes { if (_hasStopped) return Future.value(null); _hasStopped = true; - return channel.invokeMethod('$HttpMetric#stop'); + return FirebasePerformance.channel.invokeMethod( + '$HttpMetric#stop', + {'handle': _handle}, + ); } } diff --git a/packages/firebase_performance/lib/src/performance_attributes.dart b/packages/firebase_performance/lib/src/performance_attributes.dart index de2f6452c41d..c12abb499655 100644 --- a/packages/firebase_performance/lib/src/performance_attributes.dart +++ b/packages/firebase_performance/lib/src/performance_attributes.dart @@ -20,8 +20,7 @@ abstract class PerformanceAttributes { bool get _hasStarted; bool get _hasStopped; - @visibleForTesting - MethodChannel get channel; + int get _handle; /// Sets a String [value] for the specified [attribute]. /// @@ -42,9 +41,13 @@ abstract class PerformanceAttributes { } _attributes[attribute] = value; - return channel.invokeMethod( + return FirebasePerformance.channel.invokeMethod( '$PerformanceAttributes#putAttribute', - {'attribute': attribute, 'value': value}, + { + 'handle': _handle, + 'attribute': attribute, + 'value': value, + }, ); } @@ -53,9 +56,9 @@ abstract class PerformanceAttributes { if (!_hasStarted || _hasStopped) return Future.value(null); _attributes.remove(attribute); - return channel.invokeMethod( + return FirebasePerformance.channel.invokeMethod( '$PerformanceAttributes#removeAttribute', - attribute, + {'handle': _handle, 'attribute': attribute}, ); } @@ -67,8 +70,9 @@ abstract class PerformanceAttributes { )); } - return channel.invokeMapMethod( + return FirebasePerformance.channel.invokeMapMethod( '$PerformanceAttributes#getAttributes', + {'handle': _handle}, ); } } diff --git a/packages/firebase_performance/lib/src/trace.dart b/packages/firebase_performance/lib/src/trace.dart index 20e240385eb7..5f8a98ad0151 100644 --- a/packages/firebase_performance/lib/src/trace.dart +++ b/packages/firebase_performance/lib/src/trace.dart @@ -19,7 +19,7 @@ part of firebase_performance; /// You can confirm that Performance Monitoring results appear in the Firebase /// console. Results should appear within 12 hours. class Trace extends PerformanceAttributes { - Trace._(this.channel, this.name); + Trace._(this._handle, this.name); /// Maximum allowed length of the name of a [Trace]. static const int maxTraceNameLength = 100; @@ -32,9 +32,8 @@ class Trace extends PerformanceAttributes { @override bool _hasStopped = false; - @visibleForTesting @override - final MethodChannel channel; + final int _handle; /// Name representing this [Trace] on the Firebase Console. final String name; @@ -49,7 +48,10 @@ class Trace extends PerformanceAttributes { if (_hasStopped) return Future.value(null); _hasStarted = true; - return channel.invokeMethod('$Trace#start'); + return FirebasePerformance.channel.invokeMethod( + '$Trace#start', + {'handle': _handle}, + ); } /// Stops this [Trace]. @@ -64,7 +66,10 @@ class Trace extends PerformanceAttributes { if (_hasStopped) return Future.value(null); _hasStopped = true; - return channel.invokeMethod('$Trace#stop'); + return FirebasePerformance.channel.invokeMethod( + '$Trace#stop', + {'handle': _handle}, + ); } /// Increments the metric with the given [name]. @@ -78,9 +83,9 @@ class Trace extends PerformanceAttributes { } _metrics[name] += value; - return channel.invokeMethod( + return FirebasePerformance.channel.invokeMethod( '$Trace#incrementMetric', - {'name': name, 'value': value}, + {'handle': _handle, 'name': name, 'value': value}, ); } @@ -93,9 +98,9 @@ class Trace extends PerformanceAttributes { if (!_hasStarted || _hasStopped) return Future.value(null); _metrics[name] = value; - return channel.invokeMethod( + return FirebasePerformance.channel.invokeMethod( '$Trace#setMetric', - {'name': name, 'value': value}, + {'handle': _handle, 'name': name, 'value': value}, ); } @@ -106,9 +111,9 @@ class Trace extends PerformanceAttributes { Future getMetric(String name) { if (_hasStopped) return Future.value(_metrics[name] ?? 0); - return channel.invokeMethod( + return FirebasePerformance.channel.invokeMethod( '$Trace#getMetric', - {'name': name}, + {'handle': _handle, 'name': name}, ); } } From f9f05b7dc276bc07bf88af69190479145e68f2f1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 29 Apr 2019 23:01:53 -0700 Subject: [PATCH 21/40] Fix some method calls --- .../FlutterFirebasePerformance.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java index 312363fd46e7..ce04044a1ea8 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterFirebasePerformance.java @@ -73,9 +73,11 @@ private void isPerformanceCollectionEnabled(MethodChannel.Result result) { result.success(performance.isPerformanceCollectionEnabled()); } + @SuppressWarnings("ConstantConditions") private void setPerformanceCollectionEnabled(MethodCall call, MethodChannel.Result result) { - final boolean enabled = (Boolean) call.arguments; - performance.setPerformanceCollectionEnabled(enabled); + final Boolean enable = call.argument("enable"); + performance.setPerformanceCollectionEnabled(enable); + result.success(null); } @@ -84,7 +86,7 @@ private void newTrace(MethodCall call, MethodChannel.Result result) { final String name = call.argument("name"); final Trace trace = performance.newTrace(name); - final Integer handle = call.argument("handle"); + final Integer handle = call.argument("traceHandle"); FirebasePerformancePlugin.addHandler(handle, new FlutterTrace(trace)); result.success(null); @@ -97,7 +99,7 @@ private void newHttpMetric(MethodCall call, MethodChannel.Result result) { final HttpMetric metric = performance.newHttpMetric(url, parseHttpMethod(httpMethod)); - final Integer handle = call.argument("handle"); + final Integer handle = call.argument("httpMetricHandle"); FirebasePerformancePlugin.addHandler(handle, new FlutterHttpMetric(metric)); result.success(null); From 1a35bde6491705e7c6590c3cb4e834ee3722b09d Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 29 Apr 2019 23:38:48 -0700 Subject: [PATCH 22/40] Move ConstantConditions and generic handler call --- .../FirebasePerformancePlugin.java | 31 +++++++------------ .../FlutterHttpMetric.java | 7 ++++- .../firebaseperformance/FlutterTrace.java | 7 ++++- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FirebasePerformancePlugin.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FirebasePerformancePlugin.java index 11748c4162bc..99a1d82d06e1 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FirebasePerformancePlugin.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FirebasePerformancePlugin.java @@ -22,26 +22,16 @@ public static void registerWith(Registrar registrar) { @Override public void onMethodCall(MethodCall call, MethodChannel.Result result) { - switch (call.method) { - case "FirebasePerformance#instance": - FlutterFirebasePerformance.getInstance(call, result); - break; - case "FirebasePerformance#isPerformanceCollectionEnabled": - case "FirebasePerformance#setPerformanceCollectionEnabled": - case "FirebasePerformance#newTrace": - case "FirebasePerformance#newHttpMetric": - case "Trace#start": - case "Trace#stop": - case "Trace#setMetric": - case "Trace#incrementMetric": - case "Trace#getMetric": - case "PerformanceAttributes#putAttribute": - case "PerformanceAttributes#removeAttribute": - case "PerformanceAttributes#getAttributes": - getHandler(call).onMethodCall(call, result); - break; - default: + if (call.method.equals("FirebasePerformance#instance")) { + FlutterFirebasePerformance.getInstance(call, result); + } else { + final MethodChannel.MethodCallHandler handler = getHandler(call); + + if (handler != null) { + handler.onMethodCall(call, result); + } else { result.notImplemented(); + } } } @@ -58,9 +48,10 @@ static void removeHandler(final int handle) { handlers.remove(handle); } - @SuppressWarnings("ConstantConditions") private static MethodChannel.MethodCallHandler getHandler(final MethodCall call) { final Integer handle = call.argument("handle"); + + if (handle == null) return null; return handlers.get(handle); } } diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java index 0fdc99998af4..a6ff761b0df4 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java @@ -8,7 +8,6 @@ import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; -@SuppressWarnings("ConstantConditions") public class FlutterHttpMetric implements MethodChannel.MethodCallHandler { private final HttpMetric httpMetric; @@ -56,6 +55,7 @@ private void start(MethodChannel.Result result) { result.success(null); } + @SuppressWarnings("ConstantConditions") private void stop(MethodCall call, MethodChannel.Result result) { httpMetric.stop(); @@ -65,12 +65,14 @@ private void stop(MethodCall call, MethodChannel.Result result) { result.success(null); } + @SuppressWarnings("ConstantConditions") private void setHttpResponseCode(MethodCall call, MethodChannel.Result result) { final Integer httpResponseCode = call.argument("httpResponseCode"); httpMetric.setHttpResponseCode(httpResponseCode); result.success(null); } + @SuppressWarnings("ConstantConditions") private void setRequestPayloadSize(MethodCall call, MethodChannel.Result result) { final Number payloadSize = call.argument("requestPayloadSize"); httpMetric.setRequestPayloadSize(payloadSize.longValue()); @@ -83,12 +85,14 @@ private void setResponseContentType(MethodCall call, MethodChannel.Result result result.success(null); } + @SuppressWarnings("ConstantConditions") private void setResponsePayloadSize(MethodCall call, MethodChannel.Result result) { final Number payloadSize = call.argument("responsePayloadSize"); httpMetric.setResponsePayloadSize(payloadSize.longValue()); result.success(null); } + @SuppressWarnings("ConstantConditions") private void putAttribute(MethodCall call, MethodChannel.Result result) { final String attribute = call.argument("attribute"); final String value = call.argument("value"); @@ -98,6 +102,7 @@ private void putAttribute(MethodCall call, MethodChannel.Result result) { result.success(null); } + @SuppressWarnings("ConstantConditions") private void removeAttribute(MethodCall call, MethodChannel.Result result) { final String attribute = call.argument("attribute"); httpMetric.removeAttribute(attribute); diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java index 63a469cdcd2f..b9e2fa3fbc6b 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java @@ -8,7 +8,6 @@ import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; -@SuppressWarnings("ConstantConditions") public class FlutterTrace implements MethodChannel.MethodCallHandler { private final Trace trace; @@ -53,6 +52,7 @@ private void start(MethodChannel.Result result) { result.success(null); } + @SuppressWarnings("ConstantConditions") private void stop(MethodCall call, MethodChannel.Result result) { trace.stop(); @@ -62,6 +62,7 @@ private void stop(MethodCall call, MethodChannel.Result result) { result.success(null); } + @SuppressWarnings("ConstantConditions") private void setMetric(MethodCall call, MethodChannel.Result result) { final String name = call.argument("name"); final Number value = call.argument("value"); @@ -70,6 +71,7 @@ private void setMetric(MethodCall call, MethodChannel.Result result) { result.success(null); } + @SuppressWarnings("ConstantConditions") private void incrementMetric(MethodCall call, MethodChannel.Result result) { final String name = call.argument("name"); final Number value = call.argument("value"); @@ -78,12 +80,14 @@ private void incrementMetric(MethodCall call, MethodChannel.Result result) { result.success(null); } + @SuppressWarnings("ConstantConditions") private void getMetric(MethodCall call, MethodChannel.Result result) { final String name = call.argument("name"); result.success(trace.getLongMetric(name)); } + @SuppressWarnings("ConstantConditions") private void putAttribute(MethodCall call, MethodChannel.Result result) { final String attribute = call.argument("attribute"); final String value = call.argument("value"); @@ -93,6 +97,7 @@ private void putAttribute(MethodCall call, MethodChannel.Result result) { result.success(null); } + @SuppressWarnings("ConstantConditions") private void removeAttribute(MethodCall call, MethodChannel.Result result) { final String attribute = call.argument("attribute"); trace.removeAttribute(attribute); From 3e6fe50bc5d2c72019479ab05c1e3c1b36b5dd28 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 1 May 2019 12:18:27 -0700 Subject: [PATCH 23/40] Redesign for iOS --- .../ios/Classes/FLTFirebasePerformance.m | 51 ++++++------------- .../ios/Classes/FLTHttpMetric.m | 17 +++---- .../ios/Classes/FLTTrace.m | 17 +++---- .../ios/Classes/FirebasePerformancePlugin.h | 12 ++--- .../ios/Classes/FirebasePerformancePlugin.m | 51 +++++++++++++++++-- 5 files changed, 81 insertions(+), 67 deletions(-) diff --git a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m index 62879def378f..eff5e62672d1 100644 --- a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m +++ b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m @@ -5,31 +5,21 @@ #import "FirebasePerformancePlugin.h" @interface FLTFirebasePerformance () -@property id registrar; @property FIRPerformance *performance; @end @implementation FLTFirebasePerformance + (void)registerWithRegistrar:(nonnull NSObject *)registrar {} -- (instancetype _Nonnull)initWithRegistrar:(NSObject *_Nonnull)registrar { - self = [self init]; - if (self) { - _performance = [FIRPerformance sharedInstance]; - _registrar = registrar; - } - - return self; ++ (void)sharedInstanceWithCall:(FlutterMethodCall*)call result:(FlutterResult)result { + NSNumber *handle = call.arguments[@"handle"]; + [FLTFirebasePerformancePlugin addMethodHandler:handle methodHandler:[FLTFirebasePerformance new]]; } - (instancetype)init { self = [super init]; if (self) { - if (![FIRApp appNamed:@"__FIRAPP_DEFAULT"]) { - NSLog(@"Configuring the default Firebase app..."); - [FIRApp configure]; - NSLog(@"Configured the default Firebase app %@.", [FIRApp defaultApp].name); - } + _performance = [FIRPerformance sharedInstance]; } return self; @@ -54,43 +44,32 @@ - (void)isPerformanceCollectionEnabled:(FlutterResult)result { } - (void)setPerformanceCollectionEnabled:(FlutterMethodCall *)call result:(FlutterResult)result { - NSNumber *enable = call.arguments; + NSNumber *enable = call.arguments[@"enable"]; [_performance setDataCollectionEnabled:[enable boolValue]]; result(nil); } - (void)newTrace:(FlutterMethodCall *)call result:(FlutterResult)result { - NSString *traceName = call.arguments[@"traceName"]; - FIRTrace *trace = [_performance traceWithName:traceName]; + NSString *name = call.arguments[@"name"]; + FIRTrace *trace = [_performance traceWithName:name]; + FLTTrace *handler = [[FLTTrace alloc] initWithTrace:trace]; - NSString *channelName = call.arguments[@"channelName"]; - FlutterMethodChannel* channel = [FlutterMethodChannel - methodChannelWithName:channelName - binaryMessenger:[_registrar messenger]]; + NSNumber *handle = call.arguments[@"traceHandle"]; + [FLTFirebasePerformancePlugin addMethodHandler:handle methodHandler:handler]; - FLTTrace *delegate = [[FLTTrace alloc] initWithTrace:trace registrar:_registrar channel:channel]; - [_registrar addMethodCallDelegate:delegate channel:channel]; result(nil); } - (void)newHttpMetric:(FlutterMethodCall *)call result:(FlutterResult)result { - NSString *httpMethod = call.arguments[@"httpMethod"]; - FIRHTTPMethod method = [FLTFirebasePerformance parseHttpMethod:httpMethod]; - - NSString *urlString = call.arguments[@"url"]; - NSURL *url = [NSURL URLWithString:urlString]; + FIRHTTPMethod method = [FLTFirebasePerformance parseHttpMethod:call.arguments[@"httpMethod"]]; + NSURL *url = [NSURL URLWithString:call.arguments[@"url"]]; FIRHTTPMetric *metric = [[FIRHTTPMetric alloc] initWithURL:url HTTPMethod:method]; + FLTHttpMetric *handler = [[FLTHttpMetric alloc] initWithHTTPMetric:metric]; - NSString *channelName = call.arguments[@"channelName"]; - FlutterMethodChannel *channel = [FlutterMethodChannel - methodChannelWithName:channelName - binaryMessenger:[_registrar messenger]]; + NSNumber *handle = call.arguments[@"httpMetricHandle"]; + [FLTFirebasePerformancePlugin addMethodHandler:handle methodHandler:handler]; - FLTHttpMetric *delegate = [[FLTHttpMetric alloc] initWithHTTPMetric:metric - registrar:_registrar - channel:channel]; - [_registrar addMethodCallDelegate:delegate channel:channel]; result(nil); } diff --git a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m index 5d6ca4df6552..376c03d7515a 100644 --- a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m +++ b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m @@ -6,21 +6,15 @@ @interface FLTHttpMetric () @property FIRHTTPMetric *metric; -@property id registrar; -@property FlutterMethodChannel *channel; @end @implementation FLTHttpMetric + (void)registerWithRegistrar:(nonnull NSObject *)registrar {} -- (instancetype _Nonnull)initWithHTTPMetric:(FIRHTTPMetric *)metric - registrar:(NSObject *_Nonnull)registrar - channel:(FlutterMethodChannel *)channel { +- (instancetype _Nonnull)initWithHTTPMetric:(FIRHTTPMetric *)metric { self = [self init]; if (self) { _metric = metric; - _registrar = registrar; - _channel = channel; } return self; @@ -30,7 +24,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result if ([@"HttpMetric#start" isEqualToString:call.method]) { [self start:result]; } else if ([@"HttpMetric#stop" isEqualToString:call.method]) { - [self stop:result]; + [self stop:call result:result]; } else if ([@"HttpMetric#httpResponseCode" isEqualToString:call.method]) { [self setHttpResponseCode:call result:result]; } else if ([@"HttpMetric#requestPayloadSize" isEqualToString:call.method]) { @@ -55,9 +49,12 @@ - (void)start:(FlutterResult)result { result(nil); } -- (void)stop:(FlutterResult)result { +- (void)stop:(FlutterMethodCall *)call result:(FlutterResult)result { [_metric stop]; - [_registrar addMethodCallDelegate:nil channel:nil]; + + NSNumber *handle = call.arguments[@"handle"]; + [FLTFirebasePerformancePlugin removeMethodHandler:handle]; + result(nil); } diff --git a/packages/firebase_performance/ios/Classes/FLTTrace.m b/packages/firebase_performance/ios/Classes/FLTTrace.m index 72e94a17638c..9cbd9d274234 100644 --- a/packages/firebase_performance/ios/Classes/FLTTrace.m +++ b/packages/firebase_performance/ios/Classes/FLTTrace.m @@ -6,20 +6,14 @@ @interface FLTTrace () @property FIRTrace *trace; -@property id registrar; -@property FlutterMethodChannel *channel; @end @implementation FLTTrace + (void)registerWithRegistrar:(nonnull NSObject *)registrar {} -- (instancetype _Nonnull)initWithTrace:(FIRTrace *)trace - registrar:(NSObject *_Nonnull)registrar - channel:(FlutterMethodChannel *)channel { +- (instancetype _Nonnull)initWithTrace:(FIRTrace *)trace { self = [self init]; if (self) { - _registrar = registrar; - _channel = channel; _trace = trace; } @@ -30,7 +24,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result if ([@"Trace#start" isEqualToString:call.method]) { [self start:result]; } else if ([@"Trace#stop" isEqualToString:call.method]) { - [self stop:result]; + [self stop:call result:result]; } else if ([@"Trace#setMetric" isEqualToString:call.method]) { [self setMetric:call result:result]; } else if ([@"Trace#incrementMetric" isEqualToString:call.method]) { @@ -53,9 +47,12 @@ - (void)start:(FlutterResult)result { result(nil); } -- (void)stop:(FlutterResult)result { +- (void)stop:(FlutterMethodCall *)call result:(FlutterResult)result { [_trace stop]; - [_registrar addMethodCallDelegate:nil channel:_channel]; + + NSNumber *handle = call.arguments[@"handle"]; + [FLTFirebasePerformancePlugin removeMethodHandler:handle]; + result(nil); } diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h index 8eda01fb8dad..cc5de2523517 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h @@ -2,20 +2,18 @@ #import @interface FLTFirebasePerformancePlugin : NSObject ++ (void)addMethodHandler:(NSNumber *_Nonnull)handle methodHandler:(id_Nonnull)handler; ++ (void)removeMethodHandler:(NSNumber *_Nonnull)handle; @end @interface FLTFirebasePerformance : NSObject -- (instancetype _Nonnull)initWithRegistrar:(NSObject *_Nonnull)registrar; ++ (void)sharedInstanceWithCall:(FlutterMethodCall *_Nonnull)call result:(FlutterResult _Nonnull)result; @end @interface FLTTrace : NSObject -- (instancetype _Nonnull)initWithTrace:(FIRTrace *_Nonnull)trace - registrar:(NSObject *_Nonnull)registrar - channel:(FlutterMethodChannel *_Nonnull)channel; +- (instancetype _Nonnull)initWithTrace:(FIRTrace *_Nonnull)trace; @end @interface FLTHttpMetric : NSObject -- (instancetype _Nonnull)initWithHTTPMetric:(FIRHTTPMetric *_Nonnull)metric - registrar:(NSObject *_Nonnull)registrar - channel:(FlutterMethodChannel *_Nonnull)channel; +- (instancetype _Nonnull)initWithHTTPMetric:(FIRHTTPMetric *_Nonnull)metric; @end diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m index e96ef47e288a..80703623a1fc 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m @@ -5,14 +5,57 @@ #import "FirebasePerformancePlugin.h" @implementation FLTFirebasePerformancePlugin +static NSMutableDictionary> *methodHandlers; + + (void)registerWithRegistrar:(NSObject *)registrar { + methodHandlers = [NSMutableDictionary new]; + FlutterMethodChannel *channel = - [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_performance" - binaryMessenger:[registrar messenger]]; + [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_performance" + binaryMessenger:[registrar messenger]]; - FLTFirebasePerformance *instance = [[FLTFirebasePerformance alloc] initWithRegistrar:registrar]; + FLTFirebasePerformancePlugin *instance = [FLTFirebasePerformancePlugin new]; [registrar addMethodCallDelegate:instance channel:channel]; } -- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {} +- (instancetype)init { + self = [super init]; + if (self) { + if (![FIRApp appNamed:@"__FIRAPP_DEFAULT"]) { + NSLog(@"Configuring the default Firebase app..."); + [FIRApp configure]; + NSLog(@"Configured the default Firebase app %@.", [FIRApp defaultApp].name); + } + } + + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { + if ([@"FirebasePerformance#instance" isEqualToString:call.method]) { + [FLTFirebasePerformance sharedInstanceWithCall:call result:result]; + result(nil); + } else { + NSNumber *handle = call.arguments[@"handle"]; + + if (![handle isEqual:[NSNull null]]) { + [methodHandlers[handle] handleMethodCall:call result:result]; + } else { + result(FlutterMethodNotImplemented); + } + } +} + ++ (void)addMethodHandler:(NSNumber *)handle methodHandler:(id)handler { + if (methodHandlers[handle]) { + NSString *reason = [[NSString alloc] initWithFormat:@"Object for handle already exists: %d", handle.intValue]; + @throw [[NSException alloc] initWithName:NSInvalidArgumentException reason:reason userInfo:nil]; + } + + methodHandlers[handle] = handler; +} + ++ (void)removeMethodHandler:(NSNumber *)handle { + [methodHandlers removeObjectForKey:handle]; +} @end From 21fd8cbdb6a2b043a6a08ab4c6ad510962216fa8 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 1 May 2019 12:28:07 -0700 Subject: [PATCH 24/40] Formatting --- .../ios/Classes/FLTFirebasePerformance.m | 5 +++-- .../firebase_performance/ios/Classes/FLTHttpMetric.m | 3 ++- packages/firebase_performance/ios/Classes/FLTTrace.m | 3 ++- .../ios/Classes/FirebasePerformancePlugin.h | 12 +++++++----- .../ios/Classes/FirebasePerformancePlugin.m | 7 ++++--- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m index eff5e62672d1..7737df7d67a6 100644 --- a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m +++ b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m @@ -9,9 +9,10 @@ @interface FLTFirebasePerformance () @end @implementation FLTFirebasePerformance -+ (void)registerWithRegistrar:(nonnull NSObject *)registrar {} ++ (void)registerWithRegistrar:(nonnull NSObject *)registrar { +} -+ (void)sharedInstanceWithCall:(FlutterMethodCall*)call result:(FlutterResult)result { ++ (void)sharedInstanceWithCall:(FlutterMethodCall *)call result:(FlutterResult)result { NSNumber *handle = call.arguments[@"handle"]; [FLTFirebasePerformancePlugin addMethodHandler:handle methodHandler:[FLTFirebasePerformance new]]; } diff --git a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m index 376c03d7515a..8c0bc1f86b35 100644 --- a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m +++ b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m @@ -9,7 +9,8 @@ @interface FLTHttpMetric () @end @implementation FLTHttpMetric -+ (void)registerWithRegistrar:(nonnull NSObject *)registrar {} ++ (void)registerWithRegistrar:(nonnull NSObject *)registrar { +} - (instancetype _Nonnull)initWithHTTPMetric:(FIRHTTPMetric *)metric { self = [self init]; diff --git a/packages/firebase_performance/ios/Classes/FLTTrace.m b/packages/firebase_performance/ios/Classes/FLTTrace.m index 9cbd9d274234..510e8f5fc135 100644 --- a/packages/firebase_performance/ios/Classes/FLTTrace.m +++ b/packages/firebase_performance/ios/Classes/FLTTrace.m @@ -9,7 +9,8 @@ @interface FLTTrace () @end @implementation FLTTrace -+ (void)registerWithRegistrar:(nonnull NSObject *)registrar {} ++ (void)registerWithRegistrar:(nonnull NSObject *)registrar { +} - (instancetype _Nonnull)initWithTrace:(FIRTrace *)trace { self = [self init]; diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h index cc5de2523517..f50df538a254 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h @@ -2,18 +2,20 @@ #import @interface FLTFirebasePerformancePlugin : NSObject -+ (void)addMethodHandler:(NSNumber *_Nonnull)handle methodHandler:(id_Nonnull)handler; ++ (void)addMethodHandler:(NSNumber *_Nonnull)handle + methodHandler:(id_Nonnull)handler; + (void)removeMethodHandler:(NSNumber *_Nonnull)handle; @end -@interface FLTFirebasePerformance : NSObject -+ (void)sharedInstanceWithCall:(FlutterMethodCall *_Nonnull)call result:(FlutterResult _Nonnull)result; +@interface FLTFirebasePerformance : NSObject ++ (void)sharedInstanceWithCall:(FlutterMethodCall *_Nonnull)call + result:(FlutterResult _Nonnull)result; @end -@interface FLTTrace : NSObject +@interface FLTTrace : NSObject - (instancetype _Nonnull)initWithTrace:(FIRTrace *_Nonnull)trace; @end -@interface FLTHttpMetric : NSObject +@interface FLTHttpMetric : NSObject - (instancetype _Nonnull)initWithHTTPMetric:(FIRHTTPMetric *_Nonnull)metric; @end diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m index 80703623a1fc..82298f0ae970 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m @@ -11,8 +11,8 @@ + (void)registerWithRegistrar:(NSObject *)registrar { methodHandlers = [NSMutableDictionary new]; FlutterMethodChannel *channel = - [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_performance" - binaryMessenger:[registrar messenger]]; + [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_performance" + binaryMessenger:[registrar messenger]]; FLTFirebasePerformancePlugin *instance = [FLTFirebasePerformancePlugin new]; [registrar addMethodCallDelegate:instance channel:channel]; @@ -48,7 +48,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result + (void)addMethodHandler:(NSNumber *)handle methodHandler:(id)handler { if (methodHandlers[handle]) { - NSString *reason = [[NSString alloc] initWithFormat:@"Object for handle already exists: %d", handle.intValue]; + NSString *reason = + [[NSString alloc] initWithFormat:@"Object for handle already exists: %d", handle.intValue]; @throw [[NSException alloc] initWithName:NSInvalidArgumentException reason:reason userInfo:nil]; } From 83aa1a9313718d7cef2fa924be6e2597525138f4 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 1 May 2019 12:49:20 -0700 Subject: [PATCH 25/40] formattinn --- .../ios/Classes/FirebasePerformancePlugin.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h index f50df538a254..3c45bd342866 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h @@ -3,7 +3,7 @@ @interface FLTFirebasePerformancePlugin : NSObject + (void)addMethodHandler:(NSNumber *_Nonnull)handle - methodHandler:(id_Nonnull)handler; + methodHandler:(id _Nonnull)handler; + (void)removeMethodHandler:(NSNumber *_Nonnull)handle; @end From acfa84afd71064be5bb8f921448675a3623c1998 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 1 May 2019 12:59:44 -0700 Subject: [PATCH 26/40] integeration testing --- .../test_driver/firebase_performance.dart | 46 ++++++++++++++----- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/packages/firebase_performance/example/test_driver/firebase_performance.dart b/packages/firebase_performance/example/test_driver/firebase_performance.dart index 295a5da94ad2..98c192bf5ff5 100644 --- a/packages/firebase_performance/example/test_driver/firebase_performance.dart +++ b/packages/firebase_performance/example/test_driver/firebase_performance.dart @@ -25,20 +25,44 @@ void main() { expect(disabled, isFalse); }); - // TODO(bparrishMines): Rewrite integration test when iOS portion is written. - /* - test('metric', () async { + test('trace', () async { final Trace trace = performance.newTrace('test'); - trace.putAttribute('testAttribute', 'foo'); - trace.attributes['testAttribute2'] = 'bar'; + await trace.start(); - trace.incrementMetric('testMetric', 1); + + trace.putAttribute('testAttribute', 'foo'); + final Map attributes = await trace.getAttributes(); + expect(attributes, {'testAttribute': 'foo'}); + + trace.incrementMetric('testMetric', 22); + final int metric = await trace.getMetric('testMetric'); + expect(metric, 22); + + trace.setMetric('testMetric2', 33); + final int metric2 = await trace.getMetric('testMetric2'); + expect(metric2, 33); + await trace.stop(); - expect(trace.getAttribute('testAttribute'), 'foo'); - expect(trace.attributes['testAttribute'], 'foo'); - expect(trace.getAttribute('testAttribute2'), null); - expect(trace.getAttribute('testMetric'), null); }); - */ + + test('httpmetric', () async { + final HttpMetric httpMetric = performance.newHttpMetric( + 'www.google.com', + HttpMethod.Connect, + ); + + await httpMetric.start(); + + httpMetric.putAttribute('testAttribute', 'foo'); + final Map attributes = await httpMetric.getAttributes(); + expect(attributes, {'testAttribute': 'foo'}); + + httpMetric.httpResponseCode = 45; + httpMetric.requestPayloadSize = 45; + httpMetric.responseContentType = 'testString'; + httpMetric.responsePayloadSize = 45; + + await httpMetric.stop(); + }); }); } From 9d8ff822d2d5a132d570f08a30c94f21a4b9745e Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 1 May 2019 13:56:15 -0700 Subject: [PATCH 27/40] Update testing --- .../lib/src/performance_attributes.dart | 18 +- .../firebase_performance/lib/src/trace.dart | 3 +- .../test/firebase_performance_test.dart | 182 ++++++++++-------- 3 files changed, 115 insertions(+), 88 deletions(-) diff --git a/packages/firebase_performance/lib/src/performance_attributes.dart b/packages/firebase_performance/lib/src/performance_attributes.dart index c12abb499655..119567a1eaf0 100644 --- a/packages/firebase_performance/lib/src/performance_attributes.dart +++ b/packages/firebase_performance/lib/src/performance_attributes.dart @@ -22,7 +22,7 @@ abstract class PerformanceAttributes { int get _handle; - /// Sets a String [value] for the specified [attribute]. + /// Sets a String [value] for the specified attribute with [name]. /// /// Updates the value of the attribute if the attribute already exists. /// The maximum number of attributes that can be added are @@ -31,34 +31,34 @@ abstract class PerformanceAttributes { /// Name of the attribute has max length of [maxAttributeKeyLength] /// characters. Value of the attribute has max length of /// [maxAttributeValueLength] characters. - Future putAttribute(String attribute, String value) { + Future putAttribute(String name, String value) { if (!_hasStarted || _hasStopped || - attribute.length > maxAttributeKeyLength || + name.length > maxAttributeKeyLength || value.length > maxAttributeValueLength || _attributes.length == 5) { return Future.value(null); } - _attributes[attribute] = value; + _attributes[name] = value; return FirebasePerformance.channel.invokeMethod( '$PerformanceAttributes#putAttribute', { 'handle': _handle, - 'attribute': attribute, + 'name': name, 'value': value, }, ); } - /// Removes an already added [attribute]. - Future removeAttribute(String attribute) { + /// Removes an already added attribute with [name]. + Future removeAttribute(String name) { if (!_hasStarted || _hasStopped) return Future.value(null); - _attributes.remove(attribute); + _attributes.remove(name); return FirebasePerformance.channel.invokeMethod( '$PerformanceAttributes#removeAttribute', - {'handle': _handle, 'attribute': attribute}, + {'handle': _handle, 'name': name}, ); } diff --git a/packages/firebase_performance/lib/src/trace.dart b/packages/firebase_performance/lib/src/trace.dart index 5f8a98ad0151..f77e0f7a3683 100644 --- a/packages/firebase_performance/lib/src/trace.dart +++ b/packages/firebase_performance/lib/src/trace.dart @@ -78,10 +78,11 @@ class Trace extends PerformanceAttributes { /// not been started or has already been stopped, returns immediately without /// taking action. Future incrementMetric(String name, int value) { - if (!_hasStarted || _hasStopped || _metrics[name] == null) { + if (!_hasStarted || _hasStopped) { return Future.value(null); } + _metrics.putIfAbsent(name, () => 0); _metrics[name] += value; return FirebasePerformance.channel.invokeMethod( '$Trace#incrementMetric', diff --git a/packages/firebase_performance/test/firebase_performance_test.dart b/packages/firebase_performance/test/firebase_performance_test.dart index 7ce36bb65294..c2dbd1997c0a 100644 --- a/packages/firebase_performance/test/firebase_performance_test.dart +++ b/packages/firebase_performance/test/firebase_performance_test.dart @@ -9,10 +9,13 @@ import 'package:flutter_test/flutter_test.dart'; void main() { group('$FirebasePerformance', () { - final FirebasePerformance performance = FirebasePerformance.instance; + FirebasePerformance performance; final List log = []; bool isPerformanceCollectionEnabledResult; + int firebasePerformanceHandle; + int nextHandle = 0; + setUp(() { FirebasePerformance.channel .setMockMethodCallHandler((MethodCall methodCall) async { @@ -27,6 +30,19 @@ void main() { log.clear(); }); + test('instance', () { + firebasePerformanceHandle = nextHandle++; + + performance = FirebasePerformance.instance; + + expect(log, [ + isMethodCall( + 'FirebasePerformance#instance', + arguments: {'handle': firebasePerformanceHandle}, + ), + ]); + }); + test('isPerformanceCollectionEnabled', () async { isPerformanceCollectionEnabledResult = true; final bool enabled = await performance.isPerformanceCollectionEnabled(); @@ -39,11 +55,11 @@ void main() { expect(log, [ isMethodCall( 'FirebasePerformance#isPerformanceCollectionEnabled', - arguments: null, + arguments: {'handle': firebasePerformanceHandle}, ), isMethodCall( 'FirebasePerformance#isPerformanceCollectionEnabled', - arguments: null, + arguments: {'handle': firebasePerformanceHandle}, ), ]); }); @@ -55,24 +71,31 @@ void main() { expect(log, [ isMethodCall( 'FirebasePerformance#setPerformanceCollectionEnabled', - arguments: true, + arguments: { + 'handle': firebasePerformanceHandle, + 'enable': true, + }, ), isMethodCall( 'FirebasePerformance#setPerformanceCollectionEnabled', - arguments: false, + arguments: { + 'handle': firebasePerformanceHandle, + 'enable': false, + }, ), ]); }); test('newTrace', () { - final Trace trace = performance.newTrace('test-trace'); + performance.newTrace('test-trace'); expect(log, [ isMethodCall( 'FirebasePerformance#newTrace', arguments: { - 'channelName': trace.channel.name, - 'traceName': 'test-trace', + 'handle': firebasePerformanceHandle, + 'traceHandle': nextHandle++, + 'name': 'test-trace', }, ), ]); @@ -80,17 +103,14 @@ void main() { test('newHttpMetric', () { final String url = 'https://google.com'; - - final HttpMetric metric = performance.newHttpMetric( - url, - HttpMethod.Connect, - ); + performance.newHttpMetric(url, HttpMethod.Connect); expect(log, [ isMethodCall( 'FirebasePerformance#newHttpMetric', arguments: { - 'channelName': metric.channel.name, + 'handle': firebasePerformanceHandle, + 'httpMetricHandle': nextHandle++, 'url': url, 'httpMethod': HttpMethod.Connect.toString(), }, @@ -102,16 +122,14 @@ void main() { final String url = 'https://google.com'; final HttpMethod method = HttpMethod.Connect; - final HttpMetric metric = performance.newHttpMetric( - 'https://google.com', - method, - ); + performance.newHttpMetric('https://google.com', method); expect(log, [ isMethodCall( 'FirebasePerformance#newHttpMetric', arguments: { - 'channelName': metric.channel.name, + 'handle': firebasePerformanceHandle, + 'httpMetricHandle': nextHandle++, 'url': url, 'httpMethod': method.toString(), }, @@ -121,54 +139,55 @@ void main() { group('$Trace', () { Trace testTrace; - final List traceLog = []; + int currentTestTraceHandle; setUp(() { testTrace = performance.newTrace('test'); - testTrace.channel - .setMockMethodCallHandler((MethodCall methodCall) async { - traceLog.add(methodCall); - switch (methodCall.method) { - case 'FirebasePerformance#isPerformanceCollectionEnabled': - return true; - default: - return null; - } - }); - traceLog.clear(); + currentTestTraceHandle = nextHandle++; + log.clear(); }); test('start', () { testTrace.start(); - expect(traceLog, [ - isMethodCall('Trace#start', arguments: null), + expect(log, [ + isMethodCall( + 'Trace#start', + arguments: {'handle': currentTestTraceHandle}, + ), ]); }); test('stop', () { + testTrace.start(); + log.clear(); + testTrace.stop(); - expect(traceLog, [ - isMethodCall('Trace#stop', arguments: null), + expect(log, [ + isMethodCall( + 'Trace#stop', + arguments: {'handle': currentTestTraceHandle}, + ), ]); }); test('incrementMetric', () { - final String name = 'counter1'; - final int value = 45; - final int increment = 3; - testTrace.start(); - testTrace.setMetric(name, value); - traceLog.clear(); + log.clear(); + final String name = 'metric1'; + final int increment = 3; testTrace.incrementMetric(name, increment); - expect(traceLog, [ + expect(log, [ isMethodCall( 'Trace#incrementMetric', - arguments: {'name': name, 'value': increment}, + arguments: { + 'handle': currentTestTraceHandle, + 'name': name, + 'value': increment, + }, ), ]); }); @@ -176,78 +195,82 @@ void main() { group('$HttpMetric', () { HttpMetric testMetric; - final List httpMetricLog = []; + int currentTestMetricHandle; setUp(() { testMetric = performance.newHttpMetric( 'https://google.com', HttpMethod.Get, ); - testMetric.channel - .setMockMethodCallHandler((MethodCall methodCall) async { - httpMetricLog.add(methodCall); - switch (methodCall.method) { - case 'FirebasePerformance#isPerformanceCollectionEnabled': - return true; - default: - return null; - } - }); - httpMetricLog.clear(); + currentTestMetricHandle = nextHandle++; + log.clear(); }); test('start', () { testMetric.start(); - expect(httpMetricLog, [ - isMethodCall('HttpMetric#start', arguments: null), + expect(log, [ + isMethodCall( + 'HttpMetric#start', + arguments: {'handle': currentTestMetricHandle}, + ), ]); }); test('stop', () { + testMetric.start(); + log.clear(); + testMetric.stop(); - expect(httpMetricLog, [ - isMethodCall('HttpMetric#stop', arguments: null), + expect(log, [ + isMethodCall( + 'HttpMetric#stop', + arguments: {'handle': currentTestMetricHandle}, + ), ]); }); }); group('$PerformanceAttributes', () { Trace attributeTrace; - final List attributeLog = []; + int currentTraceHandle; + final Map getAttributesResult = { 'a1': 'hello', 'a2': 'friend', }; setUp(() { - attributeTrace = performance.newTrace('trace'); - attributeTrace.channel + FirebasePerformance.channel .setMockMethodCallHandler((MethodCall methodCall) async { - attributeLog.add(methodCall); - if (methodCall.method == 'PerformanceAttributes#getAttributes') { - return getAttributesResult; + log.add(methodCall); + switch (methodCall.method) { + case 'PerformanceAttributes#getAttributes': + return getAttributesResult; + default: + return null; } - - return null; }); + attributeTrace = performance.newTrace('trace'); + currentTraceHandle = nextHandle++; attributeTrace.start(); - attributeLog.clear(); + log.clear(); }); test('putAttribute', () { - final String attribute = 'attr1'; + final String name = 'attr1'; final String value = 'apple'; - attributeTrace.putAttribute(attribute, value); + attributeTrace.putAttribute(name, value); - expect(attributeLog, [ + expect(log, [ isMethodCall( 'PerformanceAttributes#putAttribute', arguments: { - 'attribute': attribute, + 'handle': currentTraceHandle, + 'name': name, 'value': value, }, ), @@ -255,13 +278,16 @@ void main() { }); test('removeAttribute', () { - final String attribute = 'attr1'; - attributeTrace.removeAttribute(attribute); + final String name = 'attr1'; + attributeTrace.removeAttribute(name); - expect(attributeLog, [ + expect(log, [ isMethodCall( 'PerformanceAttributes#removeAttribute', - arguments: attribute, + arguments: { + 'handle': currentTraceHandle, + 'name': name, + }, ), ]); }); @@ -269,10 +295,10 @@ void main() { test('getAttributes', () async { final Map result = await attributeTrace.getAttributes(); - expect(attributeLog, [ + expect(log, [ isMethodCall( 'PerformanceAttributes#getAttributes', - arguments: null, + arguments: {'handle': currentTraceHandle}, ), ]); From 2a3f0b2b45f82712dc70c4d0663366cf9753c804 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 1 May 2019 13:57:53 -0700 Subject: [PATCH 28/40] attribute to name --- .../plugins/firebaseperformance/FlutterHttpMetric.java | 8 ++++---- .../flutter/plugins/firebaseperformance/FlutterTrace.java | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java index a6ff761b0df4..2e2f2e6e4ed3 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterHttpMetric.java @@ -94,18 +94,18 @@ private void setResponsePayloadSize(MethodCall call, MethodChannel.Result result @SuppressWarnings("ConstantConditions") private void putAttribute(MethodCall call, MethodChannel.Result result) { - final String attribute = call.argument("attribute"); + final String name = call.argument("name"); final String value = call.argument("value"); - httpMetric.putAttribute(attribute, value); + httpMetric.putAttribute(name, value); result.success(null); } @SuppressWarnings("ConstantConditions") private void removeAttribute(MethodCall call, MethodChannel.Result result) { - final String attribute = call.argument("attribute"); - httpMetric.removeAttribute(attribute); + final String name = call.argument("name"); + httpMetric.removeAttribute(name); result.success(null); } diff --git a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java index b9e2fa3fbc6b..0bcb54f34834 100644 --- a/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java +++ b/packages/firebase_performance/android/src/main/java/io/flutter/plugins/firebaseperformance/FlutterTrace.java @@ -89,18 +89,18 @@ private void getMetric(MethodCall call, MethodChannel.Result result) { @SuppressWarnings("ConstantConditions") private void putAttribute(MethodCall call, MethodChannel.Result result) { - final String attribute = call.argument("attribute"); + final String name = call.argument("name"); final String value = call.argument("value"); - trace.putAttribute(attribute, value); + trace.putAttribute(name, value); result.success(null); } @SuppressWarnings("ConstantConditions") private void removeAttribute(MethodCall call, MethodChannel.Result result) { - final String attribute = call.argument("attribute"); - trace.removeAttribute(attribute); + final String name = call.argument("name"); + trace.removeAttribute(name); result.success(null); } From 96ffe4981bee8c162ebbec472c6ea94b0f6d1940 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 1 May 2019 15:00:33 -0700 Subject: [PATCH 29/40] Fix method call name --- packages/firebase_performance/ios/Classes/FLTHttpMetric.m | 6 +++--- packages/firebase_performance/ios/Classes/FLTTrace.m | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m index 8c0bc1f86b35..af92b59d224d 100644 --- a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m +++ b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m @@ -34,11 +34,11 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [self responseContentType:call result:result]; } else if ([@"HttpMetric#responsePayloadSize" isEqualToString:call.method]) { [self responsePayloadSize:call result:result]; - } else if ([@"HttpMetric#putAttribute" isEqualToString:call.method]) { + } else if ([@"PerformanceAttributes#putAttribute" isEqualToString:call.method]) { [self putAttribute:call result:result]; - } else if ([@"HttpMetric#removeAttribute" isEqualToString:call.method]) { + } else if ([@"PerformanceAttributes#removeAttribute" isEqualToString:call.method]) { [self removeAttribute:call result:result]; - } else if ([@"HttpMetric#getAttributes" isEqualToString:call.method]) { + } else if ([@"PerformanceAttributes#getAttributes" isEqualToString:call.method]) { [self getAttributes:result]; } else { result(FlutterMethodNotImplemented); diff --git a/packages/firebase_performance/ios/Classes/FLTTrace.m b/packages/firebase_performance/ios/Classes/FLTTrace.m index 510e8f5fc135..9336268ba68d 100644 --- a/packages/firebase_performance/ios/Classes/FLTTrace.m +++ b/packages/firebase_performance/ios/Classes/FLTTrace.m @@ -32,11 +32,11 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [self incrementMetric:call result:result]; } else if ([@"Trace#getMetric" isEqualToString:call.method]) { [self getMetric:call result:result]; - } else if ([@"Trace#putAttribute" isEqualToString:call.method]) { + } else if ([@"PerformanceAttributes#putAttribute" isEqualToString:call.method]) { [self putAttribute:call result:result]; - } else if ([@"Trace#removeAttribute" isEqualToString:call.method]) { + } else if ([@"PerformanceAttributes#removeAttribute" isEqualToString:call.method]) { [self removeAttribute:call result:result]; - } else if ([@"Trace#getAttributes" isEqualToString:call.method]) { + } else if ([@"PerformanceAttributes#getAttributes" isEqualToString:call.method]) { [self getAttributes:result]; } else { result(FlutterMethodNotImplemented); From ecd0addcad64f0367017bfa8b3c75da6dbe6e876 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 1 May 2019 15:59:29 -0700 Subject: [PATCH 30/40] use block notation --- packages/firebase_performance/ios/Classes/FLTHttpMetric.m | 2 +- packages/firebase_performance/ios/Classes/FLTTrace.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m index af92b59d224d..64a622aeb2d7 100644 --- a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m +++ b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m @@ -109,6 +109,6 @@ - (void)removeAttribute:(FlutterMethodCall *)call result:(FlutterResult)result { } - (void)getAttributes:(FlutterResult)result { - result(_metric.attributes); + result([_metric attributes]); } @end diff --git a/packages/firebase_performance/ios/Classes/FLTTrace.m b/packages/firebase_performance/ios/Classes/FLTTrace.m index 9336268ba68d..a522e3d38a39 100644 --- a/packages/firebase_performance/ios/Classes/FLTTrace.m +++ b/packages/firebase_performance/ios/Classes/FLTTrace.m @@ -96,6 +96,6 @@ - (void)removeAttribute:(FlutterMethodCall *)call result:(FlutterResult)result { } - (void)getAttributes:(FlutterResult)result { - result(_trace.attributes); + result([_trace attributes]); } @end From f1b7a7e5c597e9377dbfa5362f22f9e4a0fb5bf8 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 1 May 2019 16:51:26 -0700 Subject: [PATCH 31/40] Missed https:// --- .../example/test_driver/firebase_performance.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_performance/example/test_driver/firebase_performance.dart b/packages/firebase_performance/example/test_driver/firebase_performance.dart index 98c192bf5ff5..ae6d62069690 100644 --- a/packages/firebase_performance/example/test_driver/firebase_performance.dart +++ b/packages/firebase_performance/example/test_driver/firebase_performance.dart @@ -47,7 +47,7 @@ void main() { test('httpmetric', () async { final HttpMetric httpMetric = performance.newHttpMetric( - 'www.google.com', + 'https://www.google.com', HttpMethod.Connect, ); From d6f25191769e53543cb037815dd73b880d892d1e Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 1 May 2019 16:58:37 -0700 Subject: [PATCH 32/40] Temporarily remove integration tests --- packages/firebase_performance/example/lib/main.dart | 1 - .../example/test_driver/firebase_performance.dart | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/firebase_performance/example/lib/main.dart b/packages/firebase_performance/example/lib/main.dart index 61e1ae39b6e7..16ed5b4322ee 100644 --- a/packages/firebase_performance/example/lib/main.dart +++ b/packages/firebase_performance/example/lib/main.dart @@ -77,7 +77,6 @@ class _MyAppState extends State { }); final Trace trace = _performance.newTrace("test"); - trace.incrementMetric("metric1", 16); trace.putAttribute("favorite_color", "blue"); diff --git a/packages/firebase_performance/example/test_driver/firebase_performance.dart b/packages/firebase_performance/example/test_driver/firebase_performance.dart index 295a5da94ad2..352db529bd1b 100644 --- a/packages/firebase_performance/example/test_driver/firebase_performance.dart +++ b/packages/firebase_performance/example/test_driver/firebase_performance.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:firebase_performance/firebase_performance.dart'; void main() { final Completer completer = Completer(); @@ -10,6 +9,8 @@ void main() { tearDownAll(() => completer.complete(null)); group('firebase_performance test driver', () { + // TODO(bparrishMines): Rewrite integration tests when iOS portion is written. + /* final FirebasePerformance performance = FirebasePerformance.instance; setUp(() async { @@ -25,8 +26,6 @@ void main() { expect(disabled, isFalse); }); - // TODO(bparrishMines): Rewrite integration test when iOS portion is written. - /* test('metric', () async { final Trace trace = performance.newTrace('test'); trace.putAttribute('testAttribute', 'foo'); From 7f96745e5037ad29dc125655333d74dd111b4f5d Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 1 May 2019 17:04:12 -0700 Subject: [PATCH 33/40] Temporarily remove integration tests --- .../example/test_driver/firebase_performance.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/firebase_performance/example/test_driver/firebase_performance.dart b/packages/firebase_performance/example/test_driver/firebase_performance.dart index fcabfe11f239..352db529bd1b 100644 --- a/packages/firebase_performance/example/test_driver/firebase_performance.dart +++ b/packages/firebase_performance/example/test_driver/firebase_performance.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:firebase_performance/firebase_performance.dart'; void main() { final Completer completer = Completer(); @@ -10,6 +9,8 @@ void main() { tearDownAll(() => completer.complete(null)); group('firebase_performance test driver', () { + // TODO(bparrishMines): Rewrite integration tests when iOS portion is written. + /* final FirebasePerformance performance = FirebasePerformance.instance; setUp(() async { @@ -37,5 +38,6 @@ void main() { expect(trace.getAttribute('testAttribute2'), null); expect(trace.getAttribute('testMetric'), null); }); + */ }); } From 52f04b8d3dcfabf53f909006f4afdad7be7d1904 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Sun, 5 May 2019 22:38:34 -0700 Subject: [PATCH 34/40] Make sharedInstance a constructor --- .../ios/Classes/FLTFirebasePerformance.m | 20 ++++++++----------- .../ios/Classes/FirebasePerformancePlugin.h | 3 +-- .../ios/Classes/FirebasePerformancePlugin.m | 5 ++++- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m index 7737df7d67a6..b8869e03d9f0 100644 --- a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m +++ b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m @@ -12,18 +12,14 @@ @implementation FLTFirebasePerformance + (void)registerWithRegistrar:(nonnull NSObject *)registrar { } -+ (void)sharedInstanceWithCall:(FlutterMethodCall *)call result:(FlutterResult)result { - NSNumber *handle = call.arguments[@"handle"]; - [FLTFirebasePerformancePlugin addMethodHandler:handle methodHandler:[FLTFirebasePerformance new]]; -} - -- (instancetype)init { - self = [super init]; - if (self) { - _performance = [FIRPerformance sharedInstance]; - } - - return self; ++ (instancetype _Nonnull)sharedInstance { + static FLTFirebasePerformance *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FLTFirebasePerformance alloc] init]; + sharedInstance.performance = [FIRPerformance sharedInstance]; + }); + return sharedInstance; } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h index 3c45bd342866..17e20b5dfa21 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h @@ -8,8 +8,7 @@ @end @interface FLTFirebasePerformance : NSObject -+ (void)sharedInstanceWithCall:(FlutterMethodCall *_Nonnull)call - result:(FlutterResult _Nonnull)result; ++ (instancetype _Nonnull)sharedInstance; @end @interface FLTTrace : NSObject diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m index 82298f0ae970..a88409b01e6f 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m @@ -33,7 +33,10 @@ - (instancetype)init { - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { if ([@"FirebasePerformance#instance" isEqualToString:call.method]) { - [FLTFirebasePerformance sharedInstanceWithCall:call result:result]; + NSNumber *handle = call.arguments[@"handle"]; + FLTFirebasePerformance performance = [FLTFirebasePerformance sharedInstance]; + + [FLTFirebasePerformancePlugin addMethodHandler:handle methodHandler:performance]; result(nil); } else { NSNumber *handle = call.arguments[@"handle"]; From fda650fed83d25b32845b3dea950bb0b805bd1b0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Sun, 5 May 2019 23:28:53 -0700 Subject: [PATCH 35/40] Update FirebasePerformancePlugin.m --- .../ios/Classes/FirebasePerformancePlugin.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m index a88409b01e6f..606d683067bb 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m @@ -34,7 +34,7 @@ - (instancetype)init { - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { if ([@"FirebasePerformance#instance" isEqualToString:call.method]) { NSNumber *handle = call.arguments[@"handle"]; - FLTFirebasePerformance performance = [FLTFirebasePerformance sharedInstance]; + FLTFirebasePerformance *performance = [FLTFirebasePerformance sharedInstance]; [FLTFirebasePerformancePlugin addMethodHandler:handle methodHandler:performance]; result(nil); From c02398541842b8af1e924307bab7647d8e4930cd Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Sun, 5 May 2019 23:30:09 -0700 Subject: [PATCH 36/40] Update FirebasePerformancePlugin.m --- .../ios/Classes/FirebasePerformancePlugin.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m index a88409b01e6f..606d683067bb 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m @@ -34,7 +34,7 @@ - (instancetype)init { - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { if ([@"FirebasePerformance#instance" isEqualToString:call.method]) { NSNumber *handle = call.arguments[@"handle"]; - FLTFirebasePerformance performance = [FLTFirebasePerformance sharedInstance]; + FLTFirebasePerformance *performance = [FLTFirebasePerformance sharedInstance]; [FLTFirebasePerformancePlugin addMethodHandler:handle methodHandler:performance]; result(nil); From 71ad2ea0b861e838b8d737c67c35a15637be64b2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 7 May 2019 11:53:41 -0700 Subject: [PATCH 37/40] Create internal methods --- .../ios/Classes/FLTFirebasePerformance.m | 2 +- .../ios/Classes/FLTHttpMetric.m | 2 +- .../ios/Classes/FLTTrace.m | 2 +- .../FirebasePerformancePlugin+Internal.h | 23 +++++++++++++++++++ .../ios/Classes/FirebasePerformancePlugin.h | 15 ------------ .../ios/Classes/FirebasePerformancePlugin.m | 2 +- 6 files changed, 27 insertions(+), 19 deletions(-) create mode 100644 packages/firebase_performance/ios/Classes/FirebasePerformancePlugin+Internal.h diff --git a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m index b8869e03d9f0..ab8a60b552fb 100644 --- a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m +++ b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "FirebasePerformancePlugin.h" +#import "FirebasePerformancePlugin+Internal.h" @interface FLTFirebasePerformance () @property FIRPerformance *performance; diff --git a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m index 64a622aeb2d7..6140cb348d3f 100644 --- a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m +++ b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "FirebasePerformancePlugin.h" +#import "FirebasePerformancePlugin+Internal.h" @interface FLTHttpMetric () @property FIRHTTPMetric *metric; diff --git a/packages/firebase_performance/ios/Classes/FLTTrace.m b/packages/firebase_performance/ios/Classes/FLTTrace.m index a522e3d38a39..f4baa6ba2738 100644 --- a/packages/firebase_performance/ios/Classes/FLTTrace.m +++ b/packages/firebase_performance/ios/Classes/FLTTrace.m @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "FirebasePerformancePlugin.h" +#import "FirebasePerformancePlugin+Internal.h" @interface FLTTrace () @property FIRTrace *trace; diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin+Internal.h b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin+Internal.h new file mode 100644 index 000000000000..8c25eeec53fd --- /dev/null +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin+Internal.h @@ -0,0 +1,23 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "FirebasePerformancePlugin.h" + +@interface FLTFirebasePerformancePlugin (Internal) ++ (void)addMethodHandler:(NSNumber *_Nonnull)handle + methodHandler:(id _Nonnull)handler; ++ (void)removeMethodHandler:(NSNumber *_Nonnull)handle; +@end + +@interface FLTFirebasePerformance : NSObject ++ (instancetype _Nonnull)sharedInstance; +@end + +@interface FLTTrace : NSObject +- (instancetype _Nonnull)initWithTrace:(FIRTrace *_Nonnull)trace; +@end + +@interface FLTHttpMetric : NSObject +- (instancetype _Nonnull)initWithHTTPMetric:(FIRHTTPMetric *_Nonnull)metric; +@end diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h index 17e20b5dfa21..44bf53592eb9 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.h @@ -2,19 +2,4 @@ #import @interface FLTFirebasePerformancePlugin : NSObject -+ (void)addMethodHandler:(NSNumber *_Nonnull)handle - methodHandler:(id _Nonnull)handler; -+ (void)removeMethodHandler:(NSNumber *_Nonnull)handle; -@end - -@interface FLTFirebasePerformance : NSObject -+ (instancetype _Nonnull)sharedInstance; -@end - -@interface FLTTrace : NSObject -- (instancetype _Nonnull)initWithTrace:(FIRTrace *_Nonnull)trace; -@end - -@interface FLTHttpMetric : NSObject -- (instancetype _Nonnull)initWithHTTPMetric:(FIRHTTPMetric *_Nonnull)metric; @end diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m index 606d683067bb..2c2c8fa7efcf 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "FirebasePerformancePlugin.h" +#import "FirebasePerformancePlugin+Internal.h" @implementation FLTFirebasePerformancePlugin static NSMutableDictionary> *methodHandlers; From 58f736d51e8908beb35a84c5e10fe6b31adcb813 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 7 May 2019 12:12:54 -0700 Subject: [PATCH 38/40] testin --- packages/firebase_performance/example/pubspec.yaml | 2 -- .../example/test_driver/firebase_performance.dart | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/firebase_performance/example/pubspec.yaml b/packages/firebase_performance/example/pubspec.yaml index ef9440d129f5..2c6ba939aa4b 100644 --- a/packages/firebase_performance/example/pubspec.yaml +++ b/packages/firebase_performance/example/pubspec.yaml @@ -17,7 +17,5 @@ dev_dependencies: sdk: flutter test: any - - flutter: uses-material-design: true diff --git a/packages/firebase_performance/example/test_driver/firebase_performance.dart b/packages/firebase_performance/example/test_driver/firebase_performance.dart index 3e52f2f4583b..ae6d62069690 100644 --- a/packages/firebase_performance/example/test_driver/firebase_performance.dart +++ b/packages/firebase_performance/example/test_driver/firebase_performance.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:firebase_performance/firebase_performance.dart'; void main() { final Completer completer = Completer(); @@ -9,8 +10,6 @@ void main() { tearDownAll(() => completer.complete(null)); group('firebase_performance test driver', () { - // TODO(bparrishMines): Rewrite integration tests when iOS portion is written. - /* final FirebasePerformance performance = FirebasePerformance.instance; setUp(() async { @@ -65,6 +64,5 @@ void main() { await httpMetric.stop(); }); - */ }); } From 21a67f8f7c4bebb00c46e52861f50e984500a1ef Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Thu, 9 May 2019 13:11:53 -0700 Subject: [PATCH 39/40] Use MethodCallHandler protocol --- .../ios/Classes/FLTFirebasePerformance.m | 3 --- .../ios/Classes/FLTHttpMetric.m | 3 --- .../firebase_performance/ios/Classes/FLTTrace.m | 3 --- .../Classes/FirebasePerformancePlugin+Internal.h | 13 +++++++++---- .../ios/Classes/FirebasePerformancePlugin.m | 4 ++-- 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m index ab8a60b552fb..81cf29c06559 100644 --- a/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m +++ b/packages/firebase_performance/ios/Classes/FLTFirebasePerformance.m @@ -9,9 +9,6 @@ @interface FLTFirebasePerformance () @end @implementation FLTFirebasePerformance -+ (void)registerWithRegistrar:(nonnull NSObject *)registrar { -} - + (instancetype _Nonnull)sharedInstance { static FLTFirebasePerformance *sharedInstance = nil; static dispatch_once_t onceToken; diff --git a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m index 6140cb348d3f..3a12f3400613 100644 --- a/packages/firebase_performance/ios/Classes/FLTHttpMetric.m +++ b/packages/firebase_performance/ios/Classes/FLTHttpMetric.m @@ -9,9 +9,6 @@ @interface FLTHttpMetric () @end @implementation FLTHttpMetric -+ (void)registerWithRegistrar:(nonnull NSObject *)registrar { -} - - (instancetype _Nonnull)initWithHTTPMetric:(FIRHTTPMetric *)metric { self = [self init]; if (self) { diff --git a/packages/firebase_performance/ios/Classes/FLTTrace.m b/packages/firebase_performance/ios/Classes/FLTTrace.m index f4baa6ba2738..3ce6af5fc3ef 100644 --- a/packages/firebase_performance/ios/Classes/FLTTrace.m +++ b/packages/firebase_performance/ios/Classes/FLTTrace.m @@ -9,9 +9,6 @@ @interface FLTTrace () @end @implementation FLTTrace -+ (void)registerWithRegistrar:(nonnull NSObject *)registrar { -} - - (instancetype _Nonnull)initWithTrace:(FIRTrace *)trace { self = [self init]; if (self) { diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin+Internal.h b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin+Internal.h index 8c25eeec53fd..f0adca5b905b 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin+Internal.h +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin+Internal.h @@ -4,20 +4,25 @@ #import "FirebasePerformancePlugin.h" +@protocol MethodCallHandler +@required +- (void)handleMethodCall:(FlutterMethodCall *_Nonnull)call result:(FlutterResult _Nonnull)result; +@end + @interface FLTFirebasePerformancePlugin (Internal) + (void)addMethodHandler:(NSNumber *_Nonnull)handle - methodHandler:(id _Nonnull)handler; + methodHandler:(id _Nonnull)handler; + (void)removeMethodHandler:(NSNumber *_Nonnull)handle; @end -@interface FLTFirebasePerformance : NSObject +@interface FLTFirebasePerformance : NSObject + (instancetype _Nonnull)sharedInstance; @end -@interface FLTTrace : NSObject +@interface FLTTrace : NSObject - (instancetype _Nonnull)initWithTrace:(FIRTrace *_Nonnull)trace; @end -@interface FLTHttpMetric : NSObject +@interface FLTHttpMetric : NSObject - (instancetype _Nonnull)initWithHTTPMetric:(FIRHTTPMetric *_Nonnull)metric; @end diff --git a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m index 2c2c8fa7efcf..1c387265c988 100644 --- a/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m +++ b/packages/firebase_performance/ios/Classes/FirebasePerformancePlugin.m @@ -5,7 +5,7 @@ #import "FirebasePerformancePlugin+Internal.h" @implementation FLTFirebasePerformancePlugin -static NSMutableDictionary> *methodHandlers; +static NSMutableDictionary> *methodHandlers; + (void)registerWithRegistrar:(NSObject *)registrar { methodHandlers = [NSMutableDictionary new]; @@ -49,7 +49,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } } -+ (void)addMethodHandler:(NSNumber *)handle methodHandler:(id)handler { ++ (void)addMethodHandler:(NSNumber *)handle methodHandler:(id)handler { if (methodHandlers[handle]) { NSString *reason = [[NSString alloc] initWithFormat:@"Object for handle already exists: %d", handle.intValue]; From a04ef6ad7801a69e216398e425ede3c5098dc525 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Thu, 9 May 2019 13:37:58 -0700 Subject: [PATCH 40/40] Add note about leaking --- packages/firebase_performance/lib/src/http_metric.dart | 5 ++++- packages/firebase_performance/lib/src/trace.dart | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/firebase_performance/lib/src/http_metric.dart b/packages/firebase_performance/lib/src/http_metric.dart index a9f54830790b..c0b27bb41ce3 100644 --- a/packages/firebase_performance/lib/src/http_metric.dart +++ b/packages/firebase_performance/lib/src/http_metric.dart @@ -8,13 +8,16 @@ part of firebase_performance; /// /// It is possible to have more than one [HttpMetric] running at a time. /// Attributes can also be added to help measure performance related events. A -/// [HttpMetric] also measures the time between calling start() and stop(). +/// [HttpMetric] also measures the time between calling `start()` and `stop()`. /// /// Data collected is automatically sent to the associated Firebase console /// after stop() is called. /// /// You can confirm that Performance Monitoring results appear in the Firebase /// console. Results should appear within 12 hours. +/// +/// It is highly recommended that one always calls `start()` and `stop()` on +/// each created [HttpMetric] to avoid leaking on the platform side. class HttpMetric extends PerformanceAttributes { HttpMetric._(this._handle, this.url, this.httpMethod); diff --git a/packages/firebase_performance/lib/src/trace.dart b/packages/firebase_performance/lib/src/trace.dart index f77e0f7a3683..cf8e1fb01d3a 100644 --- a/packages/firebase_performance/lib/src/trace.dart +++ b/packages/firebase_performance/lib/src/trace.dart @@ -11,13 +11,16 @@ part of firebase_performance; /// possible to have more than one custom trace running at a time. Each custom /// trace can have multiple metrics and attributes added to help measure /// performance related events. A trace also measures the time between calling -/// start() and stop(). +/// `start()` and `stop()`. /// /// Data collected is automatically sent to the associated Firebase console /// after stop() is called. /// /// You can confirm that Performance Monitoring results appear in the Firebase /// console. Results should appear within 12 hours. +/// +/// It is highly recommended that one always calls `start()` and `stop()` on +/// each created [Trace] to not avoid leaking on the platform side. class Trace extends PerformanceAttributes { Trace._(this._handle, this.name);