Code

Annotate meta data for db plugins
authorMark Wong <mark.wong@myemma.com>
Thu, 9 May 2013 18:06:26 +0000 (11:06 -0700)
committerMark Wong <mark.wong@myemma.com>
Mon, 13 May 2013 17:26:58 +0000 (10:26 -0700)
Provide a MetadataFrom setting to name columns whose content is to be
added as metadata to the data collected.  Similar in usage to the
ValuesFrom setting.

src/collectd.conf.pod
src/utils_db_query.c

index 417af0d7082e09147de1777ec90e803a19b6fee5..8a2fc166d9b8857b1f7facc95d94a2bea9fe4bb5 100644 (file)
@@ -1243,6 +1243,16 @@ it should be able to handle integer an floating point types, as well as strings
 
 There must be at least one B<ValuesFrom> option inside each B<Result> block.
 
+=item B<MetadataFrom> [I<column0> I<column1> ...]
+
+Names the columns whose content is used as metadata for the data sets
+that are dispatched to the daemon. 
+
+The actual data type in the columns is not that important. The plugin will
+automatically cast the values to the right type if it know how to do that. So
+it should be able to handle integer an floating point types, as well as strings
+(if they include a number at the beginning).
+
 =back
 
 =head3 B<Database> blocks
index aadf9c5ec1d7f6a4879a5701ebe19f2a25d23633..df490e13e505a063885f472426079ceb91584359 100644 (file)
@@ -38,6 +38,8 @@ struct udb_result_s
   size_t   instances_num;
   char   **values;
   size_t   values_num;
+  char   **metadata;
+  size_t   metadata_num;
 
   udb_result_t *next;
 }; /* }}} */
@@ -59,8 +61,10 @@ struct udb_result_preparation_area_s /* {{{ */
   const   data_set_t *ds;
   size_t *instances_pos;
   size_t *values_pos;
+  size_t *metadata_pos;
   char  **instances_buffer;
   char  **values_buffer;
+  char  **metadata_buffer;
 
   struct udb_result_preparation_area_s *next;
 }; /* }}} */
