Added support for new stats ranges
This commit is contained in:
parent
eba0a21eee
commit
17347440d1
|
@ -153,28 +153,55 @@ $utopia->get('/v1/projects/:projectId/usage')
|
|||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'getUsage')
|
||||
->param('projectId', '', function () { return new UID(); }, 'Project unique ID.')
|
||||
->param('range', 'monthly', function () { return new WhiteList(['daily', 'monthly', 'last30', 'last90']); }, 'Date range.', true)
|
||||
->action(
|
||||
function ($projectId) use ($response, $consoleDB, $projectDB, $register) {
|
||||
function ($projectId, $range) use ($response, $consoleDB, $projectDB, $register) {
|
||||
$project = $consoleDB->getDocument($projectId);
|
||||
|
||||
if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) {
|
||||
throw new Exception('Project not found', 404);
|
||||
}
|
||||
|
||||
$period = [
|
||||
'daily' => [
|
||||
'start' => DateTime::createFromFormat('U', strtotime('today')),
|
||||
'end' => DateTime::createFromFormat('U', strtotime('tomorrow')),
|
||||
'group' => '1m',
|
||||
],
|
||||
'monthly' => [
|
||||
'start' => DateTime::createFromFormat('U', strtotime('midnight first day of this month')),
|
||||
'end' => DateTime::createFromFormat('U', strtotime('midnight last day of this month')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'last30' => [
|
||||
'start' => DateTime::createFromFormat('U', strtotime('-30 days')),
|
||||
'end' => DateTime::createFromFormat('U', strtotime('today')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'last90' => [
|
||||
'start' => DateTime::createFromFormat('U', strtotime('-90 days')),
|
||||
'end' => DateTime::createFromFormat('U', strtotime('today')),
|
||||
'group' => '1d',
|
||||
],
|
||||
// 'yearly' => [
|
||||
// 'start' => DateTime::createFromFormat('U', strtotime('midnight first day of january')),
|
||||
// 'end' => DateTime::createFromFormat('U', strtotime('midnight last day of december')),
|
||||
// 'group' => '4w',
|
||||
// ],
|
||||
];
|
||||
|
||||
$client = $register->get('influxdb');
|
||||
|
||||
$requests = [];
|
||||
$network = [];
|
||||
|
||||
if ($client) {
|
||||
$start = DateTime::createFromFormat('U', strtotime('last day of last month'));
|
||||
$start = $start->format(DateTime::RFC3339);
|
||||
$end = DateTime::createFromFormat('U', strtotime('last day of this month'));
|
||||
$end = $end->format(DateTime::RFC3339);
|
||||
$start = $period[$range]['start']->format(DateTime::RFC3339);
|
||||
$end = $period[$range]['end']->format(DateTime::RFC3339);
|
||||
$database = $client->selectDB('telegraf');
|
||||
|
||||
// Requests
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_requests_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' GROUP BY time(1d) FILL(null)');
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_requests_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
|
@ -185,7 +212,7 @@ $utopia->get('/v1/projects/:projectId/usage')
|
|||
}
|
||||
|
||||
// Network
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_network_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' GROUP BY time(1d) FILL(null)');
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_network_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<div class="zone xl">
|
||||
<ul class="phases clear" data-ui-phases data-selected="{{router.params.tab}}">
|
||||
<li data-state="/console/database/collection?id={{router.params.id}}&project={{router.params.project}}">
|
||||
<a data-ls-attrs="href=/console/database/document?collection={{router.params.id}}&project={{router.params.project}}" class="button fly round text-align-center">
|
||||
<a xdata-ls-if="{{project-collection.rules.length}} > 0" data-ls-attrs="href=/console/database/document?collection={{router.params.id}}&project={{router.params.project}}" class="button fly round text-align-center">
|
||||
<i class="icon-plus"></i>
|
||||
</a>
|
||||
|
||||
|
@ -83,16 +83,16 @@
|
|||
<table class="vertical">
|
||||
<thead>
|
||||
<tr data-ls-loop="project-collection.rules" data-ls-as="rule">
|
||||
<th width="160" data-ls-bind="{{rule.label}}"></th>
|
||||
<th width="120" data-ls-bind="{{rule.label}}"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-ls-loop="project-documents.documents" data-ls-as="node">
|
||||
<tr data-ls-loop="project-collection.rules" data-ls-as="rule">
|
||||
<td data-ls-attrs="data-title={{rule.label}}:">
|
||||
<td data-ls-attrs="data-title={{rule.label}}:" class="text-size-small">
|
||||
<a data-ls-attrs="href=/console/database/document?id={{node.$id}}&collection={{router.params.id}}&project={{router.params.project}}">
|
||||
<span data-ls-if="{{rule.type}} !== 'document'" data-ls-bind="{{node|documentLabel}}"></span>
|
||||
<span data-ls-if="{{rule.type}} == 'document' && {{rule.array}}">Linked Documents</span>
|
||||
<span data-ls-if="{{rule.type}} == 'document' && !{{rule.array}}" class="tag">Linked Document</span>
|
||||
<span data-ls-if="{{rule.type}} == 'document' && {{rule.array}}">[]</span>
|
||||
<span data-ls-if="{{rule.type}} == 'document' && !{{rule.array}}">{...}</span>
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
use Utopia\View;
|
||||
|
||||
$collection = $this->getParam('collection', null);
|
||||
$rules = $collection->getAttribute('rules', []);
|
||||
?>
|
||||
<div
|
||||
data-service="database.getCollection"
|
||||
|
@ -67,36 +68,41 @@ $collection = $this->getParam('collection', null);
|
|||
<label> </label>
|
||||
|
||||
<div class="box">
|
||||
<?php if(empty($rules)): ?>
|
||||
<div class="margin-bottom-xl margin-top-xl margin-end margin-start text-align-center">
|
||||
<h4 class="text-fade text-size-small">No attribute rules added yet.<br /><br /><a data-ls-attrs="href=/console/database/collection/update?id={{router.params.collection}}&project={{router.params.project}}">Update Collection</a></h4>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php
|
||||
|
||||
<?php
|
||||
$comp = new View(__DIR__.'/form.phtml');
|
||||
|
||||
$comp
|
||||
->setParam('collection', $collection)
|
||||
->setParam('namespace', 'project-document')
|
||||
->setParam('key', 'data')
|
||||
->setParam('parent', 1)
|
||||
;
|
||||
|
||||
$comp = new View(__DIR__.'/form.phtml');
|
||||
|
||||
$comp
|
||||
->setParam('collection', $collection)
|
||||
->setParam('namespace', 'project-document')
|
||||
->setParam('key', 'data')
|
||||
->setParam('parent', 1)
|
||||
;
|
||||
echo $comp->render();
|
||||
?>
|
||||
|
||||
echo $comp->render();
|
||||
?>
|
||||
<div class="toggle margin-bottom" data-ls-ui-open>
|
||||
<i class="icon-plus pull-end margin-top-tiny"></i>
|
||||
<i class="icon-minus pull-end margin-top-tiny"></i>
|
||||
|
||||
<h3 class="margin-bottom-large">Permissions</h3>
|
||||
|
||||
<label for="collection-read">Read Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</span></label>
|
||||
<input type="hidden" id="collection-read" name="read" data-forms-tags data-cast-to="json" data-ls-bind="{{project-document.$permissions.read}}" placeholder="User ID, Team ID or Role" />
|
||||
|
||||
<label for="collection-write">Write Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</label>
|
||||
<input type="hidden" id="collection-write" name="write" data-forms-tags data-cast-to="json" data-ls-bind="{{project-collection.$permissions.write}}" placeholder="User ID, Team ID or Role" />
|
||||
</div>
|
||||
|
||||
<div class="toggle margin-bottom" data-ls-ui-open>
|
||||
<i class="icon-plus pull-end margin-top-tiny"></i>
|
||||
<i class="icon-minus pull-end margin-top-tiny"></i>
|
||||
|
||||
<h3 class="margin-bottom-large">Permissions</h3>
|
||||
|
||||
<label for="collection-read">Read Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</span></label>
|
||||
<input type="hidden" id="collection-read" name="read" data-forms-tags data-cast-to="json" data-ls-bind="{{project-document.$permissions.read}}" placeholder="User ID, Team ID or Role" />
|
||||
|
||||
<label for="collection-write">Write Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</label>
|
||||
<input type="hidden" id="collection-write" name="write" data-forms-tags data-cast-to="json" data-ls-bind="{{project-collection.$permissions.write}}" placeholder="User ID, Team ID or Role" />
|
||||
</div>
|
||||
|
||||
<button data-ls-if="({{project-document.$id}})">Update</button>
|
||||
<button data-ls-if="(!{{project-document.$id}})">Create</button>
|
||||
<button data-ls-if="({{project-document.$id}})">Update</button>
|
||||
<button data-ls-if="(!{{project-document.$id}})">Create</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
|
|
@ -29,6 +29,7 @@ $namespace = $this->getParam('namespace', 'project-document');
|
|||
<input name="$collection" type="hidden" data-ls-bind="<?php echo $this->escape($collection->getId()); ?>" />
|
||||
<input name="$permissions" type="hidden" data-ls-bind="{{<?php echo $this->escape($namespace); ?>.$permissions}}" data-cast-to="json" />
|
||||
<?php endif; ?>
|
||||
|
||||
<ul>
|
||||
<?php foreach($rules as $rule):
|
||||
$key = (isset($rule['key'])) ? $rule['key'] : '';
|
||||
|
|
|
@ -28,7 +28,8 @@ $graph = $this->getParam('graph', false);
|
|||
data-service="projects.getUsage"
|
||||
data-event="load"
|
||||
data-name="usage"
|
||||
data-param-project-id="{{router.params.project}}">
|
||||
data-param-project-id="{{router.params.project}}"
|
||||
data-param-range="monthly">
|
||||
|
||||
<?php if (!$graph) : ?>
|
||||
<div class="row responsive">
|
||||
|
|
7
public/dist/scripts/app-all.js
vendored
7
public/dist/scripts/app-all.js
vendored
|
@ -57,7 +57,7 @@ if(success===undefined){throw new Error('Missing required parameter: "success"')
|
|||
if(failure===undefined){throw new Error('Missing required parameter: "failure"');}
|
||||
let path='/account/sessions/oauth2/{provider}'.replace(new RegExp('{provider}','g'),provider);let payload={};if(success){payload['success']=success;}
|
||||
if(failure){payload['failure']=failure;}
|
||||
payload['project']=config.project;payload['key']=config.key;let query=Object.keys(payload).map(key=>key+'='+encodeURIComponent(payload[key])).join('&');console.log(config);return config.endpoint+path+((query)?'?'+query:'');},deleteSession:function(sessionId){if(sessionId===undefined){throw new Error('Missing required parameter: "sessionId"');}
|
||||
payload['project']=config.project;payload['key']=config.key;let query=Object.keys(payload).map(key=>key+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},deleteSession:function(sessionId){if(sessionId===undefined){throw new Error('Missing required parameter: "sessionId"');}
|
||||
let path='/account/sessions/{sessionId}'.replace(new RegExp('{sessionId}','g'),sessionId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},createVerification:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"');}
|
||||
let path='/account/verification';let payload={};if(url){payload['url']=url;}
|
||||
return http.post(path,{'content-type':'application/json',},payload);},updateVerification:function(userId,secret){if(userId===undefined){throw new Error('Missing required parameter: "userId"');}
|
||||
|
@ -259,8 +259,9 @@ if(httpUser){payload['httpUser']=httpUser;}
|
|||
if(httpPass){payload['httpPass']=httpPass;}
|
||||
return http.put(path,{'content-type':'application/json',},payload);},deleteTask:function(projectId,taskId){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
|
||||
if(taskId===undefined){throw new Error('Missing required parameter: "taskId"');}
|
||||
let path='/projects/{projectId}/tasks/{taskId}'.replace(new RegExp('{projectId}','g'),projectId).replace(new RegExp('{taskId}','g'),taskId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getUsage:function(projectId){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
|
||||
let path='/projects/{projectId}/usage'.replace(new RegExp('{projectId}','g'),projectId);let payload={};return http.get(path,{'content-type':'application/json',},payload);},listWebhooks:function(projectId){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
|
||||
let path='/projects/{projectId}/tasks/{taskId}'.replace(new RegExp('{projectId}','g'),projectId).replace(new RegExp('{taskId}','g'),taskId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getUsage:function(projectId,range='monthly'){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
|
||||
let path='/projects/{projectId}/usage'.replace(new RegExp('{projectId}','g'),projectId);let payload={};if(range){payload['range']=range;}
|
||||
return http.get(path,{'content-type':'application/json',},payload);},listWebhooks:function(projectId){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
|
||||
let path='/projects/{projectId}/webhooks'.replace(new RegExp('{projectId}','g'),projectId);let payload={};return http.get(path,{'content-type':'application/json',},payload);},createWebhook:function(projectId,name,events,url,security,httpUser='',httpPass=''){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
|
||||
if(name===undefined){throw new Error('Missing required parameter: "name"');}
|
||||
if(events===undefined){throw new Error('Missing required parameter: "events"');}
|
||||
|
|
7
public/dist/scripts/app-dep.js
vendored
7
public/dist/scripts/app-dep.js
vendored
|
@ -57,7 +57,7 @@ if(success===undefined){throw new Error('Missing required parameter: "success"')
|
|||
if(failure===undefined){throw new Error('Missing required parameter: "failure"');}
|
||||
let path='/account/sessions/oauth2/{provider}'.replace(new RegExp('{provider}','g'),provider);let payload={};if(success){payload['success']=success;}
|
||||
if(failure){payload['failure']=failure;}
|
||||
payload['project']=config.project;payload['key']=config.key;let query=Object.keys(payload).map(key=>key+'='+encodeURIComponent(payload[key])).join('&');console.log(config);return config.endpoint+path+((query)?'?'+query:'');},deleteSession:function(sessionId){if(sessionId===undefined){throw new Error('Missing required parameter: "sessionId"');}
|
||||
payload['project']=config.project;payload['key']=config.key;let query=Object.keys(payload).map(key=>key+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},deleteSession:function(sessionId){if(sessionId===undefined){throw new Error('Missing required parameter: "sessionId"');}
|
||||
let path='/account/sessions/{sessionId}'.replace(new RegExp('{sessionId}','g'),sessionId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},createVerification:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"');}
|
||||
let path='/account/verification';let payload={};if(url){payload['url']=url;}
|
||||
return http.post(path,{'content-type':'application/json',},payload);},updateVerification:function(userId,secret){if(userId===undefined){throw new Error('Missing required parameter: "userId"');}
|
||||
|
@ -259,8 +259,9 @@ if(httpUser){payload['httpUser']=httpUser;}
|
|||
if(httpPass){payload['httpPass']=httpPass;}
|
||||
return http.put(path,{'content-type':'application/json',},payload);},deleteTask:function(projectId,taskId){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
|
||||
if(taskId===undefined){throw new Error('Missing required parameter: "taskId"');}
|
||||
let path='/projects/{projectId}/tasks/{taskId}'.replace(new RegExp('{projectId}','g'),projectId).replace(new RegExp('{taskId}','g'),taskId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getUsage:function(projectId){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
|
||||
let path='/projects/{projectId}/usage'.replace(new RegExp('{projectId}','g'),projectId);let payload={};return http.get(path,{'content-type':'application/json',},payload);},listWebhooks:function(projectId){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
|
||||
let path='/projects/{projectId}/tasks/{taskId}'.replace(new RegExp('{projectId}','g'),projectId).replace(new RegExp('{taskId}','g'),taskId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getUsage:function(projectId,range='monthly'){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
|
||||
let path='/projects/{projectId}/usage'.replace(new RegExp('{projectId}','g'),projectId);let payload={};if(range){payload['range']=range;}
|
||||
return http.get(path,{'content-type':'application/json',},payload);},listWebhooks:function(projectId){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
|
||||
let path='/projects/{projectId}/webhooks'.replace(new RegExp('{projectId}','g'),projectId);let payload={};return http.get(path,{'content-type':'application/json',},payload);},createWebhook:function(projectId,name,events,url,security,httpUser='',httpPass=''){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
|
||||
if(name===undefined){throw new Error('Missing required parameter: "name"');}
|
||||
if(events===undefined){throw new Error('Missing required parameter: "events"');}
|
||||
|
|
|
@ -2784,7 +2784,7 @@
|
|||
* @throws {Error}
|
||||
* @return {Promise}
|
||||
*/
|
||||
getUsage: function(projectId) {
|
||||
getUsage: function(projectId, range = 'monthly') {
|
||||
if(projectId === undefined) {
|
||||
throw new Error('Missing required parameter: "projectId"');
|
||||
}
|
||||
|
@ -2793,6 +2793,10 @@
|
|||
|
||||
let payload = {};
|
||||
|
||||
if(range) {
|
||||
payload['range'] = range;
|
||||
}
|
||||
|
||||
return http
|
||||
.get(path, {
|
||||
'content-type': 'application/json',
|
||||
|
|
Loading…
Reference in a new issue