Ejemplo n.º 1
0
static int memcached_read (user_data_t *user_data)
{
  char buf[4096];
  char *fields[3];
  char *ptr;
  char *line;
  char *saveptr;
  int fields_num;

  gauge_t bytes_used = NAN;
  gauge_t bytes_total = NAN;
  gauge_t hits = NAN;
  gauge_t gets = NAN;
  gauge_t incr_hits = NAN;
  derive_t incr = 0;
  gauge_t decr_hits = NAN;
  derive_t decr = 0;
  derive_t rusage_user = 0;
  derive_t rusage_syst = 0;
  derive_t octets_rx = 0;
  derive_t octets_tx = 0;

  memcached_t *st;
  st = user_data->data;

  /* get data from daemon */
  if (memcached_query_daemon (buf, sizeof (buf), st) < 0) {
    return -1;
  }

#define FIELD_IS(cnst) \
  (((sizeof(cnst) - 1) == name_len) && (strcmp (cnst, fields[1]) == 0))

  ptr = buf;
  saveptr = NULL;
  while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
  {
    int name_len;

    ptr = NULL;

    fields_num = strsplit(line, fields, 3);
    if (fields_num != 3)
      continue;

    name_len = strlen(fields[1]);
    if (name_len == 0)
      continue;

    /*
     * For an explanation on these fields please refer to
     * <https://github.com/memcached/memcached/blob/master/doc/protocol.txt>
     */

    /*
     * CPU time consumed by the memcached process
     */
    if (FIELD_IS ("rusage_user"))
    {
      rusage_user = atoll (fields[2]);
    }
    else if (FIELD_IS ("rusage_system"))
    {
      rusage_syst = atoll(fields[2]);
    }

    /*
     * Number of threads of this instance
     */
    else if (FIELD_IS ("threads"))
    {
      submit_gauge2 ("ps_count", NULL, NAN, atof (fields[2]), st);
    }

    /*
     * Number of items stored
     */
    else if (FIELD_IS ("curr_items"))
    {
      submit_gauge ("memcached_items", "current", atof (fields[2]), st);
    }

    /*
     * Number of bytes used and available (total - used)
     */
    else if (FIELD_IS ("bytes"))
    {
      bytes_used = atof (fields[2]);
    }
    else if (FIELD_IS ("limit_maxbytes"))
    {
      bytes_total = atof(fields[2]);
    }

    /*
     * Connections
     */
    else if (FIELD_IS ("curr_connections"))
    {
      submit_gauge ("memcached_connections", "current", atof (fields[2]), st);
    }
    else if (FIELD_IS ("listen_disabled_num"))
    {
      submit_derive ("memcached_connections", "listen_disabled", atof (fields[2]), st);
    }

    /*
     * Commands
     */
    else if ((name_len > 4) && (strncmp (fields[1], "cmd_", 4) == 0))
    {
      const char *name = fields[1] + 4;
      submit_derive ("memcached_command", name, atoll (fields[2]), st);
      if (strcmp (name, "get") == 0)
        gets = atof (fields[2]);
    }

    /*
     * Increment/Decrement
     */
    else if (FIELD_IS("incr_misses"))
    {
      derive_t incr_count = atoll (fields[2]);
      submit_derive ("memcached_ops", "incr_misses", incr_count, st);
      incr += incr_count;
    }
    else if (FIELD_IS ("incr_hits"))
    {
      derive_t incr_count = atoll (fields[2]);
      submit_derive ("memcached_ops", "incr_hits", incr_count, st);
      incr_hits = atof (fields[2]);
      incr += incr_count;
    }
    else if (FIELD_IS ("decr_misses"))
    {
      derive_t decr_count = atoll (fields[2]);
      submit_derive ("memcached_ops", "decr_misses", decr_count, st);
      decr += decr_count;
    }
    else if (FIELD_IS ("decr_hits"))
    {
      derive_t decr_count = atoll (fields[2]);
      submit_derive ("memcached_ops", "decr_hits", decr_count, st);
      decr_hits = atof (fields[2]);
      decr += decr_count;
    }

    /*
     * Operations on the cache, i. e. cache hits, cache misses and evictions of items
     */
    else if (FIELD_IS ("get_hits"))
    {
      submit_derive ("memcached_ops", "hits", atoll (fields[2]), st);
      hits = atof (fields[2]);
    }
    else if (FIELD_IS ("get_misses"))
    {
      submit_derive ("memcached_ops", "misses", atoll (fields[2]), st);
    }
    else if (FIELD_IS ("evictions"))
    {
      submit_derive ("memcached_ops", "evictions", atoll (fields[2]), st);
    }

    /*
     * Network traffic
     */
    else if (FIELD_IS ("bytes_read"))
    {
      octets_rx = atoll (fields[2]);
    }
    else if (FIELD_IS ("bytes_written"))
    {
      octets_tx = atoll (fields[2]);
    }
  } /* while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL) */

  if (!isnan (bytes_used) && !isnan (bytes_total) && (bytes_used <= bytes_total))
    submit_gauge2 ("df", "cache", bytes_used, bytes_total - bytes_used, st);

  if ((rusage_user != 0) || (rusage_syst != 0))
    submit_derive2 ("ps_cputime", NULL, rusage_user, rusage_syst, st);

  if ((octets_rx != 0) || (octets_tx != 0))
    submit_derive2 ("memcached_octets", NULL, octets_rx, octets_tx, st);

  if (!isnan (gets) && !isnan (hits))
  {
    gauge_t rate = NAN;

    if (gets != 0.0)
      rate = 100.0 * hits / gets;

    submit_gauge ("percent", "hitratio", rate, st);
  }

  if (!isnan (incr_hits) && incr != 0)
  {
    gauge_t incr_rate = 100.0 * incr_hits / incr;
    submit_gauge ("percent", "incr_hitratio", incr_rate, st);
    submit_derive ("memcached_ops", "incr", incr, st);
  }

  if (!isnan (decr_hits) && decr != 0)
  {
    gauge_t decr_rate = 100.0 * decr_hits / decr;
    submit_gauge ("percent", "decr_hitratio", decr_rate, st);
    submit_derive ("memcached_ops", "decr", decr, st);
  }

  return 0;
} /* int memcached_read */
Ejemplo n.º 2
0
struct robot_specs *
res_parse (const char *source, int length)
{
  int line_count = 1;

  const char *p   = source;
  const char *end = source + length;

  /* true if last applicable user-agent field matches Wget. */
  bool user_agent_applies = false;

  /* true if last applicable user-agent field *exactly* matches
     Wget.  */
  bool user_agent_exact = false;

  /* whether we ever encountered exact user agent. */
  bool found_exact = false;

  /* count of allow/disallow lines in the current "record", i.e. after
     the last `user-agent' instructions.  */
  int record_count = 0;

  struct robot_specs *specs = xnew0 (struct robot_specs);

  while (1)
    {
      const char *lineend, *lineend_real;
      const char *field_b, *field_e;
      const char *value_b, *value_e;

      if (p == end)
        break;
      lineend_real = memchr (p, '\n', end - p);
      if (lineend_real)
        ++lineend_real;
      else
        lineend_real = end;
      lineend = lineend_real;

      /* Before doing anything else, check whether the line is empty
         or comment-only. */
      SKIP_SPACE (p);
      if (EOL (p) || *p == '#')
        goto next;

      /* Make sure the end-of-line comments are respected by setting
         lineend to a location preceding the first comment.  Real line
         ending remains in lineend_real.  */
      for (lineend = p; lineend < lineend_real; lineend++)
        if ((lineend == p || c_isspace (*(lineend - 1)))
            && *lineend == '#')
          break;

      /* Ignore trailing whitespace in the same way. */
      while (lineend > p && c_isspace (*(lineend - 1)))
        --lineend;

      assert (!EOL (p));

      field_b = p;
      while (!EOL (p) && (c_isalnum (*p) || *p == '-'))
        ++p;
      field_e = p;

      SKIP_SPACE (p);
      if (field_b == field_e || EOL (p) || *p != ':')
        {
          DEBUGP (("Ignoring malformed line %d\n", line_count));
          goto next;
        }
      ++p;                      /* skip ':' */
      SKIP_SPACE (p);

      value_b = p;
      while (!EOL (p))
        ++p;
      value_e = p;

      /* Finally, we have a syntactically valid line. */
      if (FIELD_IS ("user-agent"))
        {
          /* We have to support several cases:

             --previous records--

             User-Agent: foo
             User-Agent: Wget
             User-Agent: bar
             ... matching record ...

             User-Agent: baz
             User-Agent: qux
             ... non-matching record ...

             User-Agent: *
             ... matching record, but will be pruned later ...

             We have to respect `User-Agent' at the beginning of each
             new record simply because we don't know if we're going to
             encounter "Wget" among the agents or not.  Hence,
             match_user_agent is called when record_count != 0.

             But if record_count is 0, we have to keep calling it
             until it matches, and if that happens, we must not call
             it any more, until the next record.  Hence the other part
             of the condition.  */
          if (record_count != 0 || user_agent_applies == false)
            match_user_agent (value_b, value_e - value_b,
                              &user_agent_applies, &user_agent_exact);
          if (user_agent_exact)
            found_exact = true;
          record_count = 0;
        }
      else if (FIELD_IS ("allow"))
        {
          if (user_agent_applies)
            {
              add_path (specs, value_b, value_e, true, user_agent_exact);
            }
          ++record_count;
        }
      else if (FIELD_IS ("disallow"))
        {
          if (user_agent_applies)
            {
              bool allowed = false;
              if (value_b == value_e)
                /* Empty "disallow" line means everything is *allowed*!  */
                allowed = true;
              add_path (specs, value_b, value_e, allowed, user_agent_exact);
            }
          ++record_count;
        }
      else
        {
          DEBUGP (("Ignoring unknown field at line %d\n", line_count));
          goto next;
        }

    next:
      p = lineend_real;
      ++line_count;
    }

  if (found_exact)
    {
      /* We've encountered an exactly matching user-agent.  Throw out
         all the stuff with user-agent: *.  */
      prune_non_exact (specs);
    }
  else if (specs->size > specs->count)
    {
      /* add_path normally over-allocates specs->paths.  Reallocate it
         to the correct size in order to conserve some memory.  */
      specs->paths = xrealloc (specs->paths,
                               specs->count * sizeof (struct path_info));
      specs->size = specs->count;
    }

  return specs;
}
Ejemplo n.º 3
0
static int memcached_read (void) /* {{{ */
{
	char buf[1024];
	char *fields[3];
	char *ptr;
	char *line;
	char *saveptr;
	int fields_num;

	gauge_t bytes_used = NAN;
	gauge_t bytes_total = NAN;
	gauge_t hits = NAN;
	gauge_t gets = NAN;
	counter_t rusage_user = 0;
	counter_t rusage_syst = 0;
	counter_t octets_rx = 0;
	counter_t octets_tx = 0;

	/* get data from daemon */
	if (memcached_query_daemon (buf, sizeof (buf)) < 0) {
		return -1;
	}

#define FIELD_IS(cnst) \
	(((sizeof(cnst) - 1) == name_len) && (strcmp (cnst, fields[1]) == 0))

	ptr = buf;
	saveptr = NULL;
	while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
	{
		int name_len;

		ptr = NULL;

		fields_num = strsplit(line, fields, 3);
		if (fields_num != 3)
			continue;

		name_len = strlen(fields[1]);
		if (name_len == 0)
			continue;

		/*
		 * For an explanation on these fields please refer to
		 * <http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt>
		 */

		/*
		 * CPU time consumed by the memcached process
		 */
		if (FIELD_IS ("rusage_user"))
		{
			rusage_user = atoll (fields[2]);
		}
		else if (FIELD_IS ("rusage_system"))
		{
			rusage_syst = atoll(fields[2]);
		}

		/*
		 * Number of threads of this instance
		 */
		else if (FIELD_IS ("threads"))
		{
			submit_gauge2 ("ps_count", NULL, NAN, atof (fields[2]));
		}

		/*
		 * Number of items stored
		 */
		else if (FIELD_IS ("curr_items"))
		{
			submit_gauge ("memcached_items", "current", atof (fields[2]));
		}

		/*
		 * Number of bytes used and available (total - used)
		 */
		else if (FIELD_IS ("bytes"))
		{
			bytes_used = atof (fields[2]);
		}
		else if (FIELD_IS ("limit_maxbytes"))
		{
			bytes_total = atof(fields[2]);
		}

		/*
		 * Connections
		 */
		else if (FIELD_IS ("curr_connections"))
		{
			submit_gauge ("memcached_connections", "current", atof (fields[2]));
		}

		/*
		 * Commands
		 */
		else if ((name_len > 4) && (strncmp (fields[1], "cmd_", 4) == 0))
		{
			const char *name = fields[1] + 4;
			submit_counter ("memcached_command", name, atoll (fields[2]));
			if (strcmp (name, "get") == 0)
				gets = atof (fields[2]);
		}

		/*
		 * Operations on the cache, i. e. cache hits, cache misses and evictions of items
		 */
		else if (FIELD_IS ("get_hits"))
		{
			submit_counter ("memcached_ops", "hits", atoll (fields[2]));
			hits = atof (fields[2]);
		}
		else if (FIELD_IS ("get_misses"))
		{
			submit_counter ("memcached_ops", "misses", atoll (fields[2]));
		}
		else if (FIELD_IS ("evictions"))
		{
			submit_counter ("memcached_ops", "evictions", atoll (fields[2]));
		}

		/*
		 * Network traffic
		 */
		else if (FIELD_IS ("bytes_read"))
		{
			octets_rx = atoll (fields[2]);
		}
		else if (FIELD_IS ("bytes_written"))
		{
			octets_tx = atoll (fields[2]);
		}
	} /* while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL) */

	if (!isnan (bytes_used) && !isnan (bytes_total) && (bytes_used <= bytes_total))
		submit_gauge2 ("df", "cache", bytes_used, bytes_total - bytes_used);

	if ((rusage_user != 0) || (rusage_syst != 0))
		submit_counter2 ("ps_cputime", NULL, rusage_user, rusage_syst);

	if ((octets_rx != 0) || (octets_tx != 0))
		submit_counter2 ("memcached_octets", NULL, octets_rx, octets_tx);

	if (!isnan (gets) && !isnan (hits))
	{
		gauge_t rate = NAN;

		if (gets != 0.0)
			rate = 100.0 * hits / gets;

		submit_gauge ("percent", "hitratio", rate);
	}

	return 0;
}