[openstack-dev] [Ceilometer] Complex query BP implementation

Jay Pipes jaypipes at gmail.com
Tue Dec 24 02:44:57 UTC 2013


On 12/16/2013 03:54 PM, Ildikó Váncsa wrote:
> Hi guys,
>
> The first working version of the Complex filter expressions in API
> queries blueprint [1] was pushed for review[2].
>
> We implemented a new query REST resource in order to provide rich query
> functionality for samples, alarms and alarm history. The future plans
> (in separated blueprints) with this new functionality is extending it to
> support Statistics and stored queries. The new feature is documented on
> Launchpad wiki[3], with an example for how to use the new query on the API.
>
> What is your opinion about this solution?
>
> I would appreciate some review comments and/or feedback on the
> implementation. :)

Hi Ildiko, thanks for your proposed API for complex querying in 
Ceilometer. Unfortunately, I'm not a fan of the approach taken, but I do 
see some definite need/use cases here.

My main objection to the proposed solution is that it violates the 
principle in all of the OpenStack REST APIs that a POST request 
*creates* a resource. In the proposed API, you use:

POST /query/$resource

to actually retrieve records of type $resource. In all the other 
OpenStack REST APIs, the above request would create a $resource 
subresource of a "query" resource. And, to be honest, people expect HTTP 
REST APIs to use the GET HTTP method for querying, not POST. It's an 
anti-pattern to use POST in this way.

Now, that said... I think that the advanced query interface you propose 
does indeed have real-world, demanded use cases. Right now, you are 100% 
correct that the existing GET request filters are simplistic and don't 
support either aggregation or advanced union or intersection queries.

I would definitely be supportive of using POST to store "saved queries" 
(as you mention in your wiki page). However, the main query interface 
should remain the GET HTTP method, including for ad-hoc advanced querying.

So, what I would like to see is essentially a removal of the "query" 
resource, and instead tack on your advanced Ceilometer domain-specific 
language to the supported GET query arguments. This would have two 
advantages:

1) You will not need to re-implement the orderby and limit expressions. 
Virtually all other OpenStack APIs (including Ceilometer) use the 
"limit" and "sort_by" query parameters already, so those should be used 
as-is.

2) Users will already be familiar with the standard GET /samples, GET 
/alarms, etc query interface, and all they would need to learn is how to 
encode the advanced query parameters properly. No need to 
learn/implement new resource endpoints.

You used this English-language example of an advanced query:

"Check for cpu_util samples reported between 18:00-18:15 or between 
18:30 - 18:45 where the utilization is between 23 and 26 percent."

and had the following POST request JSON-ified body:

POST /query/meters
["and",
   ["and",
     ["and",
       ["=", "counter_name", "cpu_util"],
       [">", "counter_volume", 0.23]],
     ["and",
       ["=", "counter_name", "cpu_util"],
       ["<", "counter_volume", 0.26]]],
   ["or",
     ["and",
	  [">", "timestamp", "2013-12-01T18:00:00"],
	  ["<", "timestamp", "2013-12-01T18:15:00"]],
     ["and",
	  [">", "timestamp", "2013-12-01T18:30:00"],
	  ["<", "timestamp", "2013-12-01T18:45:00"]]]]

(note that the above doesn't actually correspond to the English-language 
query... you would not want the third-level "and"s and you would want >= 
and <= for the temporal BETWEEN clause...)

The equivalent GET request might be encoded like so:

GET 
/meters?expr=(expr1%20or%20expr2)%20and%20expr3&expr1=(timestamp%3E%3D2013-12-01T18%3A00%3A00%20and%20timestamp%3C%3D2013-12-01T18%3A15%3A00)&expr2=(timestamp%3E%3D2013-12-01T18%3A30%3A00%20and%20timestamp%3C%3D2013-12-01T18%3A45%3A00)&expr3=(counter_name%3D%27cpu_util%27%20and%20(counter_volume%20%3E%200.23%20and%20counter_volume%20%3C%200.26))

Which is just the following, with the values url-encoded:

expr = (expr1 or expr2) and expr3
expr1 = (timestamp>=2013-12-01T18:00:00 and timestamp<=2013-12-01T18:15:00 )
expr2 = (timestamp>=2013-12-01T18:30:00 and timestamp<=2013-12-01T18:45:00)
expr3 = (counter_name='cpu_util' and (counter_volume>0.23 and 
counter_volume<0.26))

I know the expression might not look as nice as POST /query/meters, but 
it is in-line with Internet custom.

I would definitely support the use of your POST with JSON-encoded query 
DSL for stored views, though. For example, to save a stored query for 
the above report:

POST /reports
["and",
   ["and",
       ["=", "counter_name", "cpu_util"],
       ["between", "counter_volume", 0.23, 0.26],
   ["or",
     ["and",
	  [">", "timestamp", "2013-12-01T18:00:00"],
	  ["<", "timestamp", "2013-12-01T18:15:00"]],
     ["and",
	  [">", "timestamp", "2013-12-01T18:30:00"],
	  ["<", "timestamp", "2013-12-01T18:45:00"]]]]

And then you could issue the same query using the GET of the returned 
report UUID or report name...

GET /reports/$REPORT_ID

Best,
-jay

> [1]
> https://blueprints.launchpad.net/ceilometer/+spec/complex-filter-expressions-in-api-queries
>
>
> [2]
> https://review.openstack.org/#/q/status:open+project:openstack/ceilometer+branch:master+topic:bp/complex-filter-expressions-in-api-queries,n,z
>
>
> [3]
> https://wiki.openstack.org/wiki/Ceilometer/ComplexFilterExpressionsInAPIQueries
>
> Thanks and Best Regards,
>
> Ildiko
>
>
>
> _______________________________________________
> OpenStack-dev mailing list
> OpenStack-dev at lists.openstack.org
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>




More information about the OpenStack-dev mailing list