Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
[firebase_performance] Refactor and API update of firebase_performance (
Browse files Browse the repository at this point in the history
  • Loading branch information
bparrishMines committed May 14, 2019
1 parent 7346a50 commit 90ed52d
Show file tree
Hide file tree
Showing 18 changed files with 1,177 additions and 680 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,160 +5,53 @@
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;
public class FirebasePerformancePlugin implements MethodChannel.MethodCallHandler {
private static final String CHANNEL_NAME = "plugins.flutter.io/firebase_performance";

private final SparseArray<Trace> traces = new SparseArray<>();
private final SparseArray<HttpMetric> httpMetrics = new SparseArray<>();
private static final SparseArray<MethodChannel.MethodCallHandler> handlers = new SparseArray<>();

public static void registerWith(Registrar registrar) {
final MethodChannel channel =
new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_performance");
final MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL_NAME);
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:
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
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();
}
}
}

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<String, Integer> metrics = call.argument("metrics");
for (Map.Entry<String, Integer> entry : metrics.entrySet()) {
trace.incrementMetric(entry.getKey(), entry.getValue());
}

Map<String, String> attributes = call.argument("attributes");
for (Map.Entry<String, String> entry : attributes.entrySet()) {
trace.putAttribute(entry.getKey(), entry.getValue());
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);
}

trace.stop();
traces.remove(handle);
result.success(null);
handlers.put(handle, handler);
}

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);
static void removeHandler(final int handle) {
handlers.remove(handle);
}

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<String, String> attributes = call.argument("attributes");
for (Map.Entry<String, String> entry : attributes.entrySet()) {
metric.putAttribute(entry.getKey(), entry.getValue());
}
private static MethodChannel.MethodCallHandler getHandler(final MethodCall call) {
final Integer handle = call.argument("handle");

metric.stop();
httpMetrics.remove(handle);
result.success(null);
if (handle == null) return null;
return handlers.get(handle);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// 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.

package io.flutter.plugins.firebaseperformance;

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;

public class FlutterFirebasePerformance 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 FirebasePerformance performance;

@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() {
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, result);
break;
case "FirebasePerformance#newTrace":
newTrace(call, result);
break;
case "FirebasePerformance#newHttpMetric":
newHttpMetric(call, result);
break;
default:
result.notImplemented();
}
}

private void isPerformanceCollectionEnabled(MethodChannel.Result result) {
result.success(performance.isPerformanceCollectionEnabled());
}

@SuppressWarnings("ConstantConditions")
private void setPerformanceCollectionEnabled(MethodCall call, MethodChannel.Result result) {
final Boolean enable = call.argument("enable");
performance.setPerformanceCollectionEnabled(enable);

result.success(null);
}

@SuppressWarnings("ConstantConditions")
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("traceHandle");
FirebasePerformancePlugin.addHandler(handle, new FlutterTrace(trace));

result.success(null);
}

@SuppressWarnings("ConstantConditions")
private void newHttpMetric(MethodCall call, MethodChannel.Result 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("httpMetricHandle");
FirebasePerformancePlugin.addHandler(handle, new FlutterHttpMetric(metric));

result.success(null);
}
}
Loading

4 comments on commit 90ed52d

@sinaso
Copy link

@sinaso sinaso commented on 90ed52d Jun 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason behind using say "$FirebasePerformance#newHttpMetric" instead of "FirebasePerformance$newHttpMetric" (note the dollar sign) in strings? I am getting errors in production apk, when obfuscation is enabled, since the the class names are replaced with obfuscated ones.

Is there a way I can disable obfuscation for a plugin?
thanks!

@bparrishMines
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason behind using say "$FirebasePerformance#newHttpMetric" instead of "FirebasePerformance$newHttpMetric" (note the dollar sign) in strings? I am getting errors in production apk, when obfuscation is enabled, since the the class names are replaced with obfuscated ones.

Is there a way I can disable obfuscation for a plugin?
thanks!

Hi @sinaso, I typically use $FirebasePerformance#newHttpMetric because it makes it easier to update the method channels if a class changes names. A few plugins use this format, but if it causes problems with obfuscating dart code, we may move away from that format.

I'm not aware of a way to disable it only for plugins.

I created an issue to track this: flutter/flutter#35764

@sinaso
Copy link

@sinaso sinaso commented on 90ed52d Jul 8, 2019 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@axel-op
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sinaso This is fixed in the last version of the plugin. See #1874

Please sign in to comment.