Skip to content

Commit

Permalink
allow escaping the dot character in paths using a backslash
Browse files Browse the repository at this point in the history
Occasionally expvar output contains keys that are hostnames,
IP addresses, or filenames that contain the "." character.  For
example:

{
  "bleve": {
    "bootDuration": 16559,
    "indexes": {
      "bench.bleve": {
        "index": {
          "analysis_time": 10889841135,
          "batches": 145,
          "deletes": 0,
          "errors": 0,
          "index_time": 21277401883,
          "lookup_queue_len": 0,
          "updates": 14500
        },
        "search_time": 0,
        "searches": 0
      }
    }
  }
...
}

I can now chart the lookup_queue_len value using the var:

bleve.indexes.bench\.bleve.index.lookup_queue_len

This partially addresses divan#11 (still does not escape colon character).
  • Loading branch information
mschoch committed Dec 1, 2015
1 parent 383ee49 commit e7f60e5
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 1 deletion.
46 changes: 45 additions & 1 deletion var.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const (
// Example: "mem:memstats.Alloc" => []string{"memstats", "Alloc"}
func (v VarName) ToSlice() []string {
start := strings.IndexRune(string(v), ':') + 1
slice := strings.FieldsFunc(string(v)[start:], func(r rune) bool { return r == '.' })
slice := DottedFieldsToSliceEscaped(string(v)[start:])
return slice
}

Expand Down Expand Up @@ -128,3 +128,47 @@ func roundDuration(d time.Duration) time.Duration {
}
return d
}

func DottedFieldsToSliceEscaped(s string) []string {
rv := make([]string, 0)
lastSlash := false
curr := ""
for _, r := range s {
// base case, dot not after slash
if !lastSlash && r == '.' {
if len(curr) > 0 {
rv = append(rv, curr)
curr = ""
}
continue
} else if !lastSlash {
// any character not after slash
curr += string(r)
if r == '\\' {
lastSlash = true
} else {
lastSlash = false
}
continue
} else if r == '\\' {
// last was slash, and so is this
lastSlash = false // 2 slashes = 0
// we already appended a single slash on first
continue
} else if r == '.' {
// we see \. but already appended \ last time
// replace it with .
curr = curr[:len(curr)-1] + "."
lastSlash = false
} else {
// \ and any other character, ignore
curr += string(r)
lastSlash = false
continue
}
}
if len(curr) > 0 {
rv = append(rv, curr)
}
return rv
}
45 changes: 45 additions & 0 deletions var_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,49 @@ func TestVarName(t *testing.T) {
if kind != KindDuration {
t.Fatalf("Expecting kind to be %v, but got: %v", KindDuration, kind)
}

// single \. escapes the dot
v = VarName(`bleve.indexes.bench\.bleve.index.lookup_queue_len`)

slice = v.ToSlice()
if len(slice) != 5 || slice[0] != "bleve" || slice[1] != "indexes" || slice[2] != "bench.bleve" ||
slice[3] != "index" || slice[4] != "lookup_queue_len" {
t.Fatalf("ToSlice failed: %v", slice)
}

// double \\. escapes backslash, not dot
v = VarName(`bleve.indexes.bench\\.bleve.index.lookup_queue_len`)

slice = v.ToSlice()
if len(slice) != 6 || slice[0] != "bleve" || slice[1] != "indexes" || slice[2] != "bench\\" ||
slice[3] != "bleve" || slice[4] != "index" || slice[5] != "lookup_queue_len" {
t.Fatalf("ToSlice failed: %v", slice)
}

// triple \\\. escapes backslash then dot
v = VarName(`bleve.indexes.bench\\\.bleve.index.lookup_queue_len`)

slice = v.ToSlice()
if len(slice) != 5 || slice[0] != "bleve" || slice[1] != "indexes" || slice[2] != "bench\\.bleve" ||
slice[3] != "index" || slice[4] != "lookup_queue_len" {
t.Fatalf("ToSlice failed: %v", slice)
}

// quadruple \\\\. escapes two backslashes, not dot
v = VarName(`bleve.indexes.bench\\\\.bleve.index.lookup_queue_len`)

slice = v.ToSlice()
if len(slice) != 6 || slice[0] != "bleve" || slice[1] != "indexes" || slice[2] != "bench\\\\" ||
slice[3] != "bleve" || slice[4] != "index" || slice[5] != "lookup_queue_len" {
t.Fatalf("ToSlice failed: %v", slice)
}

// unsupported \x passes through unaltered
v = VarName(`bleve.indexes.bench\xbleve.index.lookup_queue_len`)

slice = v.ToSlice()
if len(slice) != 5 || slice[0] != "bleve" || slice[1] != "indexes" || slice[2] != "bench\\xbleve" ||
slice[3] != "index" || slice[4] != "lookup_queue_len" {
t.Fatalf("ToSlice failed: %v", slice)
}
}

0 comments on commit e7f60e5

Please sign in to comment.