Repository: incubator-htrace
Updated Branches:
  refs/heads/master 2e2757f83 -> 7c27517d0


HTRACE-285. htraced tool: fix query parsing and add query_test (cmccabe)


Project: http://git-wip-us.apache.org/repos/asf/incubator-htrace/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-htrace/commit/7c27517d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-htrace/tree/7c27517d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-htrace/diff/7c27517d

Branch: refs/heads/master
Commit: 7c27517d0d2c858c1046a16a85cd50b685531eb3
Parents: 2e2757f
Author: Colin P. Mccabe <[email protected]>
Authored: Mon Nov 2 16:19:45 2015 -0800
Committer: Colin P. Mccabe <[email protected]>
Committed: Mon Nov 2 16:19:45 2015 -0800

----------------------------------------------------------------------
 .../go/src/org/apache/htrace/htrace/cmd.go      | 10 +--
 .../go/src/org/apache/htrace/htrace/queries.go  | 31 ++++---
 .../src/org/apache/htrace/htrace/query_test.go  | 88 ++++++++++++++++++++
 3 files changed, 114 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/7c27517d/htrace-htraced/go/src/org/apache/htrace/htrace/cmd.go
----------------------------------------------------------------------
diff --git a/htrace-htraced/go/src/org/apache/htrace/htrace/cmd.go 
b/htrace-htraced/go/src/org/apache/htrace/htrace/cmd.go
index f3668ea..14b7f73 100644
--- a/htrace-htraced/go/src/org/apache/htrace/htrace/cmd.go
+++ b/htrace-htraced/go/src/org/apache/htrace/htrace/cmd.go
@@ -43,7 +43,7 @@ var GIT_VERSION string
 const EXIT_SUCCESS = 0
 const EXIT_FAILURE = 1
 
