Пример #1
0
static void
cockpit_metrics_close (CockpitChannel *channel,
                       const gchar *problem)
{
  CockpitMetrics *self = COCKPIT_METRICS (channel);

  if (self->priv->timeout)
    {
      g_source_remove (self->priv->timeout);
      self->priv->timeout = 0;
    }

  COCKPIT_CHANNEL_CLASS (cockpit_metrics_parent_class)->close (channel, problem);
}
Пример #2
0
static void
cockpit_metrics_dispose (GObject *object)
{
  CockpitMetrics *self = COCKPIT_METRICS (object);

  if (self->priv->timeout)
    {
      g_source_remove (self->priv->timeout);
      self->priv->timeout = 0;
    }

  if (self->priv->last_meta)
    {
      json_object_unref (self->priv->last_meta);
      self->priv->last_meta = NULL;
    }

  if (self->priv->last_data)
    {
      g_free (self->priv->last_data[0]);
      g_free (self->priv->last_data);
      self->priv->last_data = NULL;
    }

  if (self->priv->next_meta)
    {
      json_object_unref (self->priv->next_meta);
      self->priv->next_meta = NULL;
    }

  if (self->priv->next_data)
    {
      g_free (self->priv->next_data[0]);
      g_free (self->priv->next_data);
      self->priv->next_data = NULL;
    }

  if (self->priv->derived)
    {
      g_free (self->priv->derived[0]);
      g_free (self->priv->derived);
      self->priv->derived = NULL;
    }

  g_free (self->priv->metric_info);
  self->priv->metric_info = NULL;

  G_OBJECT_CLASS (cockpit_metrics_parent_class)->dispose (object);
}
Пример #3
0
static void
cockpit_internal_metrics_prepare (CockpitChannel *channel)
{
  CockpitInternalMetrics *self = COCKPIT_INTERNAL_METRICS (channel);
  JsonObject *options;
  JsonArray *metrics;
  int i;

  COCKPIT_CHANNEL_CLASS (cockpit_internal_metrics_parent_class)->prepare (channel);

  options = cockpit_channel_get_options (channel);

  /* "instances" option */
  if (!cockpit_json_get_strv (options, "instances", NULL, (gchar ***)&self->instances))
    {
      cockpit_channel_fail (channel, "protocol-error",
                            "invalid \"instances\" option (not an array of strings)");
      return;
    }

  /* "omit-instances" option */
  if (!cockpit_json_get_strv (options, "omit-instances", NULL, (gchar ***)&self->omit_instances))
    {
      cockpit_channel_fail (channel, "protocol-error",
                            "invalid \"omit-instances\" option (not an array of strings)");
      return;
    }

  /* "metrics" option */
  self->n_metrics = 0;
  if (!cockpit_json_get_array (options, "metrics", NULL, &metrics))
    {
      cockpit_channel_fail (channel, "protocol-error",
                            "invalid \"metrics\" option was specified (not an array)");
      return;
    }
  if (metrics)
    self->n_metrics = json_array_get_length (metrics);

  self->metrics = g_new0 (MetricInfo, self->n_metrics);
  for (i = 0; i < self->n_metrics; i++)
    {
      MetricInfo *info = &self->metrics[i];
      if (!convert_metric_description (self, json_array_get_element (metrics, i), info, i))
        return;
      if (!info->desc)
        {
          cockpit_channel_close (channel, "not-supported");
          return;
        }
    }

  /* "interval" option */
  if (!cockpit_json_get_int (options, "interval", 1000, &self->interval))
    {
      cockpit_channel_fail (channel, "protocol-error", "invalid \"interval\" option");
      return;
    }
  else if (self->interval <= 0 || self->interval > G_MAXINT)
    {
      cockpit_channel_fail (channel, "protocol-error",
                            "invalid \"interval\" value: %" G_GINT64_FORMAT, self->interval);
      return;
    }

  self->need_meta = TRUE;

  cockpit_metrics_metronome (COCKPIT_METRICS (self), self->interval);
  cockpit_channel_ready (channel, NULL);
}
Пример #4
0
static void
cockpit_internal_metrics_tick (CockpitMetrics *metrics,
                               gint64 timestamp)
{
  CockpitInternalMetrics *self = (CockpitInternalMetrics *)metrics;
  struct timeval now_timeval;
  gint64 now;

  gettimeofday (&now_timeval, NULL);
  now = timestamp_from_timeval (&now_timeval);

  /* Reset samples
   */
  for (int i = 0; i < self->n_metrics; i++)
    {
      MetricInfo *info = &self->metrics[i];
      if (info->desc->instanced)
        g_hash_table_foreach (info->instances, instance_reset, NULL);
      else
        info->value = NAN;
    }

  /* Sample
   */
  if (self->samplers & CPU_SAMPLER)
    cockpit_cpu_samples (COCKPIT_SAMPLES (self));
  if (self->samplers & MEMORY_SAMPLER)
    cockpit_memory_samples (COCKPIT_SAMPLES (self));
  if (self->samplers & BLOCK_SAMPLER)
    cockpit_block_samples (COCKPIT_SAMPLES (self));
  if (self->samplers & NETWORK_SAMPLER)
    cockpit_network_samples (COCKPIT_SAMPLES (self));
  if (self->samplers & MOUNT_SAMPLER)
    cockpit_mount_samples (COCKPIT_SAMPLES (self));
  if (self->samplers & CGROUP_SAMPLER)
    cockpit_cgroup_samples (COCKPIT_SAMPLES (self));
  if (self->samplers & DISK_SAMPLER)
    cockpit_disk_samples (COCKPIT_SAMPLES (self));

  /* Check for disappeared instances
   */
  for (int i = 0; i < self->n_metrics; i++)
    {
      MetricInfo *info = &self->metrics[i];
      if (info->desc->instanced)
        if (g_hash_table_foreach_remove (info->instances, instance_unseen, NULL) > 0)
          self->need_meta = TRUE;
    }

  /* Send a meta message if necessary.  This will also allocate a new
     buffer and setup the instance indices.
   */
  if (self->need_meta)
    {
      send_meta (self);
      self->need_meta = FALSE;
    }

  /* Ship them out
   */
  double **buffer = cockpit_metrics_get_data_buffer (COCKPIT_METRICS (self));
  for (int i = 0; i < self->n_metrics; i++)
    {
      MetricInfo *info = &self->metrics[i];
      if (info->desc->instanced)
        {
          GHashTableIter iter;
          gpointer key, value;

          g_hash_table_iter_init (&iter, info->instances);
          while (g_hash_table_iter_next (&iter, &key, &value))
            {
              InstanceInfo *inst = value;
              buffer[i][inst->index] = inst->value;
            }
        }
      else
        buffer[i][0] = info->value;
    }

  cockpit_metrics_send_data (COCKPIT_METRICS (self), now);
  cockpit_metrics_flush_data (COCKPIT_METRICS (self));
}
Пример #5
0
static void
send_meta (CockpitInternalMetrics *self)
{
  JsonArray *metrics;
  JsonObject *metric;
  JsonObject *root;
  struct timeval now_timeval;
  gint64 now;

  gettimeofday (&now_timeval, NULL);
  now = timestamp_from_timeval (&now_timeval);

  root = json_object_new ();
  json_object_set_int_member (root, "timestamp", now);
  json_object_set_int_member (root, "now", now);
  json_object_set_int_member (root, "interval", self->interval);

  metrics = json_array_new ();
  for (int i = 0; i < self->n_metrics; i++)
    {
      MetricInfo *info = &self->metrics[i];
      metric = json_object_new ();

      /* Name and derivation mode
       */
      json_object_set_string_member (metric, "name", info->desc->name);
      if (info->derive)
        json_object_set_string_member (metric, "derive", info->derive);

      /* Instances
       */
      if (info->desc->instanced)
        {
          GHashTableIter iter;
          gpointer key, value;
          int index;
          JsonArray *instances = json_array_new ();

          g_hash_table_iter_init (&iter, info->instances);
          index = 0;
          while (g_hash_table_iter_next (&iter, &key, &value))
            {
              const gchar *name = key;
              InstanceInfo *inst = value;

              /* HACK: We can't use json_builder_add_string_value here since
                 it turns empty strings into 'null' values inside arrays.

                 https://bugzilla.gnome.org/show_bug.cgi?id=730803
              */
              {
                JsonNode *string_element = json_node_alloc ();
                json_node_init_string (string_element, name);
                json_array_add_element (instances, string_element);
              }

              inst->index = index++;
            }
          json_object_set_array_member (metric, "instances", instances);
        }

      /* Units and semantics
       */
      json_object_set_string_member (metric, "units", info->desc->units);
      json_object_set_string_member (metric, "semantics", info->desc->semantics);

      json_array_add_object_element (metrics, metric);
    }

  json_object_set_array_member (root, "metrics", metrics);

  cockpit_metrics_send_meta (COCKPIT_METRICS (self), root, FALSE);

  json_object_unref (root);
}