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

Add Metrics #27

Merged
merged 3 commits into from Feb 9, 2018
Merged

Add Metrics #27

merged 3 commits into from Feb 9, 2018

Conversation

pb82
Copy link
Contributor

@pb82 pb82 commented Feb 7, 2018

Motivation

Initial version of the android metrics sdk.

JIRA: AGDROID-719

Description

Example Usage:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        MetricsService metrics = this.core.getInstance(MetricsService.class);
        metrics.init(getApplicationContext());
        ...
    }

Progress

  • Initial POC
  • Reponse handling and logging
  • Tests

HttpRequest request = httpService.newRequest();
request.post(config.getUri(), getMetricsData(context));
request.execute();
// TODO: response callback and response status logging
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@secondsun I tried

            final HttpResponse response = request.execute();
            response.onComplete(new Runnable() {
                @Override
                public void run() {
                    Log.d(LOG_TAG, "status: " + response.getStatus());
                }
            });

but that results in a null pointer exception when it's trying to get the status code from the response. What's the recommended way to use the http module in such a case? It looks like it's already executing the http requests on the network thread, so no need to use AsyncTask?


public class MetricsService implements ServiceModule {
public final static String LOG_TAG = "AEROGEAR/METRICS";
private final static String STORAGE_NAME = "aerogear-metrics";
Copy link
Contributor

Choose a reason for hiding this comment

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

I would normally suggest using the full package name to avoid potential naming conflicts.

@pb82 pb82 force-pushed the AGDROID-719 branch 5 times, most recently from 774f8d3 to e0ffe89 Compare February 7, 2018 16:48
@danielpassos danielpassos changed the title Agdroid 719 Add Metrics Feb 7, 2018
build.gradle Outdated
@@ -33,6 +33,14 @@ subprojects {
}
}

// We want to expose the SDK version and name to the metrics subproject
project(':metrics') {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it should be the core responsibility

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

// Required for metrics, exposed by the parent project
versionName project.ext.versionName
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it should be the core responsibility

Copy link
Contributor

Choose a reason for hiding this comment

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

Using Core for versioning on IOS


dependencies {
implementation project(path: ':core')
implementation fileTree(dir: 'libs', include: ['*.jar'])
Copy link
Collaborator

Choose a reason for hiding this comment

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

It should be removed

implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
Copy link
Collaborator

Choose a reason for hiding this comment

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

Version is coming from the BOM and should be removed from here

@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="mobile.aerogear.org.metrics" />
Copy link
Collaborator

Choose a reason for hiding this comment

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

We are using a different kind of package (correctly or not) in the other modules org.aerogear.mobile.[module-name]


@Override
public void configure(MobileCore core, ServiceConfiguration serviceConfiguration) {
config = new MetricsConfig(serviceConfiguration);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we can use ServiceConfiguration instead of creating a new one


@Override
public void destroy() {
// Not used
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the comment is not necessarily, and it can be a empty method

}
}

private byte[] getMetricsData(final Context context) throws JSONException {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Only a personal opinion it can be createMetricsData or only metricsData, but again it's only a personal thought

.getPackageManager()
.getPackageInfo(context.getPackageName(), 0).versionName;
} catch (PackageManager.NameNotFoundException e) {
logger.error(LOG_TAG, e);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure if's going to happen but I think we should raise an Exception instead of return null


public class MetricsService implements ServiceModule {
private final static String MODULE_NAME = "metrics";
private final static String LOG_TAG = "AEROGEAR/METRICS";
Copy link
Collaborator

Choose a reason for hiding this comment

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

s/LOG_TAG/TAG

* @param context Android app context
* @return String Client ID
*/
private String getOrCreateClientId(final Context context) {
Copy link
Member

Choose a reason for hiding this comment

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

@pb82 @wtrocki @danielpassos
First thing I noticed is private methods/fields/etc.. I think we should better go with protected as we are developing an SDK for our users and not an app. They might want to override stuff.
Just a general comment to keep in mind to make things extendable.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Very nice catch!!!

result.put("appVersion", getAppVersion(context));
result.put("sdkVersion", BuildConfig.VERSION_NAME);

return result.toString().getBytes();
Copy link
Member

Choose a reason for hiding this comment

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

Similar concern to make things extendable.
I would make this method protected and make it return JSONObject. If a user wants to override metrics sent, they should be able to just call super, get the JSONObject and then modify it.
toString or getBytes() conversion could very well happen in the caller of this method, if it is only called from one place.

*
* @param context Android application context
*/
public void init(final Context context) {
Copy link
Member

Choose a reason for hiding this comment

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

IMO this depends on how we call this init method. Perhaps we can still throw the exception and let the caller decide what to do with it.
Looked for callers, couldn't find any at the moment. How is this supposed to be called?

@wtrocki
Copy link
Contributor

wtrocki commented Feb 8, 2018

See also IOS SDK implementation: aerogear/aerogear-ios-sdk#13

@@ -103,7 +103,7 @@ afterEvaluate { project ->
source = variant.javaCompile.source
ext.androidJar = project.files(android.getBootClasspath().join(File.pathSeparator))
classpath = files(variant.javaCompile.classpath.files) + files(ext.androidJar)
exclude '**/BuildConfig.java'
exclude '**/BuildConfig'
Copy link
Contributor Author

@pb82 pb82 Feb 8, 2018

Choose a reason for hiding this comment

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

For some reason those exclusions don't work with .java and gradle gives out warnings. That's why i've changed it, it seems to work as expected this way.

@@ -0,0 +1 @@
mock-maker-inline
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This allows Mockito to mock final classes and methods

import java.util.UUID;

public class MetricsService implements ServiceModule {
public final static String STORAGE_NAME = "mobile.aerogear.org.metrics";
Copy link
Collaborator

Choose a reason for hiding this comment

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

s/mobile.aerogear.org.metrics/org.aerogear.mobile.metrics

@danielpassos
Copy link
Collaborator

@pb82 Just need a very small fix and we are good to go. Awesome work here man.

Approval Intense Clapping.gif?raw=true

@aliok
Copy link
Member

aliok commented Feb 9, 2018

I haven't actually tried running the code, but looks good to me 👍
I still have the feeling that we should use protected for almost every private thing in order to allow extension of things, but this is something that could be done anytime.

@pb82
Copy link
Contributor Author

pb82 commented Feb 9, 2018

@danielpassos Changed the storage name to the actual package name
@aliok Yes that can be done at any time. I also feel that we need to think about how we want people to extend the SDK. Right now they could override those methods in their own implementation but then, what do they do with it? There must be a documented way to register your own implementation in the SDK (core is responsible for creating the instances).

@danielpassos danielpassos merged commit 4f50915 into aerogear:master Feb 9, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants