int prev_process_info__compute_load(cdtime_t tm, pid_t pid, unsigned long stime, unsigned long  utime, unsigned long *spercent, unsigned long *upercent) { /* {{{ */
/* Notes :
 * stime and utime are provided in machine unit (time or ticks) and will be converted in seconds here
 * tm is provided in cdtime_t (and will be converted into seconds here)
 * result values spercent and upercent are percent values
 * this function returns 0 if spercent and upercernt are meaningful.
 */
    prev_process_info_t *info;
    if(NULL == (info = g_tree_lookup(prev_process_info, GINT_TO_POINTER(pid)))) {
        info = g_slice_alloc(sizeof(*info));
        info->tm = tm;
        info->stime = stime;
        info->utime = utime;
        g_tree_insert(prev_process_info, GINT_TO_POINTER(pid), info);
        *spercent = 0;
        *upercent = 0;
        return(-1);
    }

    *spercent = TICKS_TO_SECONDS((100 * (stime - info->stime)) / CDTIME_T_TO_TIME_T(tm - info->tm));
    *upercent = TICKS_TO_SECONDS((100 * (utime - info->utime)) / CDTIME_T_TO_TIME_T(tm - info->tm));
    info->stime = stime;
    info->utime = utime;
    info->tm = tm;
    return(0);
} /* }}} */
Esempio n. 2
0
static int value_list_to_string (char *buffer, int buffer_len,
    const data_set_t *ds, const value_list_t *vl)
{
  int offset;
  int status;
  size_t i;
  time_t t;

  assert (0 == strcmp (ds->type, vl->type));

  memset (buffer, '\0', buffer_len);

  t = CDTIME_T_TO_TIME_T (vl->time);
  status = ssnprintf (buffer, buffer_len, "%lu", (unsigned long) t);
  if ((status < 1) || (status >= buffer_len))
    return (-1);
  offset = status;

  for (i = 0; i < ds->ds_num; i++)
  {
    if ((ds->ds[i].type != DS_TYPE_COUNTER)
        && (ds->ds[i].type != DS_TYPE_GAUGE)
	&& (ds->ds[i].type != DS_TYPE_DERIVE)
	&& (ds->ds[i].type != DS_TYPE_ABSOLUTE))
      return (-1);

    if (ds->ds[i].type == DS_TYPE_COUNTER)
    {
      status = ssnprintf (buffer + offset, buffer_len - offset,
          ":%llu", vl->values[i].counter);
    }
    else if (ds->ds[i].type == DS_TYPE_GAUGE)
    {
      status = ssnprintf (buffer + offset, buffer_len - offset,
          ":%f", vl->values[i].gauge);
    }
    else if (ds->ds[i].type == DS_TYPE_DERIVE) {
      status = ssnprintf (buffer + offset, buffer_len - offset,
	  ":%"PRIi64, vl->values[i].derive);
    }
    else /* if (ds->ds[i].type == DS_TYPE_ABSOLUTE) */ {
      status = ssnprintf (buffer + offset, buffer_len - offset,
	  ":%"PRIu64, vl->values[i].absolute);

    }

    if ((status < 1) || (status >= (buffer_len - offset)))
      return (-1);

    offset += status;
  } /* for ds->ds_num */

  return (0);
} /* int value_list_to_string */
Esempio n. 3
0
int format_graphite (char *buffer, size_t buffer_size,
    data_set_t const *ds, value_list_t const *vl,
    char const *prefix, char const *postfix, char const escape_char,
    unsigned int flags)
{
    int status = 0;
    int buffer_pos = 0;

    gauge_t *rates = NULL;
    if (flags & GRAPHITE_STORE_RATES)
      rates = uc_get_rate (ds, vl);

    for (size_t i = 0; i < ds->ds_num; i++)
    {
        char const *ds_name = NULL;
        char        key[10*DATA_MAX_NAME_LEN];
        char        values[512];
        size_t      message_len;
        char        message[1024];

        if ((flags & GRAPHITE_ALWAYS_APPEND_DS)
            || (ds->ds_num > 1))
          ds_name = ds->ds[i].name;

        /* Copy the identifier to `key' and escape it. */
        status = gr_format_name (key, sizeof (key), vl, ds_name,
                    prefix, postfix, escape_char, flags);
        if (status != 0)
        {
            ERROR ("format_graphite: error with gr_format_name");
            sfree (rates);
            return (status);
        }

        escape_graphite_string (key, escape_char);
        /* Convert the values to an ASCII representation and put that into
         * `values'. */
        status = gr_format_values (values, sizeof (values), i, ds, vl, rates);
        if (status != 0)
        {
            ERROR ("format_graphite: error with gr_format_values");
            sfree (rates);
            return (status);
        }

        /* Compute the graphite command */
        message_len = (size_t) ssnprintf (message, sizeof (message),
                "%s %s %u\r\n",
                key,
                values,
                (unsigned int) CDTIME_T_TO_TIME_T (vl->time));
        if (message_len >= sizeof (message)) {
            ERROR ("format_graphite: message buffer too small: "
                    "Need %zu bytes.", message_len + 1);
            sfree (rates);
            return (-ENOMEM);
        }

        /* Append it in case we got multiple data set */
        if ((buffer_pos + message_len) >= buffer_size)
        {
            ERROR ("format_graphite: target buffer too small");
            sfree (rates);
            return (-ENOMEM);
        }
        memcpy((void *) (buffer + buffer_pos), message, message_len);
        buffer_pos += message_len;
    }
    sfree (rates);
    return (status);
} /* int format_graphite */
Esempio n. 4
0
static void log_logstash_print (yajl_gen g, int severity,
	   	cdtime_t timestamp_time)
{
	FILE *fh;
	_Bool do_close = 0;
	struct tm timestamp_tm;
	char timestamp_str[64];
	const unsigned char *buf;
	time_t tt;
#if HAVE_YAJL_V2
	size_t len;
#else
	unsigned int len;
#endif

	if (yajl_gen_string(g, (u_char *)"@level", strlen("@level")) !=
	    yajl_gen_status_ok)
		goto err;

	switch (severity) {
	case LOG_ERR:
		if (yajl_gen_string(g, (u_char *)"error", strlen("error")) !=
		    yajl_gen_status_ok)
			goto err;
		break;
	case LOG_WARNING:
		if (yajl_gen_string(g, (u_char *)"warning",
				    strlen("warning")) !=
		    yajl_gen_status_ok)
			goto err;
		break;
	case LOG_NOTICE:
		if (yajl_gen_string(g, (u_char *)"notice", strlen("notice")) !=
		    yajl_gen_status_ok)
			goto err;
		break;
	case LOG_INFO:
		if (yajl_gen_string(g, (u_char *)"info", strlen("info")) !=
		    yajl_gen_status_ok)
			goto err;
		break;
	case LOG_DEBUG:
		if (yajl_gen_string(g, (u_char *)"debug", strlen("debug")) !=
		    yajl_gen_status_ok)
			goto err;
		break;
	default:
		if (yajl_gen_string(g, (u_char *)"unknown",
				    strlen("unknown")) !=
		    yajl_gen_status_ok)
			goto err;
		break;
	}

	if (yajl_gen_string(g, (u_char *)"@timestamp", strlen("@timestamp")) !=
	    yajl_gen_status_ok)
		goto err;

	tt = CDTIME_T_TO_TIME_T (timestamp_time);
	gmtime_r (&tt, &timestamp_tm);

	/*
	 * format time as a UTC ISO 8601 compliant string
	 */
	strftime (timestamp_str, sizeof (timestamp_str),
		  "%Y-%m-%d %H:%M:%SZ", &timestamp_tm);
	timestamp_str[sizeof (timestamp_str) - 1] = '\0';

	if (yajl_gen_string(g, (u_char *)timestamp_str,
			    strlen(timestamp_str)) !=
	    yajl_gen_status_ok)
		goto err;

	if (yajl_gen_map_close(g) != yajl_gen_status_ok)
		goto err;

	if (yajl_gen_get_buf(g, &buf, &len) != yajl_gen_status_ok)
		goto err;
	pthread_mutex_lock (&file_lock);

	if (log_file == NULL)
	{
		fh = fopen (DEFAULT_LOGFILE, "a");
		do_close = 1;
	} else if (strcasecmp(log_file, "stdout") == 0) {
        fh = stdout;
        do_close = 0;
	} else if (strcasecmp(log_file, "stderr") == 0) {
        fh = stderr;
        do_close = 0;
	} else {
		fh = fopen (log_file, "a");
		do_close = 1;
	}

	if (fh == NULL)
	{
			char errbuf[1024];
			fprintf (stderr, "log_logstash plugin: fopen (%s) failed: %s\n",
					(log_file == NULL) ? DEFAULT_LOGFILE : log_file,
					sstrerror (errno, errbuf, sizeof (errbuf)));
	}
	else
	{
		fprintf(fh, "%s\n", buf);
		if (do_close) {
			fclose (fh);
		} else {
			fflush(fh);
		}
	}
	pthread_mutex_unlock (&file_lock);
	yajl_gen_free(g);
	return;

 err:
	yajl_gen_free(g);
	fprintf(stderr, "Could not correctly generate JSON message\n");
	return;
} /* void log_logstash_print */
Esempio n. 5
0
static void logfile_print (const char *msg, int severity,
	   	cdtime_t timestamp_time)
{
	FILE *fh;
	_Bool do_close = 0;
	struct tm timestamp_tm;
	char timestamp_str[64];
	char level_str[16] = "";

	if (print_severity)
	{
		switch (severity)
		{
		case LOG_ERR:
			snprintf(level_str, sizeof (level_str), "[error] ");
			break;	
		case LOG_WARNING:
			snprintf(level_str, sizeof (level_str), "[warning] ");
			break;
		case LOG_NOTICE:
			snprintf(level_str, sizeof (level_str), "[notice] ");
			break;	
		case LOG_INFO:
			snprintf(level_str, sizeof (level_str), "[info] ");
			break;	
		case LOG_DEBUG:
			snprintf(level_str, sizeof (level_str), "[debug] ");
			break;	
		default:
			break;
		}
	}

	if (print_timestamp)
	{
		time_t tt = CDTIME_T_TO_TIME_T (timestamp_time);
		localtime_r (&tt, &timestamp_tm);

		strftime (timestamp_str, sizeof (timestamp_str), "%Y-%m-%d %H:%M:%S",
				&timestamp_tm);
		timestamp_str[sizeof (timestamp_str) - 1] = '\0';
	}

	pthread_mutex_lock (&file_lock);

	if (log_file == NULL)
	{
		fh = fopen (DEFAULT_LOGFILE, "a");
		do_close = 1;
	}
	else if (strcasecmp (log_file, "stderr") == 0)
		fh = stderr;
	else if (strcasecmp (log_file, "stdout") == 0)
		fh = stdout;
	else
	{
		fh = fopen (log_file, "a");
		do_close = 1;
	}

	if (fh == NULL)
	{
			char errbuf[1024];
			fprintf (stderr, "logfile plugin: fopen (%s) failed: %s\n",
					(log_file == NULL) ? DEFAULT_LOGFILE : log_file,
					sstrerror (errno, errbuf, sizeof (errbuf)));
	}
	else
	{
		if (print_timestamp)
			fprintf (fh, "[%s] %s%s\n", timestamp_str, level_str, msg);
		else
			fprintf (fh, "%s%s\n", level_str, msg);

		if (do_close) {
			fclose (fh);
		} else {
			fflush(fh);
		}
	}

	pthread_mutex_unlock (&file_lock);

	return;
} /* void logfile_print */
Esempio n. 6
0
/* * * * * * * * * *
 * WARNING:  Magic *
 * * * * * * * * * */
static int rra_get (char ***ret, const value_list_t *vl, /* {{{ */
    const rrdcreate_config_t *cfg)
{
  char **rra_def;
  int rra_num;

  int *rts;
  int  rts_num;

  int rra_max;

  int span;

  int cdp_num;
  int cdp_len;
  int i, j;

  char buffer[128];

  /* The stepsize we use here: If it is user-set, use it. If not, use the
   * interval of the value-list. */
  int ss;

  if (cfg->rrarows <= 0)
  {
    *ret = NULL;
    return (-1);
  }

  if ((cfg->xff < 0) || (cfg->xff >= 1.0))
  {
    *ret = NULL;
    return (-1);
  }

  if (cfg->stepsize > 0)
    ss = cfg->stepsize;
  else
    ss = (int) CDTIME_T_TO_TIME_T (vl->interval);
  if (ss <= 0)
  {
    *ret = NULL;
    return (-1);
  }

  /* Use the configured timespans or fall back to the built-in defaults */
  if (cfg->timespans_num != 0)
  {
    rts = cfg->timespans;
    rts_num = cfg->timespans_num;
  }
  else
  {
    rts = rra_timespans;
    rts_num = rra_timespans_num;
  }

  rra_max = rts_num * rra_types_num;

  if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
    return (-1);
  memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
  rra_num = 0;

  cdp_len = 0;
  for (i = 0; i < rts_num; i++)
  {
    span = rts[i];

    if ((span / ss) < cfg->rrarows)
      span = ss * cfg->rrarows;

    if (cdp_len == 0)
      cdp_len = 1;
    else
      cdp_len = (int) floor (((double) span)
          / ((double) (cfg->rrarows * ss)));

    cdp_num = (int) ceil (((double) span)
        / ((double) (cdp_len * ss)));

    for (j = 0; j < rra_types_num; j++)
    {
      int status;

      if (rra_num >= rra_max)
        break;

      status = ssnprintf (buffer, sizeof (buffer), "RRA:%s:%3.1f:%u:%u",
          rra_types[j], cfg->xff, cdp_len, cdp_num);

      if ((status < 0) || ((size_t) status >= sizeof (buffer)))
      {
        ERROR ("rra_get: Buffer would have been truncated.");
        continue;
      }

      rra_def[rra_num++] = sstrdup (buffer);
    }
  }

  *ret = rra_def;
  return (rra_num);
} /* }}} int rra_get */
Esempio n. 7
0
/*
 * Public functions
 */
int cu_rrd_create_file (const char *filename, /* {{{ */
    const data_set_t *ds, const value_list_t *vl,
    const rrdcreate_config_t *cfg)
{
  char **argv;
  int argc;
  char **rra_def;
  int rra_num;
  char **ds_def;
  int ds_num;
  int status = 0;
  time_t last_up;
  unsigned long stepsize;

  if (check_create_dir (filename))
    return (-1);

  if ((rra_num = rra_get (&rra_def, vl, cfg)) < 1)
  {
    ERROR ("cu_rrd_create_file failed: Could not calculate RRAs");
    return (-1);
  }

  if ((ds_num = ds_get (&ds_def, ds, vl, cfg)) < 1)
  {
    ERROR ("cu_rrd_create_file failed: Could not calculate DSes");
    return (-1);
  }

  argc = ds_num + rra_num;

  if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
  {
    char errbuf[1024];
    ERROR ("cu_rrd_create_file failed: %s",
        sstrerror (errno, errbuf, sizeof (errbuf)));
    return (-1);
  }

  memcpy (argv, ds_def, ds_num * sizeof (char *));
  memcpy (argv + ds_num, rra_def, rra_num * sizeof (char *));
  argv[ds_num + rra_num] = NULL;

  last_up = CDTIME_T_TO_TIME_T (vl->time);
  if (last_up <= 10)
    last_up = time (NULL);
  last_up -= 10;

  if (cfg->stepsize > 0)
    stepsize = cfg->stepsize;
  else
    stepsize = (unsigned long) CDTIME_T_TO_TIME_T (vl->interval);

  status = srrd_create (filename, stepsize, last_up,
      argc, (const char **) argv);

  free (argv);
  ds_free (ds_num, ds_def);
  rra_free (rra_num, rra_def);

  if (status != 0)
  {
    WARNING ("cu_rrd_create_file: srrd_create (%s) returned status %i.",
        filename, status);
  }
  else
  {
    DEBUG ("cu_rrd_create_file: Successfully created RRD file \"%s\".",
        filename);
  }

  return (status);
} /* }}} int cu_rrd_create_file */
Esempio n. 8
0
static int ds_get (char ***ret, /* {{{ */
    const data_set_t *ds, const value_list_t *vl,
    const rrdcreate_config_t *cfg)
{
  char **ds_def;
  int ds_num;

  char min[32];
  char max[32];
  char buffer[128];

  ds_def = (char **) malloc (ds->ds_num * sizeof (char *));
  if (ds_def == NULL)
  {
    char errbuf[1024];
    ERROR ("rrdtool plugin: malloc failed: %s",
        sstrerror (errno, errbuf, sizeof (errbuf)));
    return (-1);
  }
  memset (ds_def, '\0', ds->ds_num * sizeof (char *));

  for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
  {
    data_source_t *d = ds->ds + ds_num;
    char *type;
    int status;

    ds_def[ds_num] = NULL;

    if (d->type == DS_TYPE_COUNTER)
      type = "COUNTER";
    else if (d->type == DS_TYPE_GAUGE)
      type = "GAUGE";
    else if (d->type == DS_TYPE_DERIVE)
      type = "DERIVE";
    else if (d->type == DS_TYPE_ABSOLUTE)
      type = "ABSOLUTE";
    else
    {
      ERROR ("rrdtool plugin: Unknown DS type: %i",
          d->type);
      break;
    }

    if (isnan (d->min))
    {
      sstrncpy (min, "U", sizeof (min));
    }
    else
      ssnprintf (min, sizeof (min), "%f", d->min);

    if (isnan (d->max))
    {
      sstrncpy (max, "U", sizeof (max));
    }
    else
      ssnprintf (max, sizeof (max), "%f", d->max);

    status = ssnprintf (buffer, sizeof (buffer),
        "DS:%s:%s:%i:%s:%s",
        d->name, type,
        (cfg->heartbeat > 0)
        ? cfg->heartbeat
        : (int) CDTIME_T_TO_TIME_T (2 * vl->interval),
        min, max);
    if ((status < 1) || ((size_t) status >= sizeof (buffer)))
      break;

    ds_def[ds_num] = sstrdup (buffer);
  } /* for ds_num = 0 .. ds->ds_num */

  if (ds_num != ds->ds_num)
  {
    ds_free (ds_num, ds_def);
    return (-1);
  }

  *ret = ds_def;
  return (ds_num);
} /* }}} int ds_get */
Esempio n. 9
0
static Event *riemann_value_to_protobuf (struct riemann_host const *host, /* {{{ */
		data_set_t const *ds,
		value_list_t const *vl, size_t index,
		gauge_t const *rates)
{
	Event *event;
	char name_buffer[5 * DATA_MAX_NAME_LEN];
	char service_buffer[6 * DATA_MAX_NAME_LEN];
	int i;

	event = malloc (sizeof (*event));
	if (event == NULL)
	{
		ERROR ("write_riemann plugin: malloc failed.");
		return (NULL);
	}
	memset (event, 0, sizeof (*event));
	event__init (event);

	event->host = strdup (vl->host);
	event->time = CDTIME_T_TO_TIME_T (vl->time);
	event->has_time = 1;
	event->ttl = CDTIME_T_TO_TIME_T (2 * vl->interval);
	event->has_ttl = 1;

	riemann_event_add_attribute (event, "plugin", vl->plugin);
	if (vl->plugin_instance[0] != 0)
		riemann_event_add_attribute (event, "plugin_instance",
				vl->plugin_instance);

	riemann_event_add_attribute (event, "type", vl->type);
	if (vl->type_instance[0] != 0)
		riemann_event_add_attribute (event, "type_instance",
				vl->type_instance);

	if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL))
	{
		char ds_type[DATA_MAX_NAME_LEN];

		ssnprintf (ds_type, sizeof (ds_type), "%s:rate",
				DS_TYPE_TO_STRING(ds->ds[index].type));
		riemann_event_add_attribute (event, "ds_type", ds_type);
	}
	else
	{
		riemann_event_add_attribute (event, "ds_type",
				DS_TYPE_TO_STRING(ds->ds[index].type));
	}
	riemann_event_add_attribute (event, "ds_name", ds->ds[index].name);
	{
		char ds_index[DATA_MAX_NAME_LEN];

		ssnprintf (ds_index, sizeof (ds_index), "%zu", index);
		riemann_event_add_attribute (event, "ds_index", ds_index);
	}

	for (i = 0; i < riemann_tags_num; i++)
		riemann_event_add_tag (event, riemann_tags[i]);

	if (ds->ds[index].type == DS_TYPE_GAUGE)
	{
		event->has_metric_d = 1;
		event->metric_d = (double) vl->values[index].gauge;
	}
	else if (rates != NULL)
	{
		event->has_metric_d = 1;
		event->metric_d = (double) rates[index];
	}
	else
	{
		event->has_metric_sint64 = 1;
		if (ds->ds[index].type == DS_TYPE_DERIVE)
			event->metric_sint64 = (int64_t) vl->values[index].derive;
		else if (ds->ds[index].type == DS_TYPE_ABSOLUTE)
			event->metric_sint64 = (int64_t) vl->values[index].absolute;
		else
			event->metric_sint64 = (int64_t) vl->values[index].counter;
	}

	format_name (name_buffer, sizeof (name_buffer),
			/* host = */ "", vl->plugin, vl->plugin_instance,
			vl->type, vl->type_instance);
	if (host->always_append_ds || (ds->ds_num > 1))
		ssnprintf (service_buffer, sizeof (service_buffer),
				"%s/%s", &name_buffer[1], ds->ds[index].name);
	else
		sstrncpy (service_buffer, &name_buffer[1],
				sizeof (service_buffer));

	event->service = strdup (service_buffer);

	DEBUG ("write_riemann plugin: Successfully created protobuf for metric: "
			"host = \"%s\", service = \"%s\"",
			event->host, event->service);
	return (event);
} /* }}} Event *riemann_value_to_protobuf */
Esempio n. 10
0
static Msg *riemann_notification_to_protobuf (struct riemann_host *host, /* {{{ */
		notification_t const *n)
{
	Msg *msg;
	Event *event;
	char service_buffer[6 * DATA_MAX_NAME_LEN];
	char const *severity;
	notification_meta_t *meta;
	int i;

	msg = malloc (sizeof (*msg));
	if (msg == NULL)
	{
		ERROR ("write_riemann plugin: malloc failed.");
		return (NULL);
	}
	memset (msg, 0, sizeof (*msg));
	msg__init (msg);

	msg->events = malloc (sizeof (*msg->events));
	if (msg->events == NULL)
	{
		ERROR ("write_riemann plugin: malloc failed.");
		sfree (msg);
		return (NULL);
	}

	event = malloc (sizeof (*event));
	if (event == NULL)
	{
		ERROR ("write_riemann plugin: malloc failed.");
		sfree (msg->events);
		sfree (msg);
		return (NULL);
	}
	memset (event, 0, sizeof (*event));
	event__init (event);

	msg->events[0] = event;
	msg->n_events = 1;

	event->host = strdup (n->host);
	event->time = CDTIME_T_TO_TIME_T (n->time);
	event->has_time = 1;

	switch (n->severity)
	{
		case NOTIF_OKAY:	severity = "ok"; break;
		case NOTIF_WARNING:	severity = "warning"; break;
		case NOTIF_FAILURE:	severity = "critical"; break;
		default:		severity = "unknown";
	}
	event->state = strdup (severity);

	riemann_event_add_tag (event, "notification");
	if (n->host[0] != 0)
		riemann_event_add_attribute (event, "host", n->host);
	if (n->plugin[0] != 0)
		riemann_event_add_attribute (event, "plugin", n->plugin);
	if (n->plugin_instance[0] != 0)
		riemann_event_add_attribute (event, "plugin_instance",
				n->plugin_instance);

	if (n->type[0] != 0)
		riemann_event_add_attribute (event, "type", n->type);
	if (n->type_instance[0] != 0)
		riemann_event_add_attribute (event, "type_instance",
				n->type_instance);

	for (i = 0; i < riemann_tags_num; i++)
		riemann_event_add_tag (event, riemann_tags[i]);

	format_name (service_buffer, sizeof (service_buffer),
			/* host = */ "", n->plugin, n->plugin_instance,
			n->type, n->type_instance);
	event->service = strdup (&service_buffer[1]);

	/* Pull in values from threshold */
	for (meta = n->meta; meta != NULL; meta = meta->next)
	{
		if (strcasecmp ("CurrentValue", meta->name) != 0)
			continue;

		event->metric_d = meta->nm_value.nm_double;
		event->has_metric_d = 1;
		break;
	}

	DEBUG ("write_riemann plugin: Successfully created protobuf for notification: "
			"host = \"%s\", service = \"%s\", state = \"%s\"",
			event->host, event->service, event->state);
	return (msg);
} /* }}} Msg *riemann_notification_to_protobuf */
Esempio n. 11
0
static int init (void)
{
#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
	kern_return_t status;

	port_host = mach_host_self ();

	/* FIXME: Free `cpu_list' if it's not NULL */
	if ((status = host_processors (port_host, &cpu_list, &cpu_list_len)) != KERN_SUCCESS)
	{
		ERROR ("cpu plugin: host_processors returned %i", (int) status);
		cpu_list_len = 0;
		return (-1);
	}

	DEBUG ("host_processors returned %i %s", (int) cpu_list_len, cpu_list_len == 1 ? "processor" : "processors");
	INFO ("cpu plugin: Found %i processor%s.", (int) cpu_list_len, cpu_list_len == 1 ? "" : "s");

	cpu_temp_retry_max = 86400 / CDTIME_T_TO_TIME_T (plugin_get_interval ());
/* #endif PROCESSOR_CPU_LOAD_INFO */

#elif defined(HAVE_LIBKSTAT)
	kstat_t *ksp_chain;

	numcpu = 0;

	if (kc == NULL)
		return (-1);

	/* Solaris doesn't count linear.. *sigh* */
	for (numcpu = 0, ksp_chain = kc->kc_chain;
			(numcpu < MAX_NUMCPU) && (ksp_chain != NULL);
			ksp_chain = ksp_chain->ks_next)
		if (strncmp (ksp_chain->ks_module, "cpu_stat", 8) == 0)
			ksp[numcpu++] = ksp_chain;
/* #endif HAVE_LIBKSTAT */

#elif CAN_USE_SYSCTL
	size_t numcpu_size;
	int mib[2] = {CTL_HW, HW_NCPU};
	int status;

	numcpu = 0;
	numcpu_size = sizeof (numcpu);

	status = sysctl (mib, STATIC_ARRAY_SIZE (mib),
			&numcpu, &numcpu_size, NULL, 0);
	if (status == -1)
	{
		char errbuf[1024];
		WARNING ("cpu plugin: sysctl: %s",
				sstrerror (errno, errbuf, sizeof (errbuf)));
		return (-1);
	}
/* #endif CAN_USE_SYSCTL */

#elif defined (HAVE_SYSCTLBYNAME)
	size_t numcpu_size;

	numcpu_size = sizeof (numcpu);

	if (sysctlbyname ("hw.ncpu", &numcpu, &numcpu_size, NULL, 0) < 0)
	{
		char errbuf[1024];
		WARNING ("cpu plugin: sysctlbyname(hw.ncpu): %s",
				sstrerror (errno, errbuf, sizeof (errbuf)));
		return (-1);
	}

#ifdef HAVE_SYSCTL_KERN_CP_TIMES
	numcpu_size = sizeof (maxcpu);

	if (sysctlbyname("kern.smp.maxcpus", &maxcpu, &numcpu_size, NULL, 0) < 0)
	{
		char errbuf[1024];
		WARNING ("cpu plugin: sysctlbyname(kern.smp.maxcpus): %s",
				sstrerror (errno, errbuf, sizeof (errbuf)));
		return (-1);
	}
#else
	if (numcpu != 1)
		NOTICE ("cpu: Only one processor supported when using `sysctlbyname' (found %i)", numcpu);
#endif
/* #endif HAVE_SYSCTLBYNAME */

#elif defined(HAVE_LIBSTATGRAB)
	/* nothing to initialize */
/* #endif HAVE_LIBSTATGRAB */

#elif defined(HAVE_PERFSTAT)
	/* nothing to initialize */
#endif /* HAVE_PERFSTAT */

	return (0);
} /* int init */
Esempio n. 12
0
static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
		data_set_t const *ds,
		value_list_t const *vl, size_t index,
		gauge_t const *rates,
		int status)
{
	char name_buffer[5 * DATA_MAX_NAME_LEN];
	char service_buffer[6 * DATA_MAX_NAME_LEN];
	size_t i;
	char *ret_str;
	char *temp_str;
	char *value_str;
	int res;
	// First part of the JSON string
	const char *part1 = "{\"name\": \"collectd\", \"type\": \"metric\"";

	char *handlers_str = build_json_str_list("handlers", &(host->metric_handlers));
	if (handlers_str == NULL) {
		ERROR("write_sensu plugin: Unable to alloc memory");
		return NULL;
	}

	// incorporate the handlers
	if (strlen(handlers_str) == 0) {
		free(handlers_str);
		ret_str = strdup(part1);
		if (ret_str == NULL) {
			ERROR("write_sensu plugin: Unable to alloc memory");
			return NULL;
		}
	}
	else {
		res = asprintf(&ret_str, "%s, %s", part1, handlers_str);
		free(handlers_str);
		if (res == -1) {
			ERROR("write_sensu plugin: Unable to alloc memory");
			return NULL;
		}
	}

	// incorporate the plugin name information
	res = asprintf(&temp_str, "%s, \"collectd_plugin\": \"%s\"", ret_str, vl->plugin);
	free(ret_str);
	if (res == -1) {
		ERROR("write_sensu plugin: Unable to alloc memory");
		return NULL;
	}
	ret_str = temp_str;

	// incorporate the plugin type
	res = asprintf(&temp_str, "%s, \"collectd_plugin_type\": \"%s\"", ret_str, vl->type);
	free(ret_str);
	if (res == -1) {
		ERROR("write_sensu plugin: Unable to alloc memory");
		return NULL;
	}
	ret_str = temp_str;

	// incorporate the plugin instance if any
	if (vl->plugin_instance[0] != 0) {
		res = asprintf(&temp_str, "%s, \"collectd_plugin_instance\": \"%s\"", ret_str, vl->plugin_instance);
		free(ret_str);
		if (res == -1) {
			ERROR("write_sensu plugin: Unable to alloc memory");
			return NULL;
		}
		ret_str = temp_str;
	}

	// incorporate the plugin type instance if any
	if (vl->type_instance[0] != 0) {
		res = asprintf(&temp_str, "%s, \"collectd_plugin_type_instance\": \"%s\"", ret_str, vl->type_instance);
		free(ret_str);
		if (res == -1) {
			ERROR("write_sensu plugin: Unable to alloc memory");
			return NULL;
		}
		ret_str = temp_str;
	}

	// incorporate the data source type
	if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL)) {
		char ds_type[DATA_MAX_NAME_LEN];
		ssnprintf (ds_type, sizeof (ds_type), "%s:rate", DS_TYPE_TO_STRING(ds->ds[index].type));
		res = asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"", ret_str, ds_type);
		free(ret_str);
		if (res == -1) {
			ERROR("write_sensu plugin: Unable to alloc memory");
			return NULL;
		}
		ret_str = temp_str;
	} else {
		res = asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"", ret_str, DS_TYPE_TO_STRING(ds->ds[index].type));
		free(ret_str);
		if (res == -1) {
			ERROR("write_sensu plugin: Unable to alloc memory");
			return NULL;
		}
		ret_str = temp_str;
	}

	// incorporate the data source name
	res = asprintf(&temp_str, "%s, \"collectd_data_source_name\": \"%s\"", ret_str, ds->ds[index].name);
	free(ret_str);
	if (res == -1) {
		ERROR("write_sensu plugin: Unable to alloc memory");
		return NULL;
	}
	ret_str = temp_str;

	// incorporate the data source index
	{
		char ds_index[DATA_MAX_NAME_LEN];
		ssnprintf (ds_index, sizeof (ds_index), "%zu", index);
		res = asprintf(&temp_str, "%s, \"collectd_data_source_index\": %s", ret_str, ds_index);
		free(ret_str);
		if (res == -1) {
			ERROR("write_sensu plugin: Unable to alloc memory");
			return NULL;
		}
		ret_str = temp_str;
	}

	// add key value attributes from config if any
	for (i = 0; i < sensu_attrs_num; i += 2) {
		res = asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, sensu_attrs[i], sensu_attrs[i+1]);
		free(ret_str);
		if (res == -1) {
			ERROR("write_sensu plugin: Unable to alloc memory");
			return NULL;
		}
		ret_str = temp_str;
	}

	// incorporate sensu tags from config if any
	if ((sensu_tags != NULL) && (strlen(sensu_tags) != 0)) {
		res = asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
		free(ret_str);
		if (res == -1) {
			ERROR("write_sensu plugin: Unable to alloc memory");
			return NULL;
		}
		ret_str = temp_str;
	}

	// calculate the value and set to a string
	if (ds->ds[index].type == DS_TYPE_GAUGE) {
		res = asprintf(&value_str, GAUGE_FORMAT, vl->values[index].gauge);
		if (res == -1) {
			free(ret_str);
			ERROR("write_sensu plugin: Unable to alloc memory");
			return NULL;
		}
	} else if (rates != NULL) {
		res = asprintf(&value_str, GAUGE_FORMAT, rates[index]);
		if (res == -1) {
			free(ret_str);
			ERROR("write_sensu plugin: Unable to alloc memory");
			return NULL;
		}
	} else {
		if (ds->ds[index].type == DS_TYPE_DERIVE) {
			res = asprintf(&value_str, "%"PRIi64, vl->values[index].derive);
			if (res == -1) {
				free(ret_str);
				ERROR("write_sensu plugin: Unable to alloc memory");
				return NULL;
			}
		}
		else if (ds->ds[index].type == DS_TYPE_ABSOLUTE) {
			res = asprintf(&value_str, "%"PRIu64, vl->values[index].absolute);
			if (res == -1) {
				free(ret_str);
				ERROR("write_sensu plugin: Unable to alloc memory");
				return NULL;
			}
		}
		else {
			res = asprintf(&value_str, "%llu", vl->values[index].counter);
			if (res == -1) {
				free(ret_str);
				ERROR("write_sensu plugin: Unable to alloc memory");
				return NULL;
			}
		}
	}

	// Generate the full service name
	sensu_format_name2(name_buffer, sizeof(name_buffer),
		vl->host, vl->plugin, vl->plugin_instance,
		vl->type, vl->type_instance, host->separator);
	if (host->always_append_ds || (ds->ds_num > 1)) {
		if (host->event_service_prefix == NULL)
			ssnprintf(service_buffer, sizeof(service_buffer), "%s.%s",
					name_buffer, ds->ds[index].name);
		else
			ssnprintf(service_buffer, sizeof(service_buffer), "%s%s.%s",
					host->event_service_prefix, name_buffer, ds->ds[index].name);
	} else {
		if (host->event_service_prefix == NULL)
			sstrncpy(service_buffer, name_buffer, sizeof(service_buffer));
		else
			ssnprintf(service_buffer, sizeof(service_buffer), "%s%s",
					host->event_service_prefix, name_buffer);
	}

	// Replace collectd sensor name reserved characters so that time series DB is happy
	in_place_replace_sensu_name_reserved(service_buffer);

	// finalize the buffer by setting the output and closing curly bracket
	res = asprintf(&temp_str, "%s, \"output\": \"%s %s %ld\"}\n", ret_str, service_buffer, value_str, CDTIME_T_TO_TIME_T(vl->time));
	free(ret_str);
	free(value_str);
	if (res == -1) {
		ERROR("write_sensu plugin: Unable to alloc memory");
		return NULL;
	}
	ret_str = temp_str;

	DEBUG("write_sensu plugin: Successfully created json for metric: "
			"host = \"%s\", service = \"%s\"",
			vl->host, service_buffer);
	return ret_str;
} /* }}} char *sensu_value_to_json */
Esempio n. 13
0
static riemann_event_t *
wrr_value_to_event(struct riemann_host const *host, /* {{{ */
                   data_set_t const *ds, value_list_t const *vl, size_t index,
                   gauge_t const *rates, int status) {
  riemann_event_t *event;
  char name_buffer[5 * DATA_MAX_NAME_LEN];
  char service_buffer[6 * DATA_MAX_NAME_LEN];
  size_t i;

  event = riemann_event_new();
  if (event == NULL) {
    ERROR("write_riemann plugin: riemann_event_new() failed.");
    return NULL;
  }

  format_name(name_buffer, sizeof(name_buffer),
              /* host = */ "", vl->plugin, vl->plugin_instance, vl->type,
              vl->type_instance);
  if (host->always_append_ds || (ds->ds_num > 1)) {
    if (host->event_service_prefix == NULL)
      snprintf(service_buffer, sizeof(service_buffer), "%s/%s", &name_buffer[1],
               ds->ds[index].name);
    else
      snprintf(service_buffer, sizeof(service_buffer), "%s%s/%s",
               host->event_service_prefix, &name_buffer[1], ds->ds[index].name);
  } else {
    if (host->event_service_prefix == NULL)
      sstrncpy(service_buffer, &name_buffer[1], sizeof(service_buffer));
    else
      snprintf(service_buffer, sizeof(service_buffer), "%s%s",
               host->event_service_prefix, &name_buffer[1]);
  }

  riemann_event_set(
      event, RIEMANN_EVENT_FIELD_HOST, vl->host, RIEMANN_EVENT_FIELD_TIME,
      (int64_t)CDTIME_T_TO_TIME_T(vl->time), RIEMANN_EVENT_FIELD_TTL,
      (float)CDTIME_T_TO_DOUBLE(vl->interval) * host->ttl_factor,
      RIEMANN_EVENT_FIELD_STRING_ATTRIBUTES, "plugin", vl->plugin, "type",
      vl->type, "ds_name", ds->ds[index].name, NULL,
      RIEMANN_EVENT_FIELD_SERVICE, service_buffer, RIEMANN_EVENT_FIELD_NONE);

#if RCC_VERSION_NUMBER >= 0x010A00
  riemann_event_set(event, RIEMANN_EVENT_FIELD_TIME_MICROS,
                    (int64_t)CDTIME_T_TO_US(vl->time));
#endif

  if (host->check_thresholds) {
    const char *state = NULL;

    switch (status) {
    case STATE_OKAY:
      state = "ok";
      break;
    case STATE_ERROR:
      state = "critical";
      break;
    case STATE_WARNING:
      state = "warning";
      break;
    case STATE_MISSING:
      state = "unknown";
      break;
    }
    if (state)
      riemann_event_set(event, RIEMANN_EVENT_FIELD_STATE, state,
                        RIEMANN_EVENT_FIELD_NONE);
  }

  if (vl->plugin_instance[0] != 0)
    riemann_event_string_attribute_add(event, "plugin_instance",
                                       vl->plugin_instance);
  if (vl->type_instance[0] != 0)
    riemann_event_string_attribute_add(event, "type_instance",
                                       vl->type_instance);

  if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL)) {
    char ds_type[DATA_MAX_NAME_LEN];

    snprintf(ds_type, sizeof(ds_type), "%s:rate",
             DS_TYPE_TO_STRING(ds->ds[index].type));
    riemann_event_string_attribute_add(event, "ds_type", ds_type);
  } else {
    riemann_event_string_attribute_add(event, "ds_type",
                                       DS_TYPE_TO_STRING(ds->ds[index].type));
  }

  {
    char ds_index[DATA_MAX_NAME_LEN];

    snprintf(ds_index, sizeof(ds_index), "%" PRIsz, index);
    riemann_event_string_attribute_add(event, "ds_index", ds_index);
  }

  for (i = 0; i < riemann_attrs_num; i += 2)
    riemann_event_string_attribute_add(event, riemann_attrs[i],
                                       riemann_attrs[i + 1]);

  for (i = 0; i < riemann_tags_num; i++)
    riemann_event_tag_add(event, riemann_tags[i]);

  if (ds->ds[index].type == DS_TYPE_GAUGE) {
    riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_D,
                      (double)vl->values[index].gauge,
                      RIEMANN_EVENT_FIELD_NONE);
  } else if (rates != NULL) {
    riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_D, (double)rates[index],
                      RIEMANN_EVENT_FIELD_NONE);
  } else {
    int64_t metric;

    if (ds->ds[index].type == DS_TYPE_DERIVE)
      metric = (int64_t)vl->values[index].derive;
    else if (ds->ds[index].type == DS_TYPE_ABSOLUTE)
      metric = (int64_t)vl->values[index].absolute;
    else
      metric = (int64_t)vl->values[index].counter;

    riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_S64, (int64_t)metric,
                      RIEMANN_EVENT_FIELD_NONE);
  }

  DEBUG("write_riemann plugin: Successfully created message for metric: "
        "host = \"%s\", service = \"%s\"",
        event->host, event->service);
  return event;
} /* }}} riemann_event_t *wrr_value_to_event */
Esempio n. 14
0
static riemann_message_t *
wrr_notification_to_message(struct riemann_host *host, /* {{{ */
                            notification_t const *n) {
  riemann_message_t *msg;
  riemann_event_t *event;
  char service_buffer[6 * DATA_MAX_NAME_LEN];
  char const *severity;

  switch (n->severity) {
  case NOTIF_OKAY:
    severity = "ok";
    break;
  case NOTIF_WARNING:
    severity = "warning";
    break;
  case NOTIF_FAILURE:
    severity = "critical";
    break;
  default:
    severity = "unknown";
  }

  format_name(service_buffer, sizeof(service_buffer),
              /* host = */ "", n->plugin, n->plugin_instance, n->type,
              n->type_instance);

  event = riemann_event_create(
      RIEMANN_EVENT_FIELD_HOST, n->host, RIEMANN_EVENT_FIELD_TIME,
      (int64_t)CDTIME_T_TO_TIME_T(n->time), RIEMANN_EVENT_FIELD_TAGS,
      "notification", NULL, RIEMANN_EVENT_FIELD_STATE, severity,
      RIEMANN_EVENT_FIELD_SERVICE, &service_buffer[1],
      RIEMANN_EVENT_FIELD_NONE);

#if RCC_VERSION_NUMBER >= 0x010A00
  riemann_event_set(event, RIEMANN_EVENT_FIELD_TIME_MICROS,
                    (int64_t)CDTIME_T_TO_US(n->time));
#endif

  if (n->host[0] != 0)
    riemann_event_string_attribute_add(event, "host", n->host);
  if (n->plugin[0] != 0)
    riemann_event_string_attribute_add(event, "plugin", n->plugin);
  if (n->plugin_instance[0] != 0)
    riemann_event_string_attribute_add(event, "plugin_instance",
                                       n->plugin_instance);

  if (n->type[0] != 0)
    riemann_event_string_attribute_add(event, "type", n->type);
  if (n->type_instance[0] != 0)
    riemann_event_string_attribute_add(event, "type_instance",
                                       n->type_instance);

  for (size_t i = 0; i < riemann_attrs_num; i += 2)
    riemann_event_string_attribute_add(event, riemann_attrs[i],
                                       riemann_attrs[i + 1]);

  for (size_t i = 0; i < riemann_tags_num; i++)
    riemann_event_tag_add(event, riemann_tags[i]);

  if (n->message[0] != 0)
    riemann_event_string_attribute_add(event, "description", n->message);

  /* Pull in values from threshold and add extra attributes */
  for (notification_meta_t *meta = n->meta; meta != NULL; meta = meta->next) {
    if (strcasecmp("CurrentValue", meta->name) == 0 &&
        meta->type == NM_TYPE_DOUBLE) {
      riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_D,
                        (double)meta->nm_value.nm_double,
                        RIEMANN_EVENT_FIELD_NONE);
      continue;
    }

    if (meta->type == NM_TYPE_STRING) {
      riemann_event_string_attribute_add(event, meta->name,
                                         meta->nm_value.nm_string);
      continue;
    }
  }

  msg = riemann_message_create_with_events(event, NULL);
  if (msg == NULL) {
    ERROR("write_riemann plugin: riemann_message_create_with_events() failed.");
    riemann_event_free(event);
    return NULL;
  }

  DEBUG("write_riemann plugin: Successfully created message for notification: "
        "host = \"%s\", service = \"%s\", state = \"%s\"",
        event->host, event->service, event->state);
  return msg;
} /* }}} riemann_message_t *wrr_notification_to_message */
Esempio n. 15
0
/*
 * Public functions
 */
