Zenoss Custom Notification Actions Using Subscribers

In a previous post I talked about how we could create custom notifications actions in Zenoss. Like a SMS notification, for example. In that post we required a valid cellphone number using a text field in the notification's content pane, as shown below:

Notification Content

In this post I want to change and improve this by using subscribers functionality instead. Similar to the e-mail (or pager) notification, which sends an e-mail to all the subscribed users using their e-mail address configured in their user settings. Since there is no SMS mobile number that we can configure in the user settings, we will have to use the Pager field instead.

The Pager Action

Using Zenoss Core 4's pager action's source code as reference is a good starting point, since we are going to use the pager field for SMS.

We can see that this action class implements a executeOnTarget method instead of a execute method we used in the previous post.


Read more…

Python Functional HTTP Testing With Gabbi

Continuing with my journey in contributing to Gnocchi, I have learned of an excellent tool which Gnocchi uses to test its API from a HTTP request approach. The tool is called Gabbi.

Coming from a Ruby, Rails, and Rspec background, I was very pleased on learning how Gabbi works and how to use it. Gabbi uses YAML to construct the tests that will hit the API endpoints, in a similar way to using Rspec's DSL when making request specs.

For my latest contribution to Gnocchi, I was working on an issue where newly created metrics were not being returned in the response from /v1/resource/generic/:id/metric. After applying the fixes and submitting the patch, it was also necessary to update some of the functional Gabbi tests that belong to this specific use case.

One of these original tests is shown below:


Read more…

Understanding Gnocchi Archive Policies

In Gnocchi, metrics can contain archive policies. Archive policies define how the data will be agregated for a metric using different available agregation methods. They also determine how long measures will be kept in a metric.

Gnocchi comes with some pre-built in archive policies. We can list them using the Gnocchi client to get a better understanding of the information they contain:

+--------+-------------+-----------------------------------------------------------------------+---------------------------------+
| name   | back_window | definition                                                            | aggregation_methods             |
+--------+-------------+-----------------------------------------------------------------------+---------------------------------+
| high   |           0 | - points: 3600, granularity: 0:00:01, timespan: 1:00:00               | std, count, min, max, sum, mean |
|        |             | - points: 10080, granularity: 0:01:00, timespan: 7 days, 0:00:00      |                                 |
|        |             | - points: 8760, granularity: 1:00:00, timespan: 365 days, 0:00:00     |                                 |
| medium |           0 | - points: 10080, granularity: 0:01:00, timespan: 7 days, 0:00:00      | std, count, min, max, sum, mean |
|        |             | - points: 8760, granularity: 1:00:00, timespan: 365 days, 0:00:00     |                                 |
| bool   |        3600 | - points: 31536000, granularity: 0:00:01, timespan: 365 days, 0:00:00 | last                            |
| low    |           0 | - points: 8640, granularity: 0:05:00, timespan: 30 days, 0:00:00      | std, count, min, max, sum, mean |
+--------+-------------+-----------------------------------------------------------------------+---------------------------------+

As we can see, each archive policy can have different agregation methods. These methods will be applied to a metric, given that the metric has the archive policy.


Read more…

Testing JSON API Strong Parameters in Rails

Recently I was experiencing a problem with a Rails API where I would update a model with new attributes, and then proceeded to add the new attributes to the model's factory, and then add the corresponding model and request specs.

The problem was that I would forget to whitelist the new attributes in the controller. Then running the request specs would not detect the error since I only test against one updated attribute that was whitelisted long ago. This became really annoying since I had no way to know if the new attributes were being whitelisted or not, and my tests weren't saying anything about it. This problem becomes even more apparent when the list of whitelisted attributes starts becoming very long.

In an API following the JSON API specification, here is an example of how the strong parameters method would look like:

def thing_params
  params.require(:data).require(:attributes).permit(:color, :size, :age, :name,
      :owner, :origin, :location, :purpose, :price, :alive)
end

As you can see, the list of attributes is getting pretty long. And we do not want to explicitly keep adding more attributes to the test.

Testing Strong Parameters in Controller Specs

After the release of Rails 5 I started ditching controller specs in favor of request specs. I like this approach and I think it's great, but I think it would be too much unecessary work to test that all the necessary attributes are whitelisted, in the request spec. Therefore I proceeded to create very simple controller specs that would test that all attributes of importance are whitelisted in the controller.


Read more…

Understanding Gnocchi Measures

Measures are simple objects that represent the timeseries data. They simply contain a timestamp and a value, and they belong to metrics. You could say that a measure has many metrics.

Adding Measures to a Metric

Using the REST API, we can easily add measures to a metric:

POST /v1/metric/511b61a1-8d67-42d5-8add-66d4209a0469/measures HTTP/1.1
Content-Type: application/json
Content-Length: 198

[
  {
    "timestamp": "2014-10-06T14:33:57",
    "value": 43.1
  },
  {
    "timestamp": "2014-10-06T14:34:12",
    "value": 12
  },
  {
    "timestamp": "2014-10-06T14:34:20",
    "value": 2
  }
]

Read more…