...
 
Commits (2)
......@@ -18,34 +18,34 @@ class analytics implements Interfaces\Api, Interfaces\ApiIgnorePam
]);
}
$span = 12;
$span = 13;
$unit = 'month';
switch ($_GET['timespan'] ?? null) {
case 'hourly':
$span = 24;
$span = 25;
$unit = 'hour';
break;
case 'daily':
$span = 7;
$span = 17;
$unit = 'day';
break;
case 'monthly':
$span = 12;
$span = 13;
$unit = 'month';
break;
}
/** @var Core\Analytics\Metrics\Manager $manager */
/** @var Core\Analytics\Graphs\Manager $manager */
$manager = Di::_()->get('Analytics\Graphs\Manager');
try {
$urn = "urn:graph:" . $manager::buildKey([
'aggregate' => $pages[0],
'key' => $_GET['key'] ?? null,
'span' => $span,
'unit' => $unit,
]);
'aggregate' => $pages[0],
'key' => $_GET['key'] ?? null,
'span' => $span,
'unit' => $unit,
]);
$graph = $manager->get($urn);
if (!$graph) {
throw new \Exception("Graph not found");
......
......@@ -3,11 +3,11 @@
namespace Minds\Core\Analytics\Graphs\Aggregates;
use DateTime;
use Minds\Core\Analytics\Graphs\Manager;
use Minds\Core\Data\cache\abstractCacher;
use Minds\Core\Data\ElasticSearch;
use Minds\Core\Data\ElasticSearch\Client;
use Minds\Core\Di\Di;
use Minds\Core\Analytics\Graphs\Manager;
class ActiveUsers implements AggregateInterface
{
......@@ -38,15 +38,37 @@ class ActiveUsers implements AggregateInterface
public function fetchAll($opts = [])
{
$result = [];
foreach ([ 'hour', 'day', 'month' ] as $unit) {
foreach (['hour', 'day', 'month'] as $unit) {
switch ($unit) {
case 'hour':
$span = 25;
break;
case 'day':
$span = 17;
break;
case 'month':
$span = 13;
break;
}
$k = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'activeusers',
'key' => null,
'unit' => $unit,
'span' => $span
]);
$result[$k] = $this->fetch([
$result[$k] = $this->fetch([
'unit' => $unit,
'span' => $span,
]);
$avgKey = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'activeusers',
'key' => 'avg',
'unit' => $unit,
'span' => $span
]);
$result[$avgKey] = Manager::calculateAverages($result[$k]);
}
return $result;
}
......@@ -54,7 +76,7 @@ class ActiveUsers implements AggregateInterface
public function fetch(array $options = [])
{
$options = array_merge([
'span' => 12,
'span' => 13,
'unit' => 'month', // day / month
'userGuid' => null,
], $options);
......@@ -64,21 +86,29 @@ class ActiveUsers implements AggregateInterface
$from = null;
switch ($options['unit']) {
case "hour":
$from = (new DateTime('midnight'))->modify("-{$options['span']} hours");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} hours");
$this->dateFormat = 'y-m-d H:i';
return $this->getHourlyPageviews($from, $to, $user_guid);
case "day":
$from = (new DateTime('midnight'))->modify("-{$options['span']} days");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime('midnight'))
->modify("-{$options['span']} days");
$this->dateFormat = 'y-m-d';
return $this->getDailyPageviews($from, $to, $user_guid);
break;
case "month":
$from = (new DateTime('midnight first day of next month'))->modify("-{$options['span']} months");
$to = new DateTime('midnight first day of next month');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} months");
$this->dateFormat = 'y-m';
return $this->getMonthlyPageviews($from, $to, $user_guid);
......@@ -159,12 +189,14 @@ class ActiveUsers implements AggregateInterface
$response = [
[
'name' => 'HAU (Logged In)',
'key' => 'loggedInHAU',
'name' => 'Hourly Active Users',
'x' => [],
'y' => []
],
[
'name' => 'HAU (Unique)',
'key' => 'uniqueHAU',
'name' => 'Hourly Unique Visits',
'x' => [],
'y' => []
]
......@@ -254,18 +286,19 @@ class ActiveUsers implements AggregateInterface
$response = [
[
'name' => 'DAU (Logged In)',
'key' => 'loggedInDAU',
'name' => 'Daily Active Users',
'x' => [],
'y' => []
],
[
'name' => 'DAU (Unique)',
'key' => 'uniqueDAU',
'name' => 'Daily Unique Visits',
'x' => [],
'y' => []
]
];
foreach ($result['aggregations']['histogram']['buckets'] as $count) {
$date = date($this->dateFormat, $count['key'] / 1000);
......@@ -291,6 +324,13 @@ class ActiveUsers implements AggregateInterface
]
]
],
[
"match_phrase" => [
"platform.keyword" => [
"query" => "browser"
]
]
]
];
// filter by user_guid
......@@ -359,22 +399,24 @@ class ActiveUsers implements AggregateInterface
$response = [
[
'name' => 'MAU',
'key' => 'loggedInMAU',
'name' => 'Monthly Active Users',
'x' => [],
'y' => []
],
[
'name' => 'Visitors',
'key' => 'uniqueMAU',
'name' => 'Monthly Active Visits',
'x' => [],
'y' => []
],
[
'name' => 'Avg. DAU',
'name' => 'Avg. Daily Unique Visits',
'x' => [],
'y' => []
],
[
'name' => 'DAU',
'name' => 'Daily Unique Visits',
'x' => [],
'y' => []
]
......
......@@ -3,11 +3,11 @@
namespace Minds\Core\Analytics\Graphs\Aggregates;
use DateTime;
use Minds\Core\Analytics\Graphs\Manager;
use Minds\Core\Data\cache\abstractCacher;
use Minds\Core\Data\ElasticSearch;
use Minds\Core\Data\ElasticSearch\Client;
use Minds\Core\Di\Di;
use Minds\Core\Analytics\Graphs\Manager;
class AvgPageviews implements AggregateInterface
{
......@@ -34,23 +34,27 @@ class AvgPageviews implements AggregateInterface
{
$result = [];
foreach ([
'mau_unique',
'mau_loggedin',
'dau_loggedin',
'dau_unique',
'total_pageviews',
'hau_unique',
'hau_loggedin',
] as $key) {
foreach ([ 'day', 'month' ] as $unit) {
'total_pageviews',
] as $key) {
foreach ([/*'day',*/ 'month'] as $unit) {
switch ($unit) {
case 'day':
$span = 17;
break;
case 'month':
$span = 13;
break;
}
$k = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'avgpageviews',
'key' => $key,
'unit' => $unit,
'span' => $span,
]);
$result[$k] = $this->fetch([
$result[$k] = $this->fetch([
'key' => $key,
'unit' => $unit
'unit' => $unit,
'span' => $span,
]);
}
}
......@@ -60,7 +64,7 @@ class AvgPageviews implements AggregateInterface
public function fetch(array $options = [])
{
$options = array_merge([
'span' => 12,
'span' => 13,
'unit' => 'month', // day / month
'key' => null,
], $options);
......@@ -74,14 +78,15 @@ class AvgPageviews implements AggregateInterface
$from = null;
switch ($options['unit']) {
case "day":
$from = (new DateTime('midnight'))->modify("-{$options['span']} days");
$to = (new DateTime('midnight'));
$interval = '1d';
$to = new DateTime('now');
$from = (new DateTime('midnight'))
->modify("-{$options['span']} days");
break;
case "month":
$from = (new DateTime('midnight first day of next month'))->modify("-{$options['span']} months");
$to = new DateTime('midnight first day of next month');
$interval = '1M';
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} months");
break;
default:
throw new \Exception("{$options['unit']} is not an accepted unit");
......@@ -89,27 +94,9 @@ class AvgPageviews implements AggregateInterface
$response = null;
switch ($key) {
case 'mau_unique':
$response = $this->getMauUnique($from, $to, $interval);
break;
case 'mau_loggedin':
$response = $this->getMauLoggedIn($from, $to, $interval);
break;
case 'dau_loggedin':
$response = $this->getDauLoggedIn($from, $to);
break;
case 'dau_unique':
$response = $this->getDauUnique($from, $to);
break;
case 'total_pageviews':
$response = $this->getTotalPageviews($from, $to);
break;
case 'hau_unique':
$response = $this->getHauUnique($from, $to);
break;
case 'hau_loggedin':
$response = $this->getHauLoggedIn($from, $to);
break;
}
return $response;
......
......@@ -7,11 +7,11 @@
namespace Minds\Core\Analytics\Graphs\Aggregates;
use DateTime;
use Minds\Core\Analytics\Graphs\Manager;
use Minds\Core\Data\cache\abstractCacher;
use Minds\Core\Data\ElasticSearch\Client;
use Minds\Core\Data\ElasticSearch\Prepared\Search;
use Minds\Core\Di\Di;
use Minds\Core\Analytics\Graphs\Manager;
class Comments implements AggregateInterface
{
......@@ -42,15 +42,37 @@ class Comments implements AggregateInterface
public function fetchAll($opts = [])
{
$result = [];
foreach ([ 'hour', 'day', 'month' ] as $unit) {
foreach (['hour', 'day', 'month'] as $unit) {
switch ($unit) {
case 'hour':
$span = 25;
break;
case 'day':
$span = 17;
break;
case 'month':
$span = 13;
break;
}
$k = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'comments',
'key' => null,
'unit' => $unit,
'span' => $span,
]);
$result[$k] = $this->fetch([
$result[$k] = $this->fetch([
'unit' => $unit,
'span' => $span,
]);
$avgKey = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'comments',
'key' => 'avg',
'unit' => $unit,
'span' => $span,
]);
$result[$avgKey] = Manager::calculateAverages($result[$k]);
}
return $result;
}
......@@ -58,7 +80,7 @@ class Comments implements AggregateInterface
public function fetch(array $options = [])
{
$options = array_merge([
'span' => 12,
'span' => 13,
'unit' => 'month', // day / month
'userGuid' => null,
], $options);
......@@ -68,20 +90,28 @@ class Comments implements AggregateInterface
$from = null;
switch ($options['unit']) {
case "hour":
$from = (new DateTime('midnight'))->modify("-{$options['span']} hours");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} hours");
$interval = '1h';
$this->dateFormat = 'y-m-d H:i';
break;
case "day":
$from = (new DateTime('midnight'))->modify("-{$options['span']} days");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime('midnight'))
->modify("-{$options['span']} days");
$interval = '1d';
$this->dateFormat = 'y-m-d';
break;
case "month":
$from = (new DateTime('midnight first day of next month'))->modify("-{$options['span']} months");
$to = new DateTime('midnight first day of next month');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} months");
$interval = '1M';
$this->dateFormat = 'y-m';
break;
......@@ -165,6 +195,7 @@ class Comments implements AggregateInterface
$response = [
[
'key' => 'comments',
'name' => 'Comments',
'x' => [],
'y' => []
......@@ -172,7 +203,8 @@ class Comments implements AggregateInterface
];
if (!$userGuid) {
$response[] = [
'name' => 'Number of Commenting Users',
'key' => 'commentingUsers',
'name' => 'Commenting Users',
'x' => [],
'y' => []
];
......
......@@ -8,7 +8,6 @@ use Minds\Core\Data\ElasticSearch\Client;
use Minds\Core\Data\ElasticSearch\Prepared\Count;
use Minds\Core\Data\ElasticSearch\Prepared\Search;
use Minds\Core\Di\Di;
use Minds\Core\Analytics\Graphs\Manager;
class Interactions implements AggregateInterface
{
......@@ -55,14 +54,20 @@ class Interactions implements AggregateInterface
$from = null;
switch ($options['unit']) {
case "day":
$from = (new DateTime('midnight'))->modify("-{$options['span']} days");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} hours");
$interval = '1d';
$this->dateFormat = 'y-m-d';
break;
case "month":
$from = (new DateTime('midnight first day of next month'))->modify("-{$options['span']} months");
$to = new DateTime('midnight first day of next month');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} months");
$interval = '1M';
$this->dateFormat = 'y-m';
break;
......
......@@ -3,11 +3,11 @@
namespace Minds\Core\Analytics\Graphs\Aggregates;
use DateTime;
use Minds\Core\Analytics\Graphs\Manager;
use Minds\Core\Data\cache\abstractCacher;
use Minds\Core\Data\ElasticSearch;
use Minds\Core\Data\ElasticSearch\Client;
use Minds\Core\Di\Di;
use Minds\Core\Analytics\Graphs\Manager;
class Pageviews implements AggregateInterface
{
......@@ -39,19 +39,39 @@ class Pageviews implements AggregateInterface
{
$result = [];
foreach ([
null,
'routes',
] as $key) {
foreach ([ 'day', 'month' ] as $unit) {
null,
'routes',
] as $key) {
foreach (['day', 'month'] as $unit) {
switch ($unit) {
case 'day':
$span = 17;
break;
case 'month':
$span = 13;
break;
}
$k = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'pageviews',
'key' => $key,
'unit' => $unit,
'span' => $span,
]);
$result[$k] = $this->fetch([
$result[$k] = $this->fetch([
'key' => $key,
'unit' => $unit,
'span' => $span,
]);
if ($key === null) {
$avgKey = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'pageviews',
'key' => 'avg',
'unit' => $unit,
'span' => $span,
]);
$result[$avgKey] = Manager::calculateAverages($result[$k]);
}
}
}
return $result;
......@@ -60,7 +80,7 @@ class Pageviews implements AggregateInterface
public function fetch(array $options = [])
{
$options = array_merge([
'span' => 12,
'span' => 13,
'unit' => 'month', // day / month
'key' => null,
], $options);
......@@ -70,14 +90,19 @@ class Pageviews implements AggregateInterface
$from = null;
switch ($options['unit']) {
case "day":
$from = (new DateTime('midnight'))->modify("-{$options['span']} days");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime('midnight'))
->modify("-{$options['span']} days");
$interval = '1d';
$this->dateFormat = 'y-m-d';
break;
case "month":
$from = (new DateTime('midnight first day of next month'))->modify("-{$options['span']} months");
$to = new DateTime('midnight first day of next month');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} months");
$interval = '1M';
$this->dateFormat = 'y-m';
break;
......@@ -175,9 +200,17 @@ class Pageviews implements AggregateInterface
]
];
$other = $result['hits']['total'];
foreach ($result['aggregations']['routes']['buckets'] as $count) {
$response[0]['labels'][] = $count['key'];
$response[0]['values'][] = $count['doc_count'];
$other -= $count['doc_count'];
}
if ($other > 0) {
$response[0]['labels'][] = 'Other';
$response[0]['values'][] = $other;
}
return $response;
......@@ -244,7 +277,8 @@ class Pageviews implements AggregateInterface
$response = [
[
'name' => 'Number of Pageviews',
'key' => 'pageviews',
'name' => 'Pageviews',
'x' => [],
'y' => []
]
......
......@@ -3,11 +3,11 @@
namespace Minds\Core\Analytics\Graphs\Aggregates;
use DateTime;
use Minds\Core\Analytics\Graphs\Manager;
use Minds\Core\Data\cache\abstractCacher;
use Minds\Core\Data\ElasticSearch;
use Minds\Core\Data\ElasticSearch\Client;
use Minds\Core\Di\Di;
use Minds\Core\Analytics\Graphs\Manager;
class Posts implements AggregateInterface
{
......@@ -38,23 +38,46 @@ class Posts implements AggregateInterface
public function fetchAll($opts = [])
{
$result = [];
foreach ([ 'hour', 'day', 'month' ] as $unit) {
foreach (['hour', 'day', 'month'] as $unit) {
switch ($unit) {
case 'hour':
$span = 25;
break;
case 'day':
$span = 17;
break;
case 'month':
$span = 13;
break;
}
$k = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'posts',
'key' => null,
'unit' => $unit,
'span' => $span
]);
$result[$k] = $this->fetch([
'unit' => $unit,
'span' => $span,
]);
$avgKey = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'posts',
'key' => 'avg',
'unit' => $unit,
'span' => $span,
]);
$result[$avgKey] = Manager::calculateAverages($result[$k]);
}
// var_dump(array_keys($result)); die();
return $result;
}
public function fetch(array $options = [])
{
$options = array_merge([
'span' => 12,
'span' => 13,
'unit' => 'month', // day / month
'userGuid' => null,
], $options);
......@@ -64,20 +87,28 @@ class Posts implements AggregateInterface
$from = null;
switch ($options['unit']) {
case "hour":
$from = (new DateTime('midnight'))->modify("-{$options['span']} hours");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} hours");
$interval = '1h';
$this->dateFormat = 'y-m-d H:i';
break;
case "day":
$from = (new DateTime('midnight'))->modify("-{$options['span']} days");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime('midnight'))
->modify("-{$options['span']} days");
$interval = '1d';
$this->dateFormat = 'y-m-d';
break;
case "month":
$from = (new DateTime('midnight first day of next month'))->modify("-{$options['span']} months");
$to = new DateTime('midnight first day of next month');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} months");
$interval = '1M';
$this->dateFormat = 'y-m';
break;
......@@ -158,6 +189,7 @@ class Posts implements AggregateInterface
$response = [
[
'key' => 'posts',
'name' => 'Posts',
'x' => [],
'y' => []
......@@ -166,7 +198,8 @@ class Posts implements AggregateInterface
if (!$userGuid) {
$response[] = [
'name' => 'Number of Posting Users',
'key' => 'postingUsers',
'name' => 'Posting Users',
'x' => [],
'y' => []
];
......
......@@ -3,11 +3,11 @@
namespace Minds\Core\Analytics\Graphs\Aggregates;
use DateTime;
use Minds\Core\Analytics\Graphs\Manager;
use Minds\Core\Data\cache\abstractCacher;
use Minds\Core\Data\ElasticSearch;
use Minds\Core\Data\ElasticSearch\Client;
use Minds\Core\Di\Di;
use Minds\Core\Analytics\Graphs\Manager;
class Reminds implements AggregateInterface
{
......@@ -38,15 +38,37 @@ class Reminds implements AggregateInterface
public function fetchAll($opts = [])
{
$result = [];
foreach ([ 'hour', 'day', 'month' ] as $unit) {
foreach (['hour', 'day', 'month'] as $unit) {
switch ($unit) {
case 'hour':
$span = 25;
break;
case 'day':
$span = 17;
break;
case 'month':
$span = 13;
break;
}
$k = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'reminds',
'key' => null,
'unit' => $unit,
'span' => $span,
]);
$result[$k] = $this->fetch([
'unit' => $unit,
'span' => $span,
]);
$avgKey = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'reminds',
'key' => 'avg',
'unit' => $unit,
'span' => $span,
]);
$result[$avgKey] = Manager::calculateAverages($result[$k]);
}
return $result;
}
......@@ -54,7 +76,7 @@ class Reminds implements AggregateInterface
public function fetch(array $options = [])
{
$options = array_merge([
'span' => 12,
'span' => 13,
'unit' => 'month', // day / month
'userGuid' => null,
], $options);
......@@ -64,20 +86,27 @@ class Reminds implements AggregateInterface
$from = null;
switch ($options['unit']) {
case "hour":
$from = (new DateTime('midnight'))->modify("-{$options['span']} hours");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} hours");
$interval = '1h';
$this->dateFormat = 'y-m-d H:i';
break;
case "day":
$from = (new DateTime('midnight'))->modify("-{$options['span']} days");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime('midnight'))
->modify("-{$options['span']} days");
$interval = '1d';
$this->dateFormat = 'y-m-d';
break;
case "month":
$from = (new DateTime('midnight first day of next month'))->modify("-{$options['span']} months");
$to = new DateTime('midnight first day of next month');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} months");
$interval = '1M';
$this->dateFormat = 'y-m';
break;
......@@ -158,6 +187,7 @@ class Reminds implements AggregateInterface
$response = [
[
'key' => 'reminds',
'name' => 'Reminds',
'x' => [],
'y' => []
......@@ -166,7 +196,8 @@ class Reminds implements AggregateInterface
if (!$userGuid) {
$response[] = [
'name' => 'Number of Reminding Users',
'key' => 'remindingUsers',
'name' => 'Reminding Users',
'x' => [],
'y' => []
];
......
......@@ -40,14 +40,32 @@ class Rewards implements AggregateInterface
{
$result = [];
foreach ([ 'day', 'month' ] as $unit) {
switch ($unit) {
case 'day':
$span = 17;
break;
case 'month':
$span = 13;
break;
}
$k = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'rewards',
'key' => null,
'unit' => $unit,
'span' => $span,
]);
$result[$k] = $this->fetch([
'unit' => $unit,
'span' => $span,
]);
$avgKey = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'rewards',
'key' => 'avg',
'unit' => $unit,
'span' => $span,
]);
$result[$avgKey] = Manager::calculateAverages($result[$k]);
}
return $result;
}
......@@ -55,21 +73,25 @@ class Rewards implements AggregateInterface
public function fetch(array $options = [])
{
$options = array_merge([
'span' => 12,
'span' => 13,
'unit' => 'month', // day / month
], $options);
$from = null;
switch ($options['unit']) {
case "day":
$from = (new DateTime('midnight'))->modify("-{$options['span']} days");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime('midnight'))
->modify("-{$options['span']} days");
$interval = '1d';
$this->dateFormat = 'y-m-d';
break;
case "month":
$from = (new DateTime('midnight first day of next month'))->modify("-{$options['span']} months");
$to = new DateTime('midnight first day of next month');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} months");
$interval = '1M';
$this->dateFormat = 'y-m';
break;
......@@ -178,11 +200,13 @@ class Rewards implements AggregateInterface
$response = [
[
'key' => 'transactions',
'name' => 'Reward Transactions',
'x' => [],
'y' => [],
],
[
'key' => 'tokens',
'name' => 'Rewarded Tokens',
'x' => [],
'y' => [],
......
......@@ -7,11 +7,11 @@
namespace Minds\Core\Analytics\Graphs\Aggregates;
use DateTime;
use Minds\Core\Analytics\Graphs\Manager;
use Minds\Core\Data\cache\abstractCacher;
use Minds\Core\Data\ElasticSearch\Client;
use Minds\Core\Data\ElasticSearch\Prepared\Search;
use Minds\Core\Di\Di;
use Minds\Core\Analytics\Graphs\Manager;
class Subscribers implements AggregateInterface
{
......@@ -39,14 +39,27 @@ class Subscribers implements AggregateInterface
public function fetchAll($opts = [])
{
$result = [];
foreach ([ 'hour', 'day', 'month' ] as $unit) {
foreach (['hour', 'day', 'month'] as $unit) {
switch ($unit) {
case 'hour':
$span = 25;
break;
case 'day':
$span = 17;
break;
case 'month':
$span = 13;
break;
}
$k = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'subscribers',
'key' => null,
'unit' => $unit,
'span' => $span,
]);
$result[$k] = $this->fetch([
'unit' => $unit,
'span' => $span,
]);
}
return $result;
......@@ -55,7 +68,7 @@ class Subscribers implements AggregateInterface
public function fetch(array $options = [])
{
$options = array_merge([
'span' => 12,
'span' => 13,
'unit' => 'month', // day / month
'userGuid' => null,
], $options);
......@@ -68,14 +81,19 @@ class Subscribers implements AggregateInterface
$from = null;
switch ($options['unit']) {
case "day":
$from = (new DateTime('midnight'))->modify("-{$options['span']} days");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime('midnight'))
->modify("-{$options['span']} days");
$interval = '1d';
$this->dateFormat = 'y-m-d';
break;
case "month":
$from = (new DateTime('midnight first day of next month'))->modify("-{$options['span']} months");
$to = new DateTime('midnight first day of next month');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} months");
$interval = '1M';
$this->dateFormat = 'y-m';
break;
......
......@@ -3,11 +3,10 @@
namespace Minds\Core\Analytics\Graphs\Aggregates;
use DateTime;
use Minds\Core\Analytics\Graphs\Manager;
use Minds\Core\Data\ElasticSearch;
use Minds\Core\Data\ElasticSearch\Client;
use Minds\Core\Di\Di;
use Minds\Interfaces\AnalyticsMetric;
use Minds\Core\Analytics\Graphs\Manager;
class TotalPageviews implements AggregateInterface
{
......@@ -34,14 +33,27 @@ class TotalPageviews implements AggregateInterface
public function fetchAll($opts = [])
{
$result = [];
foreach ([ 'hour', 'day', 'month' ] as $unit) {
foreach (['hour', 'day', 'month'] as $unit) {
switch ($unit) {
case 'hour':
$span = 25;
break;
case 'day':
$span = 17;
break;
case 'month':
$span = 13;
break;
}
$k = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'totalpageviews',
'key' => null,
'unit' => $unit,
'span' => $span,
]);
$result[$k] = $this->fetch([
'unit' => $unit,
'span' => $span,
]);
}
return $result;
......@@ -50,27 +62,35 @@ class TotalPageviews implements AggregateInterface
public function fetch(array $options = [])
{
$options = array_merge([
'span' => 12,
'span' => 13,
'unit' => 'month', // day / month
], $options);
$from = null;
switch ($options['unit']) {
case "hour":
$from = (new DateTime('midnight'))->modify("-{$options['span']} hours");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} hours");
$interval = '1h';
$this->dateFormat = 'y-m-d H:i';
break;
case "day":
$from = (new DateTime('midnight'))->modify("-{$options['span']} days");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime('midnight'))
->modify("-{$options['span']} days");
$interval = '1d';
$this->dateFormat = 'y-m-d';
break;
case "month":
$from = (new DateTime('midnight first day of next month'))->modify("-{$options['span']} months");
$to = new DateTime('midnight first day of next month');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} months");
$interval = '1M';
$this->dateFormat = 'y-m';
break;
......
......@@ -3,11 +3,11 @@
namespace Minds\Core\Analytics\Graphs\Aggregates;
use DateTime;
use Minds\Core\Analytics\Graphs\Manager;
use Minds\Core\Data\cache\abstractCacher;
use Minds\Core\Data\ElasticSearch;
use Minds\Core\Data\ElasticSearch\Client;
use Minds\Core\Di\Di;
use Minds\Core\Analytics\Graphs\Manager;
class UserSegments implements AggregateInterface
{
......@@ -38,21 +38,35 @@ class UserSegments implements AggregateInterface
public function fetchAll($opts = [])
{
$result = [];
foreach ([
null,
'avg',
] as $key) {
foreach ([ 'day', 'month' ] as $unit) {
$k = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'usersegments',
'key' => $key,
'unit' => $unit,
]);
$result[$k] = $this->fetch([
'key' => $key,
'unit' => $unit,
]);
foreach (['day', 'month'] as $unit) {
switch ($unit) {
case 'day':
$span = 17;
break;
case 'month':
$span = 13;
break;
}
$k = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'usersegments',
'key' => null,
'unit' => $unit,
'span' => $span,
]);
$result[$k] = $this->fetch([
'key' => null,
'unit' => $unit,
'span' => $span,
]);
$avgKey = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'usersegments',
'key' => 'avg',
'unit' => $unit,
'span' => $span,
]);
$result[$avgKey] = Manager::calculateAverages($result[$k]);
}
return $result;
}
......@@ -60,24 +74,26 @@ class UserSegments implements AggregateInterface
public function fetch(array $options = [])
{
$options = array_merge([
'span' => 12,
'span' => 13,
'unit' => 'month', // day / month
'key' => null,
], $options);
$key = $options['key'];
$from = null;
switch ($options['unit']) {
case "day":
$from = (new DateTime('midnight'))->modify("-{$options['span']} days");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime('midnight'))
->modify("-{$options['span']} days");
$interval = '1d';
$this->dateFormat = 'y-m-d';
break;
case "month":
$from = (new DateTime('midnight first day of next month'))->modify("-{$options['span']} months");
$to = new DateTime('midnight first day of next month');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} months");
$interval = '1M';
$this->dateFormat = 'y-m';
break;
......@@ -85,13 +101,7 @@ class UserSegments implements AggregateInterface
throw new \Exception("{$options['unit']} is not an accepted unit");
}
$response = null;
if ($key && $key == 'avg') {
$response = $this->getAverages($from, $to, $interval);
} else {
$response = $this->getGraph($from, $to, $interval);
}
$response = $this->getGraph($from, $to, $interval);
return $response;
}
......@@ -106,83 +116,6 @@ class UserSegments implements AggregateInterface
return "usersegments:{$opts['key']}:{$opts['unit']}";
}
private function getAverages($from, $to, $interval)
{
$must = [
[
"match_all" => (object) []
],
[
"range" => [
"reference_date" => [
"gte" => $from->getTimestamp() * 1000,
"lte" => $to->getTimestamp() * 1000,
"format" => "epoch_millis"
]
]
],
];
$query = [
'index' => $this->index,
'size' => 0,
"stored_fields" => [
"*"
],
"docvalue_fields" => [
(object) [
"field" => "reference_date",
"format" => "date_time"
]
],
'body' => [
'query' => [
'bool' => [
'must' => $must
]
],
"aggs" => [
"states" => [
"terms" => [
"field" => "state",
"size" => 6,
"order" => [
"_key" => "desc"
]
],
"aggs" => [
"avg" => [
"avg_bucket" => [
"buckets_path" => "1-bucket>_count"
]
],
"1-bucket" => [
"date_histogram" => [
"field" => "reference_date",
"interval" => $interval,
"min_doc_count" => 1
]
]
]
]
],
]
];
$prepared = new ElasticSearch\Prepared\Search();
$prepared->query($query);
$result = $this->client->request($prepared);
$response = [];
foreach ($result['aggregations']['states']['buckets'] as $count) {
$response[$count['key']] = $count['avg']['value'] ?? 0;
}
return $response;
}
private function getGraph($from, $to, $interval)
{
$must = [
......@@ -248,31 +181,37 @@ class UserSegments implements AggregateInterface
$response = [
[
'key' => 'curious',
'name' => 'Curious',
'x' => [],
'y' => []
],
[
'key' => 'casual',
'name' => 'Casual',
'x' => [],
'y' => []
],
[
'key' => 'core',
'name' => 'Core',
'x' => [],
'y' => []
],
[
'key' => 'cold',
'name' => 'Cold',
'x' => [],
'y' => []
],
[
'key' => 'resurrected',
'name' => 'Resurrected',
'x' => [],
'y' => []
],
[
'key' => 'new',
'name' => 'New',
'x' => [],
'y' => []
......
......@@ -3,12 +3,11 @@
namespace Minds\Core\Analytics\Graphs\Aggregates;
use DateTime;
use Minds\Core\Analytics\Graphs\Manager;
use Minds\Core\Data\cache\abstractCacher;
use Minds\Core\Data\ElasticSearch\Client;
use Minds\Core\Data\ElasticSearch\Prepared\Search;
use Minds\Core\Di\Di;
use Minds\Interfaces\AnalyticsMetric;
use Minds\Core\Analytics\Graphs\Manager;
class Votes implements AggregateInterface
{
......@@ -39,15 +38,37 @@ class Votes implements AggregateInterface
public function fetchAll($opts = [])
{
$result = [];
foreach ([ 'hour', 'day', 'month' ] as $unit) {
foreach (['hour', 'day', 'month'] as $unit) {
switch ($unit) {
case 'hour':
$span = 25;
break;
case 'day':
$span = 17;
break;
case 'month':
$span = 13;
break;
}
$k = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'votes',
'key' => null,
'unit' => $unit,
'span' => $span,
]);
$result[$k] = $this->fetch([
'unit' => $unit,
'span' => $span,
]);
$avgKey = Manager::buildKey([
'aggregate' => $opts['aggregate'] ?? 'votes',
'key' => 'avg',
'unit' => $unit,
'span' => $span,
]);
$result[$avgKey] = Manager::calculateAverages($result[$k]);
}
return $result;
}
......@@ -55,7 +76,7 @@ class Votes implements AggregateInterface
public function fetch(array $options = [])
{
$options = array_merge([
'span' => 12,
'span' => 13,
'unit' => 'month', // day / month
'userGuid' => null,
], $options);
......@@ -65,20 +86,28 @@ class Votes implements AggregateInterface
$from = null;
switch ($options['unit']) {
case "hour":
$from = (new DateTime('midnight'))->modify("-{$options['span']} hours");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} hours");
$interval = '1h';
$this->dateFormat = 'y-m-d H:i';
break;
case "day":
$from = (new DateTime('midnight'))->modify("-{$options['span']} days");
$to = (new DateTime('midnight'));
$to = new DateTime('now');
$from = (new DateTime('midnight'))
->modify("-{$options['span']} days");
$interval = '1d';
$this->dateFormat = 'y-m-d';
break;
case "month":
$from = (new DateTime('midnight first day of next month'))->modify("-{$options['span']} months");
$to = new DateTime('midnight first day of next month');
$from = (new DateTime())
->setTimestamp($to->getTimestamp())
->modify("-{$options['span']} months");
$interval = '1M';
$this->dateFormat = 'y-m';
break;
......@@ -173,6 +202,7 @@ class Votes implements AggregateInterface
$response = [
[
'key' => 'votes',
'name' => 'Votes',
'x' => [],
'y' => []
......@@ -181,7 +211,8 @@ class Votes implements AggregateInterface
if (!$userGuid) {
$response[] = [
'name' => 'Number of Voting Users',
'key' => 'votingUsers',
'name' => 'Voting Users',
'x' => [],
'y' => []
];
......
......@@ -95,7 +95,34 @@ class Manager
$opts['aggregate'],
$opts['key'],
$opts['unit'],
$opts['span'],
]);
}
public static function calculateAverages($response)
{
$averages = [];
foreach ($response as $userState) {
if (!$userState['key']) {
continue;
}
$count = count($userState['y']);
if ($count === 0) {
continue;
}
$avg = 0;
foreach ($userState['y'] as $value) {
$avg += $value ?? 0;
}
$avg /= $count;
$averages[$userState['key']] = $avg;
}
return $averages;
}
}
......@@ -51,14 +51,14 @@ class ManagerSpec extends ObjectBehavior
->shouldReturn(true);
}
function it_should_sync_aggregates_to_graphs(AvgPageviews $avgPageviewsAggregate)
function it_should_sync_aggregates_to_graphs_with_a_12_month_interval(AvgPageviews $avgPageviewsAggregate)
{
$avgPageviewsAggregate->fetch(Argument::any())
->shouldBeCalled()
->willReturn(12);
$graph = new Graph();
$graph->setKey('avgpageviews-mau_unique-month')
$graph->setKey('avgpageviews-mau_unique-month-12')
->setLastSynced(time())
->setData(12);
......@@ -75,4 +75,30 @@ class ManagerSpec extends ObjectBehavior
]);
}
function it_should_sync_aggregates_to_graphs_with_a_10_day_interval(AvgPageviews $avgPageviewsAggregate)
{
$avgPageviewsAggregate->fetch(Argument::any())
->shouldBeCalled()
->willReturn(12);
$graph = new Graph();
$graph->setKey('avgpageviews-mau_unique-day-10')
->setLastSynced(time())
->setData(12);
$this->repository->add($graph)
->shouldBeCalled();
$this->mappings->getMapping('avgpageviews')
->shouldBeCalled()
->willReturn($avgPageviewsAggregate);
$this->sync([
'aggregate' => 'avgpageviews',
'key' => 'mau_unique',
'span' => 10,
'unit' => 'day',
]);
}
}