int cu_rrd_create_file(const char *filename, /* {{{ */
                       const data_set_t *ds, const value_list_t *vl,
                       const rrdcreate_config_t *cfg) {
  char **argv;
  int argc;
  char **rra_def = NULL;
  int rra_num;
  char **ds_def = NULL;
  int ds_num;
  int status = 0;
  time_t last_up;
  unsigned long stepsize;

  if (check_create_dir(filename))
    return -1;

  if ((rra_num = rra_get(&rra_def, vl, cfg)) < 1) {
    P_ERROR("cu_rrd_create_file failed: Could not calculate RRAs");
    return -1;
  }

  if ((ds_num = ds_get(&ds_def, ds, vl, cfg)) < 1) {
    P_ERROR("cu_rrd_create_file failed: Could not calculate DSes");
    rra_free(rra_num, rra_def);
    return -1;
  }

  argc = ds_num + rra_num;

  if ((argv = malloc(sizeof(*argv) * (argc + 1))) == NULL) {
    P_ERROR("cu_rrd_create_file failed: %s", STRERRNO);
    rra_free(rra_num, rra_def);
    ds_free(ds_num, ds_def);
    return -1;
  }

  memcpy(argv, ds_def, ds_num * sizeof(char *));
  memcpy(argv + ds_num, rra_def, rra_num * sizeof(char *));
  argv[ds_num + rra_num] = NULL;

  last_up = CDTIME_T_TO_TIME_T(vl->time);
  if (last_up <= 0)
    last_up = time(NULL);
  last_up -= 1;

  if (cfg->stepsize > 0)
    stepsize = cfg->stepsize;
  else
    stepsize = (unsigned long)CDTIME_T_TO_TIME_T(vl->interval);

  if (cfg->async) {
    status = srrd_create_async(filename, stepsize, last_up, argc,
                               (const char **)argv);
    if (status != 0)
      P_WARNING("cu_rrd_create_file: srrd_create_async (%s) "
                "returned status %i.",
                filename, status);
  } else /* synchronous */
  {
    status = lock_file(filename);
    if (status != 0) {
      if (status == EEXIST)
        P_NOTICE("cu_rrd_create_file: File \"%s\" is already being created.",
                 filename);
      else
        P_ERROR("cu_rrd_create_file: Unable to lock file \"%s\".", filename);
    } else {
      status =
          srrd_create(filename, stepsize, last_up, argc, (const char **)argv);

      if (status != 0) {
        P_WARNING("cu_rrd_create_file: srrd_create (%s) returned status %i.",
                  filename, status);
      } else {
        DEBUG("cu_rrd_create_file: Successfully created RRD file \"%s\".",
              filename);
      }
      unlock_file(filename);
    }
  }

  free(argv);
  ds_free(ds_num, ds_def);
  rra_free(rra_num, rra_def);

  return status;
} /* }}} int cu_rrd_create_file */
Esempio n. 16
0
static int ds_get(char ***ret, /* {{{ */
                  const data_set_t *ds, const value_list_t *vl,
                  const rrdcreate_config_t *cfg) {
  char **ds_def;
  size_t ds_num;

  char min[32];
  char max[32];
  char buffer[128];

  assert(ds->ds_num > 0);

  ds_def = calloc(ds->ds_num, sizeof(*ds_def));
  if (ds_def == NULL) {
    P_ERROR("ds_get: calloc failed: %s", STRERRNO);
    return -1;
  }

  for (ds_num = 0; ds_num < ds->ds_num; ds_num++) {
    data_source_t *d = ds->ds + ds_num;
    const char *type;
    int status;

    ds_def[ds_num] = NULL;

    if (d->type == DS_TYPE_COUNTER)
      type = "COUNTER";
    else if (d->type == DS_TYPE_GAUGE)
      type = "GAUGE";
    else if (d->type == DS_TYPE_DERIVE)
      type = "DERIVE";
    else if (d->type == DS_TYPE_ABSOLUTE)
      type = "ABSOLUTE";
    else {
      P_ERROR("ds_get: Unknown DS type: %i", d->type);
      break;
    }

    if (isnan(d->min)) {
      sstrncpy(min, "U", sizeof(min));
    } else
      snprintf(min, sizeof(min), "%f", d->min);

    if (isnan(d->max)) {
      sstrncpy(max, "U", sizeof(max));
    } else
      snprintf(max, sizeof(max), "%f", d->max);

    status = snprintf(
        buffer, sizeof(buffer), "DS:%s:%s:%i:%s:%s", d->name, type,
        (cfg->heartbeat > 0) ? cfg->heartbeat
                             : (int)CDTIME_T_TO_TIME_T(2 * vl->interval),
        min, max);
    if ((status < 1) || ((size_t)status >= sizeof(buffer)))
      break;

    ds_def[ds_num] = sstrdup(buffer);
  } /* for ds_num = 0 .. ds->ds_num */

  if (ds_num != ds->ds_num) {
    ds_free(ds_num, ds_def);
    return -1;
  }

  if (ds_num == 0) {
    sfree(ds_def);
    return 0;
  }

  *ret = ds_def;
  return ds_num;
} /* }}} int ds_get */