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

AGPUSH-971 : Advanced Analytics, Server Side #540

Closed
wants to merge 13 commits into from
12 changes: 12 additions & 0 deletions admin-ui/app/views/notification.html
Expand Up @@ -56,6 +56,18 @@
<td>Message:</td>
<td colspan="2"><strong>{{ activityCtrl.parse(metric).alert }}</strong></td>
</tr>
<tr>
<td>Installations being opened:</td>
<td colspan="2">{{ metric.appOpenCounter }}</td>
</tr>
<tr>
<td>First time being opened:</td>
<td colspan="2">{{ metric.firstOpenDate | date : 'd MMM, HH:mm:ss, yyyy'}}</td>
</tr>
<tr>
<td>last time being opened:</td>
<td colspan="2">{{ metric.lastOpenDate | date : 'd MMM, HH:mm:ss, yyyy'}}</td>
</tr>
Copy link
Contributor

Choose a reason for hiding this comment

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

This file is no longer used in UI and needs to be removed in Beta1

</table>
<hr ng-show="metric.deliveryFailed">
<table ng-show="metric.deliveryFailed">
Expand Down
Expand Up @@ -21,6 +21,8 @@
import org.jboss.aerogear.unifiedpush.api.Installation;
import org.jboss.aerogear.unifiedpush.api.Variant;
import org.jboss.aerogear.unifiedpush.rest.AbstractBaseEndpoint;
import org.jboss.aerogear.unifiedpush.rest.util.HttpRequestUtil;
import org.jboss.aerogear.unifiedpush.service.metrics.PushMessageMetricsService;
import org.jboss.aerogear.unifiedpush.utils.AeroGearLogger;
import org.jboss.aerogear.unifiedpush.rest.util.HttpBasicHelper;
import org.jboss.aerogear.unifiedpush.service.ClientInstallationService;
Expand Down Expand Up @@ -51,6 +53,9 @@ public class InstallationRegistrationEndpoint extends AbstractBaseEndpoint {
@Inject
private GenericVariantService genericVariantService;

@Inject
private PushMessageMetricsService metricsService;


@OPTIONS
@Path("{token: .*}")
Expand All @@ -73,7 +78,7 @@ public Response crossOriginForInstallations(@Context HttpHeaders headers) {
*
* <pre>
* curl -u "variantID:secret"
* -v -H "Accept: application/json" -H "Content-type: application/json"
* -v -H "Accept: application/json" -H "Content-type: application/json" -H "aerogear-push-id: someid"
Copy link
Contributor

Choose a reason for hiding this comment

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

let's have doc for that :-) what's it's for - when to inculde etc.

Copy link
Member Author

Choose a reason for hiding this comment

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

Will be added in our Registration doc https://aerogear.org/docs/unifiedpush/client-registration/ , seems that the good place ?

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah - but perhaps here too, especually we generate the REST docs from here

* -X POST
* -d '{
* "deviceToken" : "someTokenString",
Expand Down Expand Up @@ -120,6 +125,12 @@ public Response registerInstallation(
// otherwise we register a new installation:
logger.finest("Mobile Application on device was launched");

//let's do update the analytics

String aerogearPushId = HttpRequestUtil.extractPushIdentifier(request);
if(aerogearPushId!= null) {
metricsService.updateAnalytics(aerogearPushId, variant.getVariantID());
}
// async:
clientInstallationService.addInstallation(variant, entity);

Expand Down
Expand Up @@ -85,6 +85,16 @@ public static String extractAeroGearSenderInformation(final HttpServletRequest r
return request.getHeader("user-agent");
}

/**
* Extract the header that identifies the push message.
*
* @param request , the current @link{{HttpServletRequest}}
* @return value of header
*/
public static String extractPushIdentifier(HttpServletRequest request) {
Copy link
Contributor

Choose a reason for hiding this comment

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

mind adding a test ?

return request.getHeader("aerogear-push-id");
}

/**
* Simple validation, using java.net.InetAddress.getByName().
*
Expand Down
Expand Up @@ -181,4 +181,13 @@ public void extactAscSortingParamValue() {
assertThat(HttpRequestUtil.extractSortingQueryParamValue("foo")).isTrue();
assertThat(HttpRequestUtil.extractSortingQueryParamValue("AsC")).isTrue();
}

@Test
public void extractAeroGearsPushIdHeader() {
final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getHeader("aerogear-push-id")).thenReturn("123");
final String aerogearPushId = HttpRequestUtil.extractPushIdentifier(request);

assertThat(aerogearPushId).isEqualTo("123");
}
}
Expand Up @@ -36,6 +36,10 @@ public class PushMessageInformation extends BaseModel {
private Date submitDate = new Date();
private long totalReceivers;

private long appOpenCounter;
private Date firstOpenDate;
private Date lastOpenDate;
Copy link
Contributor

Choose a reason for hiding this comment

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

we need to integrate this into the migration PR, that @qmx is currently working on for getting ready to be part of master

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have test for these new properties ?


private Set<VariantMetricInformation> variantInformations = new HashSet<VariantMetricInformation>();

/**
Expand Down Expand Up @@ -125,6 +129,52 @@ public void setTotalReceivers(long totalReceivers) {
this.totalReceivers = totalReceivers;
}

/**
* The number of time this Push Application was opened after a Push Notification
*
* @return the number of time this Push Application was opened after a Push Notification
*/
public long getAppOpenCounter() {
return appOpenCounter;
}

public void setAppOpenCounter(long appOpenCounter) {
this.appOpenCounter = appOpenCounter;
}

/**
* Increment the AppOpenCounter
*/
public void incrementAppOpenCounter() {
this.setAppOpenCounter(this.getAppOpenCounter() +1);
}

/**
* The date of the first time this Push Application was opened after a Push Notification
*
* @return the date of the first time this Push Application was opened after a Push Notification
*/
public Date getFirstOpenDate() {
return firstOpenDate;
}

public void setFirstOpenDate(Date firstOpenDate) {
this.firstOpenDate = firstOpenDate;
}

/**
* The date of the last time this Push Application was opened after a Push Notification
*
* @return the date of the last time this Push Application was opened after a Push Notification
*/
public Date getLastOpenDate() {
return lastOpenDate;
}

public void setLastOpenDate(Date lastOpenDate) {
this.lastOpenDate = lastOpenDate;
}

public void addVariantInformations(VariantMetricInformation variantMetricInformation) {
this.variantInformations.add(variantMetricInformation);
variantMetricInformation.setPushMessageInformation(this);
Expand Down
Expand Up @@ -31,6 +31,7 @@ public class VariantMetricInformation extends BaseModel {
private long receivers;
private Boolean deliveryStatus = Boolean.FALSE;
private String reason;
private long variantOpenCounter;

@JsonIgnore
private PushMessageInformation pushMessageInformation;
Expand Down Expand Up @@ -97,4 +98,21 @@ public PushMessageInformation getPushMessageInformation() {
public void setPushMessageInformation(PushMessageInformation pushMessageInformation) {
this.pushMessageInformation = pushMessageInformation;
}

/**
* To track how many time this variant has been opened after a Push Notification
*
Copy link
Contributor

Choose a reason for hiding this comment

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

return desc. missing

* @return long , the times this variant has been opened after a Push Notification
*/
public long getVariantOpenCounter() {
return variantOpenCounter;
}

public void setVariantOpenCounter(long variantOpenCounter) {
this.variantOpenCounter = variantOpenCounter;
}

public void incrementVariantOpenCounter() {
this.setVariantOpenCounter(this.getVariantOpenCounter() + 1);
}
}
Expand Up @@ -114,4 +114,7 @@ public interface PushMessageInformationDao extends GenericBaseDao<PushMessageInf
List<String> findVariantIDsWithWarnings();
List<PushMessageInformation> findLatestActivity(int maxResults);
long getNumberOfPushMessagesForApplications();

PushMessageInformation getPushMessageInformation(String id);

}
@@ -0,0 +1,33 @@
/**
* JBoss, Home of Professional Open Source
* Copyright Red Hat, Inc., and individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.aerogear.unifiedpush.dao;
import org.jboss.aerogear.unifiedpush.api.VariantMetricInformation;


Copy link
Contributor

Choose a reason for hiding this comment

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

what's this class for?

Copy link
Member Author

Choose a reason for hiding this comment

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

To retrieve a specific VariantMetricInformation instance, we had no dao for this entity before.

Copy link
Contributor

Choose a reason for hiding this comment

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

javadoc?

Copy link
Member Author

Choose a reason for hiding this comment

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

None of our DAO interfaces have Class level doc but yeah , I could add it for this one if needed.

public interface VariantMetricInformationDao extends GenericBaseDao<VariantMetricInformation, String>{

/**
* Finds a VariantMetricInformation instance by the related variantID
*
* @param variantID that is associated with the VariantMetricInformation instance
Copy link
Contributor

Choose a reason for hiding this comment

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

second param missing

* @param pushMessageinformationId of the @link{{org.jboss.aerogear.unifiedpush.api.PushMessageInformation}} that owns this instance
* @return a VariantMetricInformation instance
*/
VariantMetricInformation findVariantMetricInformationByVariantID(String variantID, String pushMessageinformationId);

}

Expand Up @@ -20,32 +20,44 @@
import org.junit.Test;


import java.util.Date;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;

public class PushMessageInformationTest {

private PushMessageInformation pushMessageInformation;
private Date openAppDate = new Date();
private Date lastOpenDate = new Date();

@Before
public void setup() {


// general job data
pushMessageInformation = new PushMessageInformation();
pushMessageInformation.setPushApplicationId("123");
pushMessageInformation.setRawJsonMessage("{\"data\" : \"something\"}");
pushMessageInformation.setIpAddress("127.0.0.1");
pushMessageInformation.setClientIdentifier("Java Sender Client");
pushMessageInformation.setAppOpenCounter(1);
pushMessageInformation.setFirstOpenDate(openAppDate);
pushMessageInformation.setLastOpenDate(lastOpenDate);


// two involved variants:
VariantMetricInformation variantInfo1 = new VariantMetricInformation();
variantInfo1.setVariantID("345");
variantInfo1.setReceivers(500);
variantInfo1.setDeliveryStatus(Boolean.FALSE);
variantInfo1.setVariantOpenCounter(1);

VariantMetricInformation variantInfo2 = new VariantMetricInformation();
variantInfo2.setVariantID("678");
variantInfo2.setReceivers(100);
variantInfo2.setDeliveryStatus(Boolean.TRUE);
variantInfo1.setVariantOpenCounter(2);

// add the variant metadata:
pushMessageInformation.getVariantInformations().add(variantInfo1);
Expand All @@ -68,5 +80,8 @@ public void checkPushMessageInformation() {
assertThat(pushMessageInformation.getIpAddress()).isEqualTo("127.0.0.1");
assertThat(pushMessageInformation.getPushApplicationId()).isEqualTo("123");
assertThat(pushMessageInformation.getClientIdentifier()).isEqualTo("Java Sender Client");
assertThat(pushMessageInformation.getAppOpenCounter()).isEqualTo(1);
assertThat(pushMessageInformation.getFirstOpenDate()).isEqualTo(openAppDate);
assertThat(pushMessageInformation.getLastOpenDate()).isEqualTo(lastOpenDate);
}
}
Expand Up @@ -141,6 +141,13 @@ public long getNumberOfPushMessagesForApplications() {
"IN (select p.pushApplicationID from PushApplication p)", Long.class).getSingleResult();
}

@Override
public PushMessageInformation getPushMessageInformation(String id) {
return getSingleResultForQuery(createQuery(
"select pmi from PushMessageInformation pmi where pmi.id = :id")
.setParameter("id", id));

}

/**
* Helper that returns 'ASC' when true and 'DESC' when false.
Expand Down
@@ -0,0 +1,40 @@
/**
* JBoss, Home of Professional Open Source
* Copyright Red Hat, Inc., and individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.jboss.aerogear.unifiedpush.jpa.dao.impl;

import org.jboss.aerogear.unifiedpush.api.VariantMetricInformation;
import org.jboss.aerogear.unifiedpush.dao.VariantMetricInformationDao;


public class JPAVariantMetricInformationDao extends JPABaseDao<VariantMetricInformation, String> implements VariantMetricInformationDao {

@Override
public VariantMetricInformation findVariantMetricInformationByVariantID(String variantID, String pushmessageinformationId){
return getSingleResultForQuery(createQuery(
"select vmi from VariantMetricInformation vmi where vmi.variantID = :variantId and vmi.pushMessageInformation.id = :pushmessageinformationId")
.setParameter("variantId", variantID)
.setParameter("pushmessageinformationId",pushmessageinformationId));

}

@Override
public Class<VariantMetricInformation> getType() {
return VariantMetricInformation.class;
}

}
Expand Up @@ -28,8 +28,10 @@
import net.jakubholy.dbunitexpress.EmbeddedDbTesterRule;

import org.jboss.aerogear.unifiedpush.api.PushMessageInformation;
import org.jboss.aerogear.unifiedpush.api.VariantMetricInformation;
import org.jboss.aerogear.unifiedpush.dao.PageResult;
import org.jboss.aerogear.unifiedpush.dao.PushMessageInformationDao;
import org.jboss.aerogear.unifiedpush.jpa.dao.impl.JPAVariantMetricInformationDao;
import org.jboss.aerogear.unifiedpush.utils.DaoDeployment;
import org.jboss.aerogear.unifiedpush.utils.DateUtils;
import org.jboss.aerogear.unifiedpush.utils.TestUtils;
Expand All @@ -47,8 +49,12 @@ public class PushMessageInformationDaoTest {

@Inject
private EntityManager entityManager;

@Inject
private PushMessageInformationDao pushMessageInformationDao;

@Inject
private JPAVariantMetricInformationDao variantMetricInformationDao;
private String pushMessageInformationID = "1";

@Deployment
Expand All @@ -59,10 +65,12 @@ public static JavaArchive createDeployment() {
@Rule
public EmbeddedDbTesterRule testDb = new EmbeddedDbTesterRule("MessageInformation.xml");


@Before
public void setUp() {
// start the shindig
entityManager.getTransaction().begin();

}

private void flushAndClear() {
Expand Down Expand Up @@ -261,4 +269,10 @@ public void deleteOldPushMessageInformations() {
messageInformations = pushMessageInformationDao.findAllForPushApplication("231231231", Boolean.TRUE);
assertThat(messageInformations).hasSize(0);
}

@Test
public void findVariantMetricByVariantId() {
VariantMetricInformation variantMetricInformation = variantMetricInformationDao.findVariantMetricInformationByVariantID("213","1");
assertThat(variantMetricInformation).isNotNull();
}
}