rest: allow to create missing metrics when sending measures in batch

Change-Id: If1f684ad368d4fb797267bbc4c099938f2722dfe
This commit is contained in:
Julien Danjou 2016-10-10 16:56:44 +02:00
parent b1fe83142c
commit f9b19ad8d0
6 changed files with 105 additions and 6 deletions

View File

@ -121,6 +121,11 @@ Or using named metrics of resources:
{{ scenarios['post-measures-batch-named']['doc'] }}
If some named metrics specified in the batch request do not exist, Gnocchi can
try to create them as long as an archive policy rule matches:
{{ scenarios['post-measures-batch-named-create']['doc'] }}
Archive Policy
==============

View File

@ -550,6 +550,20 @@
}
}
- name: post-measures-batch-named-create
request: |
POST /v1/batch/resources/metrics/measures?create_metrics=true HTTP/1.1
Content-Type: application/json
{
"{{ scenarios['create-resource-with-new-metrics']['response'].json['id'] }}": {
"disk.io.test": [
{ "timestamp": "2014-10-06T14:34:12", "value": 71 },
{ "timestamp": "2014-10-06T14:34:20", "value": 81 }
]
}
}
- name: delete-resource-generic
request: DELETE /v1/resource/generic/{{ scenarios['create-resource-generic']['response'].json['id'] }} HTTP/1.1

View File

@ -653,6 +653,8 @@ class SQLAlchemyIndexer(indexer.IndexerDriver):
if (e.constraint ==
'fk_metric_ap_name_ap_name'):
raise indexer.NoSuchArchivePolicy(archive_policy_name)
if e.constraint == 'fk_metric_resource_id_resource_id':
raise indexer.NoSuchResource(resource_id)
raise
return m

View File

@ -51,8 +51,9 @@ def abort(status_code, detail='', headers=None, comment=None, **kw):
"""Like pecan.abort, but make sure detail is a string."""
if status_code == 404 and not detail:
raise RuntimeError("http code 404 must have 'detail' set")
return pecan.abort(status_code, six.text_type(detail),
headers, comment, **kw)
if isinstance(detail, Exception):
detail = six.text_type(detail)
return pecan.abort(status_code, detail, headers, comment, **kw)
def get_user_and_project():
@ -1394,8 +1395,8 @@ class ResourcesMetricsMeasuresBatchController(rest.RestController):
{utils.ResourceUUID: {six.text_type: MeasuresListSchema}}
)
@pecan.expose()
def post(self):
@pecan.expose('json')
def post(self, create_metrics=False):
body = deserialize_and_validate(self.MeasuresBatchSchema)
known_metrics = []
@ -1405,8 +1406,35 @@ class ResourcesMetricsMeasuresBatchController(rest.RestController):
metrics = pecan.request.indexer.list_metrics(
names=names, resource_id=resource_id)
if len(names) != len(metrics):
known_names = [m.name for m in metrics]
known_names = [m.name for m in metrics]
if strutils.bool_from_string(create_metrics):
user_id, project_id = get_user_and_project()
unknown_resources = set()
for name in names:
if name not in known_names:
metric = MetricsController.MetricSchema({
"name": name
})
try:
pecan.request.indexer.create_metric(
uuid.uuid4(),
user_id, project_id,
resource_id=resource_id,
name=metric.get('name'),
unit=metric.get('unit'),
archive_policy_name=metric[
'archive_policy_name'])
except indexer.NoSuchResource as e:
unknown_resources.add(resource_id)
except indexer.IndexerException as e:
# This catch NoSuchArchivePolicy, which is unlikely
# be still possible
abort(400, e)
if unknown_resources:
abort(400, {"cause": "Unknown resources",
"detail": unknown_resources})
elif len(names) != len(metrics):
unknown_metrics.extend(
["%s/%s" % (six.text_type(resource_id), m)
for m in names if m not in known_names])

View File

@ -160,3 +160,48 @@ tests:
- timestamp: "2015-03-06T14:34:12"
value: 12
status: 202
- name: create archive policy rule for auto
POST: /v1/archive_policy_rule
request_headers:
content-type: application/json
x-roles: admin
data:
name: rule_auto
metric_pattern: "auto.*"
archive_policy_name: simple
status: 201
- name: push measurements to unknown named metrics and create it
POST: /v1/batch/resources/metrics/measures?create_metrics=true
request_headers:
content-type: application/json
data:
46c9418d-d63b-4cdd-be89-8f57ffc5952e:
auto.test:
- timestamp: "2015-03-06T14:33:57"
value: 43.1
- timestamp: "2015-03-06T14:34:12"
value: 12
status: 202
- name: get created metric to check creation
GET: /v1/resource/generic/46c9418d-d63b-4cdd-be89-8f57ffc5952e/metric/auto.test
- name: push measurements to unknown named metrics and resource with create_metrics
POST: /v1/batch/resources/metrics/measures?create_metrics=true
request_headers:
content-type: application/json
accept: application/json
data:
aaaaaaaa-d63b-4cdd-be89-111111111111:
auto.test:
- timestamp: "2015-03-06T14:33:57"
value: 43.1
- timestamp: "2015-03-06T14:34:12"
value: 12
status: 400
response_json_paths:
$.description.cause: "Unknown resources"
$.description.detail:
- "aaaaaaaa-d63b-4cdd-be89-111111111111"

View File

@ -0,0 +1,5 @@
---
features:
- "When sending measures in batch for resources, it is now possible to pass
`create_metric=true` to the query parameters so missing metrics are created.
This only works if an archive policy rule matching those named metrics matches."