/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.usergrid.persistence;
import net.jcip.annotations.NotThreadSafe;
import org.apache.usergrid.AbstractCoreIT;
import org.apache.usergrid.corepersistence.util.CpNamingUtils;
import org.apache.usergrid.persistence.entities.Event;
import org.apache.usergrid.persistence.entities.Group;
import org.apache.usergrid.persistence.entities.User;
import org.apache.usergrid.persistence.index.query.CounterResolution;
import org.apache.usergrid.persistence.model.util.UUIDGenerator;
import org.apache.usergrid.utils.ImmediateCounterRule;
import org.apache.usergrid.utils.JsonUtils;
import org.apache.usergrid.utils.UUIDUtils;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@NotThreadSafe
public class CounterIT extends AbstractCoreIT {
private static final Logger logger = LoggerFactory.getLogger( CounterIT.class );
@Rule
public ImmediateCounterRule counterRule = new ImmediateCounterRule();
long ts = System.currentTimeMillis() - ( 24 * 60 * 60 * 1000 );
public CounterIT() {
super();
}
@Ignore( "Pending https://issues.apache.org/jira/browse/USERGRID-1120. ")
// needs to have elasticsearch refreshes implemented
@Test
public void testIncrementAndDecrement() throws Exception {
logger.info( "CounterIT.testIncrementAndDecrement" );
EntityManager em = app.getEntityManager();
assertNotNull( em );
final UUID applicationId = em.getApplicationId();
Map<String, Long> counters = em.getEntityCounters( applicationId );
assertEquals( null, counters.get( "application.collection.users" ) );
UUID uuid = UUIDUtils.newTimeUUID(); // UUID.();
Map<String, Object> userProperties = new HashMap<String, Object>();
userProperties.put( "name", "test-name" );
userProperties.put( "username", "test-username" );
userProperties.put( "email", "test-email" );
User user = ( User ) em.create( uuid, "user", userProperties ).toTypedEntity();
logger.debug( "user={}", user );
em.refreshIndex();
counters = em.getEntityCounters( applicationId );
assertEquals( new Long( 1 ), counters.get( "application.collection.users" ) );
em.delete( user );
em.refreshIndex();
counters = em.getEntityCounters( applicationId );
assertEquals( new Long( 0 ), counters.get( "application.collection.users" ) );
}
@Test
public void testCounters() throws Exception {
logger.info( "CounterIT.testCounters" );
EntityManager em = app.getEntityManager();
assertNotNull( em );
UUID user1 = UUID.randomUUID();
UUID user2 = UUID.randomUUID();
// UUID groupId = UUID.randomUUID();
Event event = null;
for ( int i = 0; i < 100; i++ ) {
event = new Event();
event.setTimestamp( ts + ( i * 60 * 1000 ) );
event.addCounter( "visits", 1 );
event.setUser( user1 );
em.create( event );
event = new Event();
event.setTimestamp( ts + ( i * 60 * 1000 ) );
event.addCounter( "visits", 1 );
event.setUser( user2 );
em.create( event );
}
Results r = em.getAggregateCounters( null, null, null, "visits", CounterResolution.SIX_HOUR, ts,
System.currentTimeMillis(), false );
logger.info( JsonUtils.mapToJsonString( r.getCounters() ) );
r = em.getAggregateCounters( user1, null, null, "visits", CounterResolution.SIX_HOUR, ts,
System.currentTimeMillis(), false );
logger.info( JsonUtils.mapToJsonString( r.getCounters() ) );
r = em.getAggregateCounters( user1, null, null, "visits", CounterResolution.SIX_HOUR, ts,
System.currentTimeMillis(), true );
logger.info( JsonUtils.mapToJsonString( r.getCounters() ) );
r = em.getAggregateCounters( user1, null, null, "visits", CounterResolution.ALL, ts, System.currentTimeMillis(),
false );
logger.info( JsonUtils.mapToJsonString( r.getCounters() ) );
for ( int i = 0; i < 10; i++ ) {
event = new Event();
event.setTimestamp( ts + ( i * 60 * 60 * 1000 ) );
event.addCounter( "clicks", 1 );
em.create( event );
}
r = em.getAggregateCounters( null, null, null, "clicks", CounterResolution.HALF_HOUR, ts,
System.currentTimeMillis(), true );
logger.info( JsonUtils.mapToJsonString( r.getCounters() ) );
Query query = new Query();
query.addCounterFilter( "clicks:*:*:*" );
query.addCounterFilter( "visits:*:*:*" );
query.setStartTime( ts );
query.setFinishTime( System.currentTimeMillis() );
query.setResolution( CounterResolution.SIX_HOUR );
query.setPad( true );
r = em.getAggregateCounters( query );
logger.info( JsonUtils.mapToJsonString( r.getCounters() ) );
logger.info( JsonUtils.mapToJsonString( em.getCounterNames() ) );
Map<String, Long> counts = em.getApplicationCounters();
logger.info( "counts map: " + JsonUtils.mapToJsonString( counts ) );
assertEquals( new Long( 10 ), counts.get( "clicks" ) );
assertEquals( new Long( 200 ), counts.get( "visits" ) );
assertEquals( new Long( 210 ), counts.get( "application.collection.events" ) );
}
@Test
public void testCommunityCounters() throws Exception {
EntityManager em = setup.getEmf().getEntityManager( setup.getEmf().getManagementAppId() );
// get counts at start of test
Query query = new Query();
query.addCounterFilter( "admin.logins:*:*:*" );
query.setStartTime( ts );
query.setFinishTime( System.currentTimeMillis() );
query.setResolution( CounterResolution.SIX_HOUR );
Results or = em.getAggregateCounters( query );
final long originalCount;
if ( or.getCounters().get( 0 ).getValues().isEmpty() ) {
originalCount = 0;
}
else {
originalCount = or.getCounters().get( 0 ).getValues().get( 0 ).getValue();
}
Map<String, Long> counts = em.getApplicationCounters();
final long originalAdminLoginsCount;
if ( counts.get( "admin.logins" ) == null ) {
originalAdminLoginsCount = 0;
}
else {
originalAdminLoginsCount = counts.get( "admin.logins" );
}
String randomSuffix = UUIDGenerator.newTimeUUID().toString();
String orgName = "testCounter" + randomSuffix;
String appName = "testEntityCounters" + randomSuffix;
Group organizationEntity = new Group();
organizationEntity.setPath( "tst-counter" + randomSuffix );
organizationEntity.setProperty( "name", orgName );
organizationEntity = em.create( organizationEntity );
Entity appInfo = setup.getEmf().createApplicationV2( orgName, appName );
UUID applicationId = appInfo.getUuid();
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "name", orgName + "/" + appName );
Entity applicationEntity = em.create( applicationId, CpNamingUtils.APPLICATION_INFO, properties );
//Creating connections like below doesn't work.
em.createConnection( organizationEntity.toTypedEntity(), "owns", applicationEntity );
Event event = new Event();
event.setTimestamp( System.currentTimeMillis() );
event.addCounter( "admin.logins", 1 );
event.setGroup( organizationEntity.getUuid() );
// TODO look at row syntax of event counters being sent
em.create( event );
// event = new Event();
// event.setTimestamp(System.currentTimeMillis());
// event.addCounter("admin.logins", 1);
// em.create(event);
counts = em.getApplicationCounters();
logger.info( JsonUtils.mapToJsonString( counts ) );
assertNotNull( counts.get( "admin.logins" ) );
assertEquals( 1, counts.get( "admin.logins" ).longValue() - originalAdminLoginsCount );
// Q's:
// how to "count" a login to a specific application?
// when org is provided, why is it returning 8? Is it 4 with one 'event'?
Results r = em.getAggregateCounters( null, null, null, "admin.logins", CounterResolution.ALL, ts,
System.currentTimeMillis(), false );
logger.info( JsonUtils.mapToJsonString( r.getCounters() ) );
assertEquals( 1, r.getCounters().get( 0 ).getValues().get( 0 ).getValue() - originalAdminLoginsCount );
r = em.getAggregateCounters( query );
logger.info( JsonUtils.mapToJsonString( r.getCounters() ) );
assertEquals( 1, r.getCounters().get( 0 ).getValues().get( 0 ).getValue() - originalCount );
}
@Test
public void testTimedFlush() throws Exception {
logger.info( "CounterIT.testCounters" );
EntityManager em = app.getEntityManager();
assertNotNull( em );
UUID user1 = UUID.randomUUID();
UUID user2 = UUID.randomUUID();
// UUID groupId = UUID.randomUUID();
Event event;
for ( int i = 0; i < 100; i++ ) {
event = new Event();
event.setTimestamp( ts + ( i * 60 * 1000 ) );
event.addCounter( "visits", 1 );
event.setUser( user1 );
em.create( event );
event = new Event();
event.setTimestamp( ts + ( i * 60 * 1000 ) );
event.addCounter( "visits", 1 );
event.setUser( user2 );
em.create( event );
}
//sleep to ensure the flush has executed
Thread.sleep( 30000 );
final long totalCount = returnCounts( em, "visits" );
assertEquals(200, totalCount);
}
private long returnCounts( final EntityManager em, final String counterName ) {
Results r = em.getAggregateCounters( null, null, null, counterName, CounterResolution.SIX_HOUR, ts,
System.currentTimeMillis(), false );
final AggregateCounterSet counter = r.getCounters().get( 0 );
assertEquals(counterName, counter.getName());
long count = 0;
for(final AggregateCounter value: counter.getValues()){
count += value.getValue();
}
return count;
}
}