Commits

Manuel Polo committed 2e799d2

Added global target metadata aggregation

Comments (0)

Files changed (5)

src/main/java/org/mongoste/core/impl/mongodb/MongoStatsEngine.java

             dtTo = dateToFilter.getDateTimeValue();
         }        
         if(dtFrom == null) {
-            //Set to date
-            queryDoc.put(EVENT_DATE,new BasicDBObject("$lte", dtTo.toDate()));            
+        	if(dtTo != null) {
+        		//Set to date
+        		queryDoc.put(EVENT_DATE,new BasicDBObject("$lte", dtTo.toDate()));
+        	}
         } else {
             if(dtTo == null) {
                 //Set from date
             DBObject fields = MongoUtil.createDoc(
                     EVENT_ACTION,1,
                     FIELD_COUNT,1,
-                    EVENT_DATE,1
+                    EVENT_DATE,1,
+                    FIELD_META,1
             );
             dbc = targets.find(query,fields);
             t = System.currentTimeMillis() - t;            
             MutableDateTime dateTime = DateUtil.getDateTimeUTC(true).toMutableDateTime();
             DateTime date;
             Date eventYearMonthTargetDate;
+            Map metadata;
             int processed = 0;
             t = System.currentTimeMillis();
             while(dbc.hasNext()) {
                 actionName = resultDoc.getString(EVENT_ACTION);
                 count = resultDoc.getLong(FIELD_COUNT);
                 eventYearMonthTargetDate = (Date) resultDoc.get(EVENT_DATE);
+                resultDoc = (BasicDBObject) resultDoc.get(FIELD_META); //Check global metadata counters
+                if(resultDoc != null) {
+                	metadata = convertMetadataCountersToPlainMap(resultDoc);
+                } else {
+                	metadata = null;
+                }
                 dateTime.setDate(eventYearMonthTargetDate.getTime());
                 date = dateTime.toDateTime();
                 action = actions.get(actionName);
                     actions.put(actionName,action = new StatAction(actionName,0));
                 }
                 action.add(count);
+               	action.addMetadata(metadata);
+
                 dateCount = actionsDate.get(actionName);
                 if(dateCount == null) {
                     dateCount = new TreeMap<DateTime,StatCounter>();
                     dateCount.put(date, dateCounter = new StatCounter(actionName, 0, date.toDate()));
                 }
                 dateCounter.add(count);
+                dateCounter.addMetadata(metadata);
                 processed++;
             }
             //Build result list
         return result;
     }
 
