Skip to content

Commit

Permalink
logging queries.add :starts and :ends for log queries (Netflix#1471)
Browse files Browse the repository at this point in the history
Adds support for `:starts` and `:ends` which are frequently used
with some log queries internally.
  • Loading branch information
manolama committed May 22, 2024
1 parent bcd5d79 commit 180ac3c
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ object QueryVocabulary extends Vocabulary {
Regex,
RegexIgnoreCase,
Contains,
Starts,
Ends,
In,
And,
Or,
Expand Down Expand Up @@ -363,6 +365,63 @@ object QueryVocabulary extends Vocabulary {
List("name,request", "result,error")
}

case object Starts extends KeyValueWord {

override def name: String = "starts"

def newInstance(k: String, v: String): Query = Query.Regex(k, PatternUtils.escape(v))

override def summary: String =
"""
|Query expression that matches time series with a value that starts with the given
|sequence of characters. This version is case sensitive.
|
|Suppose you have four time series:
|
|* `name=http.requests, status=200, nf.app=server`
|* `name=sys.cpu, type=user, nf.app=foo`
|* `name=sys.cpu, type=user, nf.app=bar`
|* `name=sys.cpu, type=user, nf.app=foobar`
|
|The query `nf.app,bar,:starts` would match series with "bar" at the beginning of
|the string:
|
|* `name=sys.cpu, type=user, nf.app=bar`
""".stripMargin.trim

override def examples: List[String] =
List("name,req", "result,err")
}

case object Ends extends KeyValueWord {

override def name: String = "ends"

def newInstance(k: String, v: String): Query = Query.Regex(k, s".*${PatternUtils.escape(v)}$$")

override def summary: String =
"""
|Query expression that matches time series with a value that ends with the given
|sequence of characters. This version is case sensitive.
|
|Suppose you have four time series:
|
|* `name=http.requests, status=200, nf.app=server`
|* `name=sys.cpu, type=user, nf.app=foo`
|* `name=sys.cpu, type=user, nf.app=bar`
|* `name=sys.cpu, type=user, nf.app=foobar`
|
|The query `nf.app,bar,:ends` would match series with "bar" at the end of
|the string:
|
|* `name=sys.cpu, type=user, nf.app=bar`
|* `name=sys.cpu, type=user, nf.app=foobar`
""".stripMargin.trim

override def examples: List[String] =
List("name,error", "result,failed")
}

case object In extends SimpleWord {

override def name: String = "in"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class ModelExtractorsSuite extends FunSuite {
}

completionTest("name", 8)
completionTest("name,sps", 20)
completionTest("name,sps", 22)
completionTest("name,sps,:eq", 20)
completionTest("name,sps,:eq,app,foo,:eq", 41)
completionTest("name,sps,:eq,app,foo,:eq,:and,(,asg,)", 12)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,35 @@ class QueryVocabularySuite extends FunSuite {
assert(!q.matches(Map("foo" -> "my $var. [work-in progress]")))
}

test("starts, prefix and escape") {
val exp = interpreter.execute("a,[foo],:starts").stack(0)
assertEquals(exp.asInstanceOf[Regex].pattern.prefix(), "[foo]")
assertEquals(exp.asInstanceOf[Regex].pattern.toString, "^\\[foo\\]")
}

test("starts, matches escaped") {
val q = interpreter
.execute("foo,my $var.,:starts")
.stack(0)
.asInstanceOf[Regex]
assert(q.matches(Map("foo" -> "my $var.")))
assert(!q.matches(Map("foo" -> "initialize my $var. [work-in-progress], not a range")))
assert(q.matches(Map("foo" -> "my $var. [work-in progress]")))
}

test("ends, suffix and escape") {
val exp = interpreter.execute("a,[foo],:ends").stack(0)
assertEquals(exp.asInstanceOf[Regex].pattern.prefix(), null)
assertEquals(exp.asInstanceOf[Regex].pattern.toString, ".*\\[foo\\]$")
}

test("ends, matches escaped") {
val q = interpreter
.execute("foo,my $var.,:ends")
.stack(0)
.asInstanceOf[Regex]
assert(q.matches(Map("foo" -> "my $var.")))
assert(!q.matches(Map("foo" -> "initialize my $var. [work-in-progress], not a range")))
assert(!q.matches(Map("foo" -> "my $var. [work-in progress]")))
}
}

0 comments on commit 180ac3c

Please sign in to comment.