Permalink
Browse files

Add a command line option to pmwebd for name encoding

  • Loading branch information...
1 parent d63576e commit 4641bbf0bd2544ab3f57f523f7832a56dd7075a6 @minnus minnus committed Oct 16, 2015
Showing with 71 additions and 24 deletions.
  1. +5 −0 man/man1/pmwebd.1
  2. +7 −0 src/pmwebapi/main.cxx
  3. +59 −24 src/pmwebapi/pmgraphite.cxx
View
@@ -29,6 +29,7 @@
[\f3\-L\f1]
[\f3\-N\f1]
[\f3\-G\f1]
+[\f3\-X\f1]
[\f3\-i\f1 \f2min-interval\f1]
[\f3\-I\f1
[\f3\-K\f1 \f2spec\f1]
@@ -97,6 +98,10 @@ your web browser to
.B http://127.0.0.1:43323/
.hy
.TP
+\f3\-X\f1
+Disable encoding of common characters for metric names. Newer graphite
@fche

fche Nov 6, 2015

Contributor

It would be good to list them: / _ et al.?

+and grafana support a larger set af characters in metric names.
@fche

fche Nov 6, 2015

Contributor

"of"

+.TP
\f3\-i\f1 \f2min-interval\f1
Set the minimum sampling interval for graphite time series in seconds.
The default is 60. Smaller values give higher precision (but not
View
@@ -34,6 +34,7 @@ map<string,unsigned> clients_usage;
unsigned perm_context = 1; /* set by -c option, changed by -h/-a/-L */
unsigned new_contexts_p = 1; /* cleared by -N option */
unsigned graphite_p; /* set by -G option */
+unsigned graphite_encode = 1; /* unset by -X option */
unsigned exit_p; /* counted by SIG* handler */
static __pmServerPresence *presence;
unsigned multithread = 0; /* set by -M option */
@@ -450,6 +451,7 @@ option_overrides (int opt, pmOptions * opts)
case 't':
case 'i':
case 'I':
+ case 'X':
return 1;
}
return 0;
@@ -463,6 +465,7 @@ longopts[] = {
{"ipv6", 0, '6', 0, "listen on IPv6 only"},
PMAPI_OPTIONS_HEADER ("Graphite options"),
{"graphite", 0, 'G', 0, "enable graphite 0.9 API/backend emulation"},
+ {"graphite-noencode", 0, 'X', 0, "don't encode special characters that are now allowed by graphite"},
{"graphite-timestamp", 1, 'i', "SEC", "minimum graphite timestep (s) [default 60]"},
{"graphite-archivedir", 0, 'I', 0, "prefer archive directories [default OFF]"},
PMAPI_OPTIONS_HEADER ("Context options"),
@@ -544,6 +547,10 @@ main (int argc, char *argv[])
graphite_p = 1;
break;
+ case 'X':
+ graphite_encode = 0;
+ break;
+
case 'i':
graphite_timestep = atoi (opts.optarg);
if (graphite_timestep <= 0) {
@@ -112,10 +112,20 @@ pmgraphite_metric_encode (const string & foo)
char c = foo[i];
// Pass through enough characters to make the metric names relatively
// human-readable in the javascript guis
- if (isalnum (c) || (c == '_') || (c == ' ') || (c == '-') || (c == '/') ) {
- output << c;
- } else {
- output << "%" << hex[ (c >> 4) & 15] << hex[ (c >> 0) & 15];
+ if (graphite_encode) {
+ if (isalnum (c) || (c == '_') || (c == ' ')) {
+ output << c;
+ } else {
+ output << "-" << hex[ (c >> 4) & 15] << hex[ (c >> 0) & 15] << "-";
+ }
+ }
+ // Newer graphite/grafana support more characters
+ else {
+ if (isalnum (c) || (c == '_') || (c == ' ') || (c == '-') || (c == '/') ) {
+ output << c;
+ } else {
+ output << "%" << hex[ (c >> 4) & 15] << hex[ (c >> 0) & 15];
+ }
}
}
return output.str ();
@@ -130,22 +140,45 @@ pmgraphite_metric_decode (const string & foo)
static const char hex[] = "0123456789ABCDEF";
for (unsigned i = 0; i < foo.size (); i++) {
char c = foo[i];
- if (c == '%') {
- if (i + 2 >= foo.size ()) {
- return "";
- }
- const char *p = lower_bound (hex, hex + 16, foo[i + 1]);
- if (*p != foo[i + 1]) {
- return "";
- }
- const char *q = lower_bound (hex, hex + 16, foo[i + 2]);
- if (*q != foo[i + 2]) {
- return "";
+ if (graphite_encode) {
+ if (c == '-') {
+ if (i + 3 >= foo.size ()) {
+ return "";
+ }
+ const char *p = lower_bound (hex, hex + 16, foo[i + 1]);
+ if (*p != foo[i + 1]) {
+ return "";
+ }
+ const char *q = lower_bound (hex, hex + 16, foo[i + 2]);
+ if (*q != foo[i + 2]) {
+ return "";
+ }
+ if ('-' != foo[i + 3]) {
+ return "";
+ }
+ output += (char) (((p - hex) << 4) | (q - hex));
+ i += 3; // skip over hex bytes
+ } else {
+ output += c;
}
- output += (char) (((p - hex) << 4) | (q - hex));
- i += 2; // skip over hex bytes
} else {
- output += c;
+ if (c == '%') {
+ if (i + 2 >= foo.size ()) {
+ return "";
+ }
+ const char *p = lower_bound (hex, hex + 16, foo[i + 1]);
+ if (*p != foo[i + 1]) {
+ return "";
+ }
+ const char *q = lower_bound (hex, hex + 16, foo[i + 2]);
+ if (*q != foo[i + 2]) {
+ return "";
+ }
+ output += (char) (((p - hex) << 4) | (q - hex));
+ i += 2; // skip over hex bytes
+ } else {
+ output += c;
+ }
}
}
return output;
@@ -328,12 +361,15 @@ vector <string> pmgraphite_enumerate_metrics (struct MHD_Connection * connection
(char) __pmPathSeparator ())) {
archivepart = archivepart.substr (archivesdir.size () + 1);
}
+
// Remove the .meta part
- string metastring = ".meta";
- string::size_type metaidx = archivepart.find( metastring );
+ if (!graphite_encode) {
+ string metastring = ".meta";
+ string::size_type metaidx = archivepart.find( metastring );
- if (metaidx != std::string::npos)
- archivepart.erase(metaidx, metastring.length());
+ if (metaidx != std::string::npos)
+ archivepart.erase(metaidx, metastring.length());
+ }
archivepart = pmgraphite_metric_encode (archivepart);
@@ -1168,8 +1204,7 @@ pmgraphite_fetch_all_series (struct MHD_Connection* connection, const vector<str
js.t_start = t_start;
js.t_end = t_end;
js.t_step = t_step;
- // We took off the meta for display purposes, add it back on to open the file
- js.archive = archive_part+".meta";
+ js.archive = archive_part;
it = jobmap.insert(make_pair(archive_part,js)).first;
}

1 comment on commit 4641bbf

Contributor

fche commented on 4641bbf Nov 6, 2015

It would be nice to have at least one part of the 661 test rerun pmwebd with -X to exercise this part.

Please sign in to comment.