1
0
Fork 0
mirror of synced 2024-06-26 10:10:57 +12:00

Added support for new stats ranges

This commit is contained in:
Eldad Fux 2020-04-24 14:24:04 +03:00
parent eba0a21eee
commit 17347440d1
8 changed files with 87 additions and 46 deletions

View file

@ -153,28 +153,55 @@ $utopia->get('/v1/projects/:projectId/usage')
->label('sdk.namespace', 'projects') ->label('sdk.namespace', 'projects')
->label('sdk.method', 'getUsage') ->label('sdk.method', 'getUsage')
->param('projectId', '', function () { return new UID(); }, 'Project unique ID.') ->param('projectId', '', function () { return new UID(); }, 'Project unique ID.')
->param('range', 'monthly', function () { return new WhiteList(['daily', 'monthly', 'last30', 'last90']); }, 'Date range.', true)
->action( ->action(
function ($projectId) use ($response, $consoleDB, $projectDB, $register) { function ($projectId, $range) use ($response, $consoleDB, $projectDB, $register) {
$project = $consoleDB->getDocument($projectId); $project = $consoleDB->getDocument($projectId);
if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { if (empty($project->getId()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) {
throw new Exception('Project not found', 404); 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'); $client = $register->get('influxdb');
$requests = []; $requests = [];
$network = []; $network = [];
if ($client) { if ($client) {
$start = DateTime::createFromFormat('U', strtotime('last day of last month')); $start = $period[$range]['start']->format(DateTime::RFC3339);
$start = $start->format(DateTime::RFC3339); $end = $period[$range]['end']->format(DateTime::RFC3339);
$end = DateTime::createFromFormat('U', strtotime('last day of this month'));
$end = $end->format(DateTime::RFC3339);
$database = $client->selectDB('telegraf'); $database = $client->selectDB('telegraf');
// Requests // 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(); $points = $result->getPoints();
foreach ($points as $point) { foreach ($points as $point) {
@ -185,7 +212,7 @@ $utopia->get('/v1/projects/:projectId/usage')
} }
// Network // 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(); $points = $result->getPoints();
foreach ($points as $point) { foreach ($points as $point) {

View file

@ -31,7 +31,7 @@
<div class="zone xl"> <div class="zone xl">
<ul class="phases clear" data-ui-phases data-selected="{{router.params.tab}}"> <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}}"> <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> <i class="icon-plus"></i>
</a> </a>
@ -83,16 +83,16 @@
<table class="vertical"> <table class="vertical">
<thead> <thead>
<tr data-ls-loop="project-collection.rules" data-ls-as="rule"> <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> </tr>
</thead> </thead>
<tbody data-ls-loop="project-documents.documents" data-ls-as="node"> <tbody data-ls-loop="project-documents.documents" data-ls-as="node">
<tr data-ls-loop="project-collection.rules" data-ls-as="rule"> <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}}"> <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'" 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}}">[]</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>
</a> </a>
</th> </th>
</tr> </tr>

View file

@ -2,6 +2,7 @@
use Utopia\View; use Utopia\View;
$collection = $this->getParam('collection', null); $collection = $this->getParam('collection', null);
$rules = $collection->getAttribute('rules', []);
?> ?>
<div <div
data-service="database.getCollection" data-service="database.getCollection"
@ -67,36 +68,41 @@ $collection = $this->getParam('collection', null);
<label>&nbsp;</label> <label>&nbsp;</label>
<div class="box"> <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'); echo $comp->render();
?>
$comp
->setParam('collection', $collection)
->setParam('namespace', 'project-document')
->setParam('key', 'data')
->setParam('parent', 1)
;
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> <button data-ls-if="({{project-document.$id}})">Update</button>
<i class="icon-plus pull-end margin-top-tiny"></i> <button data-ls-if="(!{{project-document.$id}})">Create</button>
<i class="icon-minus pull-end margin-top-tiny"></i> <?php endif; ?>
<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>
</div> </div>
</form> </form>

View file

@ -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="$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" /> <input name="$permissions" type="hidden" data-ls-bind="{{<?php echo $this->escape($namespace); ?>.$permissions}}" data-cast-to="json" />
<?php endif; ?> <?php endif; ?>
<ul> <ul>
<?php foreach($rules as $rule): <?php foreach($rules as $rule):
$key = (isset($rule['key'])) ? $rule['key'] : ''; $key = (isset($rule['key'])) ? $rule['key'] : '';

View file

@ -28,7 +28,8 @@ $graph = $this->getParam('graph', false);
data-service="projects.getUsage" data-service="projects.getUsage"
data-event="load" data-event="load"
data-name="usage" data-name="usage"
data-param-project-id="{{router.params.project}}"> data-param-project-id="{{router.params.project}}"
data-param-range="monthly">
<?php if (!$graph) : ?> <?php if (!$graph) : ?>
<div class="row responsive"> <div class="row responsive">

View file

@ -57,7 +57,7 @@ if(success===undefined){throw new Error('Missing required parameter: "success"')
if(failure===undefined){throw new Error('Missing required parameter: "failure"');} 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;} let path='/account/sessions/oauth2/{provider}'.replace(new RegExp('{provider}','g'),provider);let payload={};if(success){payload['success']=success;}
if(failure){payload['failure']=failure;} 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/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;} 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"');} 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;} 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"');} 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"');} 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}/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={};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}/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"');} 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(name===undefined){throw new Error('Missing required parameter: "name"');}
if(events===undefined){throw new Error('Missing required parameter: "events"');} if(events===undefined){throw new Error('Missing required parameter: "events"');}

View file

@ -57,7 +57,7 @@ if(success===undefined){throw new Error('Missing required parameter: "success"')
if(failure===undefined){throw new Error('Missing required parameter: "failure"');} 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;} let path='/account/sessions/oauth2/{provider}'.replace(new RegExp('{provider}','g'),provider);let payload={};if(success){payload['success']=success;}
if(failure){payload['failure']=failure;} 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/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;} 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"');} 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;} 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"');} 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"');} 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}/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={};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}/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"');} 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(name===undefined){throw new Error('Missing required parameter: "name"');}
if(events===undefined){throw new Error('Missing required parameter: "events"');} if(events===undefined){throw new Error('Missing required parameter: "events"');}

View file

@ -2784,7 +2784,7 @@
* @throws {Error} * @throws {Error}
* @return {Promise} * @return {Promise}
*/ */
getUsage: function(projectId) { getUsage: function(projectId, range = 'monthly') {
if(projectId === undefined) { if(projectId === undefined) {
throw new Error('Missing required parameter: "projectId"'); throw new Error('Missing required parameter: "projectId"');
} }
@ -2793,6 +2793,10 @@
let payload = {}; let payload = {};
if(range) {
payload['range'] = range;
}
return http return http
.get(path, { .get(path, {
'content-type': 'application/json', 'content-type': 'application/json',