Skip to content

Commit

Permalink
Merge: *(querylog): added offset/limit parameters
Browse files Browse the repository at this point in the history
* commit '61a24ffc71eda26e10a11e3a9c8506909b6c4b52':
  *(querylog): decode methods to a new file
  *(querylog): added offset/limit parameters
  • Loading branch information
ameshkov committed May 27, 2020
2 parents 605d2ae + 61a24ff commit 16a6aad
Show file tree
Hide file tree
Showing 14 changed files with 1,029 additions and 776 deletions.
4 changes: 3 additions & 1 deletion changelog.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ module.exports = {
],
"scopes": [
"",
"ui",
"global",
"dnsfilter",
"home",
"dnsforward",
"dhcpd",
"documentation"
"querylog",
"documentation",
],
"types": {
"+": {
Expand Down
7 changes: 7 additions & 0 deletions openapi/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# AdGuard Home API Change Log

## v0.103: API changes

### API: Get querylog: GET /control/querylog

* Added optional "offset" and "limit" parameters

We are still using "older_than" approach in AdGuard Home UI, but we realize that it's easier to use offset/limit so here is this option now.

## v0.102: API changes

Expand Down
15 changes: 14 additions & 1 deletion openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,26 @@ paths:
tags:
- log
operationId: queryLog
summary: Get DNS server query log
summary: Get DNS server query log.
parameters:
- name: older_than
in: query
description: Filter by older than
schema:
type: string
- name: offset
in: query
description:
Specify the ranking number of the first item on the page.
Even though it is possible to use "offset" and "older_than",
we recommend choosing one of them and sticking to it.
schema:
type: integer
- name: limit
in: query
description: Limit the number of records to be returned
schema:
type: integer
- name: filter_domain
in: query
description: Filter by domain name
Expand Down
175 changes: 175 additions & 0 deletions querylog/decode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package querylog

import (
"encoding/base64"
"strconv"
"strings"
"time"

"github.com/AdguardTeam/AdGuardHome/dnsfilter"
"github.com/AdguardTeam/golibs/log"
"github.com/miekg/dns"
)

// decodeLogEntry - decodes query log entry from a line
// nolint (gocyclo)
func decodeLogEntry(ent *logEntry, str string) {
var b bool
var i int
var err error
for {
k, v, t := readJSON(&str)
if t == jsonTErr {
break
}
switch k {
case "IP":
if len(ent.IP) == 0 {
ent.IP = v
}
case "T":
ent.Time, err = time.Parse(time.RFC3339, v)

case "QH":
ent.QHost = v
case "QT":
ent.QType = v
case "QC":
ent.QClass = v

case "Answer":
ent.Answer, err = base64.StdEncoding.DecodeString(v)
case "OrigAnswer":
ent.OrigAnswer, err = base64.StdEncoding.DecodeString(v)

case "IsFiltered":
b, err = strconv.ParseBool(v)
ent.Result.IsFiltered = b
case "Rule":
ent.Result.Rule = v
case "FilterID":
i, err = strconv.Atoi(v)
ent.Result.FilterID = int64(i)
case "Reason":
i, err = strconv.Atoi(v)
ent.Result.Reason = dnsfilter.Reason(i)

case "Upstream":
ent.Upstream = v
case "Elapsed":
i, err = strconv.Atoi(v)
ent.Elapsed = time.Duration(i)

// pre-v0.99.3 compatibility:
case "Question":
var qstr []byte
qstr, err = base64.StdEncoding.DecodeString(v)
if err != nil {
break
}
q := new(dns.Msg)
err = q.Unpack(qstr)
if err != nil {
break
}
ent.QHost = q.Question[0].Name
if len(ent.QHost) == 0 {
break
}
ent.QHost = ent.QHost[:len(ent.QHost)-1]
ent.QType = dns.TypeToString[q.Question[0].Qtype]
ent.QClass = dns.ClassToString[q.Question[0].Qclass]
case "Time":
ent.Time, err = time.Parse(time.RFC3339, v)
}

if err != nil {
log.Debug("decodeLogEntry err: %s", err)
break
}
}
}

// Get value from "key":"value"
func readJSONValue(s, name string) string {
i := strings.Index(s, "\""+name+"\":\"")
if i == -1 {
return ""
}
start := i + 1 + len(name) + 3
i = strings.IndexByte(s[start:], '"')
if i == -1 {
return ""
}
end := start + i
return s[start:end]
}

const (
jsonTErr = iota
jsonTObj
jsonTStr
jsonTNum
jsonTBool
)

// Parse JSON key-value pair
// e.g.: "key":VALUE where VALUE is "string", true|false (boolean), or 123.456 (number)
// Note the limitations:
// . doesn't support whitespace
// . doesn't support "null"
// . doesn't validate boolean or number
// . no proper handling of {} braces
// . no handling of [] brackets
// Return (key, value, type)
func readJSON(ps *string) (string, string, int32) {
s := *ps
k := ""
v := ""
t := int32(jsonTErr)

q1 := strings.IndexByte(s, '"')
if q1 == -1 {
return k, v, t
}
q2 := strings.IndexByte(s[q1+1:], '"')
if q2 == -1 {
return k, v, t
}
k = s[q1+1 : q1+1+q2]
s = s[q1+1+q2+1:]

if len(s) < 2 || s[0] != ':' {
return k, v, t
}

if s[1] == '"' {
q2 = strings.IndexByte(s[2:], '"')
if q2 == -1 {
return k, v, t
}
v = s[2 : 2+q2]
t = jsonTStr
s = s[2+q2+1:]

} else if s[1] == '{' {
t = jsonTObj
s = s[1+1:]

} else {
sep := strings.IndexAny(s[1:], ",}")
if sep == -1 {
return k, v, t
}
v = s[1 : 1+sep]
if s[1] == 't' || s[1] == 'f' {
t = jsonTBool
} else if s[1] == '.' || (s[1] >= '0' && s[1] <= '9') {
t = jsonTNum
}
s = s[1+sep+1:]
}

*ps = s
return k, v, t
}
34 changes: 34 additions & 0 deletions querylog/decode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package querylog

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestJSON(t *testing.T) {
s := `
{"keystr":"val","obj":{"keybool":true,"keyint":123456}}
`
k, v, jtype := readJSON(&s)
assert.Equal(t, jtype, int32(jsonTStr))
assert.Equal(t, "keystr", k)
assert.Equal(t, "val", v)

k, v, jtype = readJSON(&s)
assert.Equal(t, jtype, int32(jsonTObj))
assert.Equal(t, "obj", k)

k, v, jtype = readJSON(&s)
assert.Equal(t, jtype, int32(jsonTBool))
assert.Equal(t, "keybool", k)
assert.Equal(t, "true", v)

k, v, jtype = readJSON(&s)
assert.Equal(t, jtype, int32(jsonTNum))
assert.Equal(t, "keyint", k)
assert.Equal(t, "123456", v)

k, v, jtype = readJSON(&s)
assert.True(t, jtype == jsonTErr)
}
Loading

0 comments on commit 16a6aad

Please sign in to comment.