-    private Map<String,Long> getActionCount(DBObject query) throws StatsEngineException {
+    private Map convertMetadataCountersToPlainMap(BasicDBObject metadata) {
+		//TODO create plain map of key.subkey -> value
+		return metadata.toMap();
+	}
+
+	private Map<String,Long> getActionCount(DBObject query) throws StatsEngineException {
         Map<String,Long> result = new HashMap<String, Long>();
         DBCursor dbc = null;
         try {

src/main/java/org/mongoste/model/StatAction.java

 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Represents a stat action counter

src/main/java/org/mongoste/model/StatCounter.java

  */
 package org.mongoste.model;
 
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
 import org.joda.time.DateTime;
-
-import java.util.Date;
-import java.io.Serializable;
+import org.mongoste.util.NumberUtil;
 
 /**
  * A stat counter
 	private String name;
     private long count;
     private DateTime dateTime;
+    private Map<String,Number> metadata;
 
     public StatCounter(String name, long count) {
         this(name,count,(DateTime)null);
         this.count += count;
     }
 
+    /**
+	 * @return the metadata counters
+	 */
+	public Map<String, Number> getMetadata() {
+		return metadata;
+	}
+	
+	/**
+	 * Adds a value map to the metadata counters
+	 * @param valueMap Plain key->value map
+	 */
+	public void addMetadata(Map<String,Object> valueMap) {
+		if(valueMap == null) {
+			//Nothing to add
+			return;
+		}
+		if(metadata == null) {
+			metadata = new HashMap<String,Number>();
+		}
+		Number count;
+		Object value;
+		for(String key : valueMap.keySet()) {
+			value = valueMap.get(key);
+			if(value instanceof Number) {
+				count = metadata.get(key);
+				if(count == null) {
+					count = 0;
+				}			
+				metadata.put(key, NumberUtil.add((Number)value,count));
+			}
+		}
+	}
 
-    @Override
+	@Override
     public String toString() {
-        return getClass().getSimpleName()+"["+getName()+":"+getCount()+" date:"+dateTime+"]";
+        return getClass().getSimpleName()+"["+getName()+":"+getCount()+" date:"+dateTime+ (metadata == null ? "" : " metadata:"+metadata) +"]";
     }
 
 

src/main/java/org/mongoste/util/NumberUtil.java

+/*
+ *    Copyright (c) 2010-2011 Manuel Polo (mrmx.org)
+ *
+ *    This program is free software: you can redistribute it and/or  modify
+ *    it under the terms of the GNU Affero General Public License, version 3,
+ *    as published by the Free Software Foundation.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU Affero General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Affero General Public License
+ *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.mongoste.util;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * Various Number util methods
+ * @author mrmx
+ */
+public final class NumberUtil {
+	
+	public static Number add(Number a,Number b) {
+		Number result = 0;
+		if(a == null) {
+			a = 0;
+		}
+		if(b == null) {
+			b = 0;
+		}
+		if(a instanceof Integer) {
+			result = ((Integer)a).intValue() + b.intValue();
+		} else if(a instanceof Long) {
+			result = ((Long)a).longValue() + b.longValue();
+		} else if(a instanceof Float) {
+			result = ((Float)a).floatValue() + b.floatValue();
+		} else if(a instanceof Double) {
+			result = ((Double)a).doubleValue() + b.doubleValue();
+		} else if(a instanceof BigInteger) {
+			result = ((BigInteger)a).add(BigInteger.valueOf(b.longValue()));
+		} else if(a instanceof BigDecimal) {
+			if(b instanceof BigDecimal) {
+				result = ((BigDecimal)a).add((BigDecimal)b);
+			} else {
+				result = ((BigDecimal)a).add(BigDecimal.valueOf(b.doubleValue()));
+			}
+		} else {
+			throw new IllegalArgumentException(a.getClass()+" not supported for adding");
+		}
+		return result;
+	}
+
+}

src/test/java/org/mongoste/core/impl/mongodb/MongoStatsEngineTest.java

     }
 
     /**
+     * Test of global metadata counters aggregation with multiple targets
+     */
+    @Test
+    public void testGlobalMetadataCountersAggregationWithMultipleTargets() throws Exception {
+        System.out.println("testGlobalMetadataCountersAggregationWithMultipleTargets");
+        int events = 100;
+        int numTargets = 12;
+        StatEvent event = engine.createSampleEvent();       
+        List<String> targets = new ArrayList<String>();
+        for(int t = 0 ; t < numTargets ; t++) {
+        	event.setTarget("target"+(t+1));
+	        event.getMetadata().put(MongoStatsEngine.METAKEY_GLOBAL_PREFIX + "global", "key");
+	        event.getMetadata().put(MongoStatsEngine.METAKEY_GLOBAL_PREFIX + "integer", 100);
+	        event.getMetadata().put(MongoStatsEngine.METAKEY_GLOBAL_PREFIX + "long", 10000000L);
+	        event.getMetadata().put(MongoStatsEngine.METAKEY_GLOBAL_PREFIX + "double", 0.333333333d);
+	        for(int i = 0 ; i < events ; i++) {
+	        	engine.handleEvent(event);	
+	        }
+	        targets.add(event.getTarget());
+        }
+        Query query = engine.createQuery();
+        query.filterBy(QueryField.CLIENT_ID, event.getClientId());
+        query.filterBy(QueryField.TARGET_TYPE, event.getTargetType());
+        query.filterBy(QueryField.TARGET, QueryOp.IN,targets);
+        List<StatAction> targetStats = query.getTargetStats();
+        System.out.println("targetStats="+targetStats);
+        assertNotNull(targetStats);        
+        assertEquals(1,targetStats.size());
+        StatAction statAction = targetStats.get(0);
+        assertNotNull(statAction);
+        Map<String,Number> metadata = statAction.getMetadata();
+        assertNotNull(metadata);      
+        int multiplier = events * numTargets;
+        assertEquals(multiplier * (Integer)event.getMetadata().get(MongoStatsEngine.METAKEY_GLOBAL_PREFIX + "integer"),metadata.get("integer"));
+        assertEquals(multiplier * (Long)event.getMetadata().get(MongoStatsEngine.METAKEY_GLOBAL_PREFIX + "long"),metadata.get("long"));
+        assertEquals(multiplier * (Double)event.getMetadata().get(MongoStatsEngine.METAKEY_GLOBAL_PREFIX + "double"),(Double)metadata.get("double"),0.0000001d);    
+        //TODO
+        assertEquals(multiplier,metadata.get("global.key"));
+    }
+    
+    /**
      * Test of buildStats method, of class MongoStatsEngine.
      */
     @Test