-var verbose *bool
+var verbose bool
 
 const USAGE = `The Apache HTrace command-line tool.  This tool retrieves and 
modifies settings and
 other data on a running htraced daemon.
@@ -68,7 +68,7 @@ func main() {
        app.Flag("Dmy.key", "Set configuration key 'my.key' to 'my.value'.  
Replace 'my.key' "+
                "with any key you want to set.").Default("my.value").String()
        addr := app.Flag("addr", "Server address.").String()
-       verbose = app.Flag("verbose", "Verbose.").Default("false").Bool()
+       verbose = *app.Flag("verbose", "Verbose.").Default("false").Bool()
        version := app.Command("version", "Print the version of this program.")
        serverInfo := app.Command("serverInfo", "Print information retrieved 
from an htraced server.")
        serverStats := app.Command("serverStats", "Print statistics retrieved 
from the htraced server.")
@@ -100,7 +100,7 @@ func main() {
        queryArg := query.Arg("query", "The query string to send.  Query 
strings have the format "+
                "[TYPE] [OPERATOR] [CONST], joined by AND 
statements.").Required().String()
        rawQuery := app.Command("rawQuery", "Send a raw JSON query to htraced.")
-       rawQueryArg := query.Arg("json", "The query JSON to 
send.").Required().String()
+       rawQueryArg := rawQuery.Arg("json", "The query JSON to 
send.").Required().String()
        cmd := kingpin.MustParse(app.Parse(os.Args[1:]))
 
        // Add the command-line settings into the configuration.
@@ -327,7 +327,7 @@ func doLoadSpans(hcl *htrace.Client, reader io.Reader) int {
                }
                spans = append(spans, &span)
        }
-       if *verbose {
+       if verbose {
                fmt.Printf("Writing ")
                prefix := ""
                for i := range spans {
@@ -390,7 +390,7 @@ func doDumpAll(hcl *htrace.Client, outPath string, lim int) 
error {
                if err == nil {
                        _, err = fmt.Fprintf(w, "%s\n", span.ToJson())
                }
-               if *verbose {
+               if verbose {
                        numSpans++
                        now := time.Now()
                        if !now.Before(nextLogTime) {

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/7c27517d/htrace-htraced/go/src/org/apache/htrace/htrace/queries.go
----------------------------------------------------------------------
diff --git a/htrace-htraced/go/src/org/apache/htrace/htrace/queries.go 
b/htrace-htraced/go/src/org/apache/htrace/htrace/queries.go
index 4ff246c..442df4f 100644
--- a/htrace-htraced/go/src/org/apache/htrace/htrace/queries.go
+++ b/htrace-htraced/go/src/org/apache/htrace/htrace/queries.go
@@ -36,12 +36,12 @@ func tokenize(str string) []string {
                switch {
                case c == prevQuote:
                        prevQuote = rune(0)
-                       return false
+                       return true
                case prevQuote != rune(0):
                        return false
                case unicode.In(c, unicode.Quotation_Mark):
                        prevQuote = c
-                       return false
+                       return true
                default:
                        return unicode.IsSpace(c)
                }
@@ -57,7 +57,7 @@ type predicateParser struct {
 }
 
 func (ps *predicateParser) Parse() (*common.Predicate, error) {
-       if ps.curToken > len(ps.tokens) {
+       if ps.curToken >= len(ps.tokens) {
                return nil, nil
        }
        if ps.curToken > 0 {
@@ -72,7 +72,7 @@ func (ps *predicateParser) Parse() (*common.Predicate, error) 
{
                                "token %d", ps.curToken))
                }
        }
-       field := common.Field(ps.tokens[ps.curToken])
+       field := common.Field(strings.ToLower(ps.tokens[ps.curToken]))
        if !field.IsValid() {
                return nil, errors.New(fmt.Sprintf("Invalid field specifier at 
token %d.  "+
                        "Can't understand %s.  Valid field specifiers are %v", 
ps.curToken,
@@ -83,7 +83,7 @@ func (ps *predicateParser) Parse() (*common.Predicate, error) 
{
                return nil, errors.New(fmt.Sprintf("Nothing found after field 
specifier "+
                        "at token %d", ps.curToken))
        }
-       op := common.Op(ps.tokens[ps.curToken])
+       op := common.Op(strings.ToLower(ps.tokens[ps.curToken]))
        if !op.IsValid() {
                return nil, errors.New(fmt.Sprintf("Invalid operation specifier 
at token %d.  "+
                        "Can't understand %s.  Valid operation specifiers are 
%v", ps.curToken,
@@ -95,20 +95,31 @@ func (ps *predicateParser) Parse() (*common.Predicate, 
error) {
                        "at token %d", ps.curToken))
        }
        val := ps.tokens[ps.curToken]
+       ps.curToken++
        return &common.Predicate{Op: op, Field: field, Val: val}, nil
 }
 
 func parseQueryString(str string) ([]common.Predicate, error) {
        ps := predicateParser{tokens: tokenize(str)}
+       if verbose {
+               fmt.Printf("Running query [ ")
+               prefix := ""
+               for tokenIdx := range(ps.tokens) {
+                       fmt.Printf("%s'%s'", prefix, ps.tokens[tokenIdx])
+                       prefix = ", "
+               }
+               fmt.Printf(" ]\n")
+       }
        preds := make([]common.Predicate, 0)
        for {
                pred, err := ps.Parse()
-               if pred == nil {
-                       break
-               }
                if err != nil {
                        return nil, err
                }
+               if pred == nil {
+                       break
+               }
+               preds = append(preds, *pred)
        }
        if len(preds) == 0 {
                return nil, errors.New("Empty query string")
@@ -140,7 +151,7 @@ func doRawQuery(hcl *htrace.Client, str string) error {
 
 // Send a query.
 func doQuery(hcl *htrace.Client, query *common.Query) error {
-       if *verbose {
+       if verbose {
                qbytes, err := json.Marshal(*query)
                if err != nil {
                        qbytes = []byte("marshaling error: " + err.Error())
@@ -151,7 +162,7 @@ func doQuery(hcl *htrace.Client, query *common.Query) error 
{
        if err != nil {
                return err
        }
-       if *verbose {
+       if verbose {
                fmt.Printf("%d results...\n", len(spans))
        }
        for i := range spans {

http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/7c27517d/htrace-htraced/go/src/org/apache/htrace/htrace/query_test.go
----------------------------------------------------------------------
diff --git a/htrace-htraced/go/src/org/apache/htrace/htrace/query_test.go 
b/htrace-htraced/go/src/org/apache/htrace/htrace/query_test.go
new file mode 100644
index 0000000..cab1e92
--- /dev/null
+++ b/htrace-htraced/go/src/org/apache/htrace/htrace/query_test.go
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package main
+
+import (
+       "encoding/json"
+       "org/apache/htrace/common"
+       "reflect"
+       "testing"
+)
+
+func predsToStr(preds []common.Predicate) string {
+       b, err := json.MarshalIndent(preds, "", "  ")
+       if err != nil {
+               return "JSON marshaling error: " + err.Error()
+       }
+       return string(b)
+}
+
+func checkParseQueryString(t *testing.T, str string, epreds 
[]common.Predicate) {
+       preds, err := parseQueryString(str)
+       if err != nil {
+               t.Fatalf("got unexpected parseQueryString error: %s\n", 
err.Error())
+       }
+       if !reflect.DeepEqual(preds, epreds) {
+               t.Fatalf("Unexpected result from parseQueryString.  " +
+                       "Expected: %s, got: %s\n", predsToStr(epreds), 
predsToStr(preds))
+       }
+}
+
+func TestParseQueryString(t *testing.T) {
+       verbose = testing.Verbose()
+       checkParseQueryString(t, "description eq ls", []common.Predicate {
+               common.Predicate {
+                       Op: common.EQUALS,
+                       Field: common.DESCRIPTION,
+                       Val: "ls",
+               },
+       })
+       checkParseQueryString(t, "begin gt 123 and end le 456", 
[]common.Predicate {
+               common.Predicate {
+                       Op: common.GREATER_THAN,
+                       Field: common.BEGIN_TIME,
+                       Val: "123",
+               },
+               common.Predicate {
+                       Op: common.LESS_THAN_OR_EQUALS,
+                       Field: common.END_TIME,
+                       Val: "456",
+               },
+       })
+       checkParseQueryString(t, `DESCRIPTION cn "Foo Bar" and ` +
+               `BEGIN ge "999" and SPANID eq 
"4565d8abc4f70ac1216a3f1834c6860b"`,
+               []common.Predicate {
+               common.Predicate {
+                       Op: common.CONTAINS,
+                       Field: common.DESCRIPTION,
+                       Val: "Foo Bar",
+               },
+               common.Predicate {
+                       Op: common.GREATER_THAN_OR_EQUALS,
+                       Field: common.BEGIN_TIME,
+                       Val: "999",
+               },
+               common.Predicate {
+                       Op: common.EQUALS,
+                       Field: common.SPAN_ID,
+                       Val: "4565d8abc4f70ac1216a3f1834c6860b",
+               },
+       })
+}

Reply via email to