@@ -188,6 +192,7 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */
 {
   value_list_t vl = VALUE_LIST_INIT;
   size_t i;
+  int status;
 
   assert (r != NULL);
   assert (r_area->ds != NULL);
@@ -253,8 +258,38 @@ static int udb_result_submit (udb_result_t *r, /* {{{ */
   vl.type_instance[sizeof (vl.type_instance) - 1] = 0;
   /* }}} */
 
+  /* Annotate meta data. {{{ */
+  if (r->metadata_num > 0)
+  {
+    vl.meta = meta_data_create ();
+    if (vl.meta == NULL)
+    {
+      ERROR ("db query utils:: meta_data_create failed.");
+      return (-ENOMEM);
+    }
+
+    for (i = 0; i < r->metadata_num; i++)
+    {
+      status = meta_data_add_string (vl.meta, r->metadata[i],
+          r_area->metadata_buffer[i]);
+      if (status != 0)
+      {
+        ERROR ("db query utils:: meta_data_add_string failed.");
+        meta_data_destroy (vl.meta);
+        vl.meta = NULL;
+        return (status);
+      }
+    }
+  }
+  /* }}} */
+
   plugin_dispatch_values (&vl);
 
+  if (r->metadata_num > 0)
+  {
+    meta_data_destroy (vl.meta);
+    vl.meta = NULL;
+  }
   sfree (vl.values);
   return (0);
 } /* }}} void udb_result_submit */
@@ -268,8 +303,10 @@ static void udb_result_finish_result (udb_result_t const *r, /* {{{ */
   prep_area->ds = NULL;
   sfree (prep_area->instances_pos);
   sfree (prep_area->values_pos);
+  sfree (prep_area->metadata_pos);
   sfree (prep_area->instances_buffer);
   sfree (prep_area->values_buffer);
+  sfree (prep_area->metadata_buffer);
 } /* }}} void udb_result_finish_result */
 
 static int udb_result_handle_result (udb_result_t *r, /* {{{ */
@@ -287,6 +324,9 @@ static int udb_result_handle_result (udb_result_t *r, /* {{{ */
   for (i = 0; i < r->values_num; i++)
     r_area->values_buffer[i] = column_values[r_area->values_pos[i]];
 
+  for (i = 0; i < r->metadata_num; i++)
+    r_area->metadata_buffer[i] = column_values[r_area->metadata_pos[i]];
+
   return udb_result_submit (r, r_area, q, q_area);
 } /* }}} int udb_result_handle_result */
 
@@ -303,14 +343,17 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
   prep_area->ds = NULL; \
   sfree (prep_area->instances_pos); \
   sfree (prep_area->values_pos); \
+  sfree (prep_area->metadata_pos); \
   sfree (prep_area->instances_buffer); \
   sfree (prep_area->values_buffer); \
+  sfree (prep_area->metadata_buffer); \
   return (status)
 
   /* Make sure previous preparations are cleaned up. */
   udb_result_finish_result (r, prep_area);
   prep_area->instances_pos = NULL;
   prep_area->values_pos = NULL;
+  prep_area->metadata_pos = NULL;
 
   /* Read `ds' and check number of values {{{ */
   prep_area->ds = plugin_get_ds (r->type);
@@ -333,8 +376,8 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
   }
   /* }}} */
 
-  /* Allocate r->instances_pos, r->values_pos, r->instances_buffer, and
-   * r->values_buffer {{{ */
+  /* Allocate r->instances_pos, r->values_pos, r->metadata_post,
+   * r->instances_buffer, r->values_buffer, and r->metadata_buffer {{{ */
   if (r->instances_num > 0)
   {
     prep_area->instances_pos
@@ -369,6 +412,23 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
     ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
     BAIL_OUT (-ENOMEM);
   }
+
+  prep_area->metadata_pos
+    = (size_t *) calloc (r->metadata_num, sizeof (size_t));
+  if (prep_area->metadata_pos == NULL)
+  {
+    ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+    BAIL_OUT (-ENOMEM);
+  }
+
+  prep_area->metadata_buffer
+    = (char **) calloc (r->metadata_num, sizeof (char *));
+  if (prep_area->metadata_buffer == NULL)
+  {
+    ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+    BAIL_OUT (-ENOMEM);
+  }
+
   /* }}} */
 
   /* Determine the position of the instance columns {{{ */
@@ -417,6 +477,29 @@ static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
     }
   } /* }}} for (i = 0; i < r->values_num; i++) */
 
+  /* Determine the position of the metadata columns {{{ */
+  for (i = 0; i < r->metadata_num; i++)
+  {
+    size_t j;
+
+    for (j = 0; j < column_num; j++)
+    {
+      if (strcasecmp (r->metadata[i], column_names[j]) == 0)
+      {
+        prep_area->metadata_pos[i] = j;
+        break;
+      }
+    }
+
+    if (j >= column_num)
+    {
+      ERROR ("db query utils: udb_result_prepare_result: "
+          "Metadata column `%s' could not be found.",
+          r->values[i]);
+      BAIL_OUT (-ENOENT);
+    }
+  } /* }}} for (i = 0; i < r->metadata_num; i++) */
+
 #undef BAIL_OUT
   return (0);
 } /* }}} int udb_result_prepare_result */
@@ -438,6 +521,10 @@ static void udb_result_free (udb_result_t *r) /* {{{ */
     sfree (r->values[i]);
   sfree (r->values);
 
+  for (i = 0; i < r->metadata_num; i++)
+    sfree (r->metadata[i]);
+  sfree (r->metadata);
+
   udb_result_free (r->next);
 
   sfree (r);
@@ -468,6 +555,7 @@ static int udb_result_create (const char *query_name, /* {{{ */
   r->instance_prefix = NULL;
   r->instances = NULL;
   r->values = NULL;
+  r->metadata = NULL;
   r->next = NULL;
 
   /* Fill the `udb_result_t' structure.. */
@@ -484,6 +572,8 @@ static int udb_result_create (const char *query_name, /* {{{ */
       status = udb_config_add_string (&r->instances, &r->instances_num, child);
     else if (strcasecmp ("ValuesFrom", child->key) == 0)
       status = udb_config_add_string (&r->values, &r->values_num, child);
+    else if (strcasecmp ("MetadataFrom", child->key) == 0)
+      status = udb_config_add_string (&r->metadata, &r->metadata_num, child);
     else
     {
       WARNING ("db query utils: Query `%s': Option `%s' not allowed here.",