Monitoring your Foxx applications

Note: this recipe is working with ArangoDB 2.5 Foxx

Problem

How to integrate a Foxx application into a monitoring system using the collectd curl_JSON plugin.

Solution

Since Foxx native tongue is JSON, integrating it with the collectd curl_JSON plugin should be an easy exercise. We have a Foxx-Application which can receive Data and write it into a collection. We specify an easy input Model:

  1. Model = Foxx.Model.extend({
  2. schema: {
  3. // Describe the attributes with Joi here
  4. '_key': Joi.string(),
  5. 'value': Joi.number()
  6. }
  7. });

And use a simple Foxx-Route to inject data into our collection:

  1. /** Creates a new FirstCollection
  2. *
  3. * Creates a new FirstCollection-Item. The information has to be in the
  4. * requestBody.
  5. */
  6. controller.post('/firstCollection', function (req, res) {
  7. var firstCollection = req.params('firstCollection');
  8. firstCollection.attributes.Date = Date.now();
  9. res.json(FirstCollection_repo.save(firstCollection).forClient());
  10. }).bodyParam('firstCollection', {
  11. description: 'The FirstCollection you want to create',
  12. type: FirstCollection
  13. });

Which we may do using cURL:

  1. echo '{"value":1 ,"_key":"13"}' | \
  2. curl -d @- http://localhost:8529/_db/_system/collectable_foxx/data/firstCollection/firstCollection

We’d expect the value to be in the range of 1 to 5. Maybe the source of this data is a web-poll or something similar.

We now add another Foxx-route which we want to link with collectd:

  1. /**
  2. * we use a group-by construct to get the values:
  3. */
  4. var db = require('org/arangodb').db;
  5. var searchQuery = 'FOR x IN @@collection FILTER x.Date >= @until collect value=x.value with count into counter RETURN {[[CONCAT("choice", value)] : counter }';
  6. controller.get('/firstCollection/lastSeconds/:nSeconds', function (req, res) {
  7. var until = Date.now() - req.params('nSeconds') * 1000;
  8. res.json(
  9. db._query(searchQuery, {
  10. '@collection': FirstCollection_repo.collection.name(),
  11. 'until': until
  12. }).toArray()
  13. );
  14. }).pathParam('nSeconds', {
  15. description: 'look up to n Seconds into the past',
  16. type: joi.string().required()
  17. });

We inspect the return document using curl and jq for nice formatting:

  1. curl 'http://localhost:8529/_db/_system/collectable_foxx/data/firstCollection/firstCollection/lastSeconds/10' |jq "."
  2. [
  3. {
  4. "1": 3
  5. "3": 7
  6. }
  7. ]

We have to design the return values in a way that collectd’s config syntax can simply grab it. This Route returns an object with flat key values where keys may range from 0 to 5. We create a simple collectd configuration in /etc/collectd/collectd.conf.d/foxx_simple.conf that matches our API:

  1. # Load the plug-in:
  2. LoadPlugin curl_json
  3. # we need to use our own types to generate individual names for our gauges:
  4. TypesDB "/etc/collectd/collectd.conf.d/foxx_simple_types.db"
  5. <Plugin curl_json>
  6. # Adjust the URL so collectd can reach your arangod:
  7. <URL "http://localhost:8529/_db/_system/collectable_foxx/data/firstCollection/firstCollection/lastSeconds/10">
  8. # Set your authentication to Aardvark here:
  9. # User "foo"
  10. # Password "bar"
  11. <Key "choice0">
  12. Type "the_values"
  13. </Key>
  14. <Key "choice1">
  15. Type "first_values"
  16. </Key>
  17. <Key "choice2">
  18. Type "second_values"
  19. </Key>
  20. <Key "choice3">
  21. Type "third_values"
  22. </Key>
  23. <Key "choice4">
  24. Type "fourth_values"
  25. </Key>
  26. <Key "choice5">
  27. Type "fifth_values"
  28. </Key>
  29. </URL>
  30. </Plugin>

To get nice metric names, we specify our own types.db file in /etc/collectd/collectd.conf.d/foxx_simple_types.db:

  1. the_values value:GAUGE:U:U
  2. first_values value:GAUGE:U:U
  3. second_values value:GAUGE:U:U
  4. third_values value:GAUGE:U:U
  5. fourth_values value:GAUGE:U:U
  6. fifth_values value:GAUGE:U:U