Pull request: 2504 querylog interval
Merge in DNS/adguard-home from 2504-querylog-ivl to master
Updates #2504.
Squashed commit of the following:
commit 5d15a6f735cd195fc81c8af909b56fbc7db1fe21
Merge: 8cd5c30d 97073d0d
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Thu Jul 1 18:45:10 2021 +0300
Merge branch 'master' into 2504-querylog-ivl
commit 8cd5c30de6f72d4b12162dbc9e3d90132795fe94
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Thu Jul 1 18:35:50 2021 +0300
client: fix fmt
commit e95d462c31d886bacec0735acc567fec7c962149
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Thu Jul 1 17:58:06 2021 +0300
home: imp code
commit 48737b249c52a997a4f34dac45fbaf699477b007
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Thu Jul 1 17:23:18 2021 +0300
home: imp duration
commit 44f5dc3d3ada5120d74caa24cace9a253b8f15d3
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Thu Jul 1 16:55:31 2021 +0300
home: imp code, docs
commit bb2826521b7e5d248ce2ab686528219c312b8ba2
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Thu Jul 1 16:11:40 2021 +0300
all: imp code, docs
commit d688aed1f340807a8bac8807c263956b0fc16f5b
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Thu Jul 1 13:49:42 2021 +0300
all: change querylog interval setting format
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
|
||||
@@ -102,11 +103,12 @@ type dnsConfig struct {
|
||||
// time interval for statistics (in days)
|
||||
StatsInterval uint32 `yaml:"statistics_interval"`
|
||||
|
||||
QueryLogEnabled bool `yaml:"querylog_enabled"` // if true, query log is enabled
|
||||
QueryLogFileEnabled bool `yaml:"querylog_file_enabled"` // if true, query log will be written to a file
|
||||
QueryLogInterval uint32 `yaml:"querylog_interval"` // time interval for query log (in days)
|
||||
QueryLogMemSize uint32 `yaml:"querylog_size_memory"` // number of entries kept in memory before they are flushed to disk
|
||||
AnonymizeClientIP bool `yaml:"anonymize_client_ip"` // anonymize clients' IP addresses in logs and stats
|
||||
QueryLogEnabled bool `yaml:"querylog_enabled"` // if true, query log is enabled
|
||||
QueryLogFileEnabled bool `yaml:"querylog_file_enabled"` // if true, query log will be written to a file
|
||||
// QueryLogInterval is the interval for query log's files rotation.
|
||||
QueryLogInterval Duration `yaml:"querylog_interval"`
|
||||
QueryLogMemSize uint32 `yaml:"querylog_size_memory"` // number of entries kept in memory before they are flushed to disk
|
||||
AnonymizeClientIP bool `yaml:"anonymize_client_ip"` // anonymize clients' IP addresses in logs and stats
|
||||
|
||||
dnsforward.FilteringConfig `yaml:",inline"`
|
||||
|
||||
@@ -185,7 +187,7 @@ var config = configuration{
|
||||
},
|
||||
FilteringEnabled: true, // whether or not use filter lists
|
||||
FiltersUpdateIntervalHours: 24,
|
||||
UpstreamTimeout: Duration{dnsforward.DefaultTimeout},
|
||||
UpstreamTimeout: Duration{Duration: dnsforward.DefaultTimeout},
|
||||
LocalDomainName: "lan",
|
||||
ResolveClients: true,
|
||||
UsePrivateRDNS: true,
|
||||
@@ -212,7 +214,7 @@ func initConfig() {
|
||||
|
||||
config.DNS.QueryLogEnabled = true
|
||||
config.DNS.QueryLogFileEnabled = true
|
||||
config.DNS.QueryLogInterval = 90
|
||||
config.DNS.QueryLogInterval = Duration{Duration: 90 * 24 * time.Hour}
|
||||
config.DNS.QueryLogMemSize = 1000
|
||||
|
||||
config.DNS.CacheSize = 4 * 1024 * 1024
|
||||
@@ -281,7 +283,7 @@ func parseConfig() error {
|
||||
}
|
||||
|
||||
if config.DNS.UpstreamTimeout.Duration == 0 {
|
||||
config.DNS.UpstreamTimeout = Duration{dnsforward.DefaultTimeout}
|
||||
config.DNS.UpstreamTimeout = Duration{Duration: dnsforward.DefaultTimeout}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -328,7 +330,7 @@ func (c *configuration) write() error {
|
||||
Context.queryLog.WriteDiskConfig(&dc)
|
||||
config.DNS.QueryLogEnabled = dc.Enabled
|
||||
config.DNS.QueryLogFileEnabled = dc.FileEnabled
|
||||
config.DNS.QueryLogInterval = dc.RotationIvl
|
||||
config.DNS.QueryLogInterval = Duration{Duration: dc.RotationIvl}
|
||||
config.DNS.QueryLogMemSize = dc.MemSize
|
||||
config.DNS.AnonymizeClientIP = dc.AnonymizeClientIP
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func initDNSServer() error {
|
||||
HTTPRegister: httpRegister,
|
||||
FindClient: Context.clients.findMultiple,
|
||||
BaseDir: baseDir,
|
||||
RotationIvl: config.DNS.QueryLogInterval,
|
||||
RotationIvl: config.DNS.QueryLogInterval.Duration,
|
||||
MemSize: config.DNS.QueryLogMemSize,
|
||||
Enabled: config.DNS.QueryLogEnabled,
|
||||
FileEnabled: config.DNS.QueryLogFileEnabled,
|
||||
|
||||
@@ -12,6 +12,35 @@ type Duration struct {
|
||||
time.Duration
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer interface for Duration. It wraps
|
||||
// time.Duration.String method and additionally cuts off non-leading zero values
|
||||
// of minutes and seconds. Some values which are differ between the
|
||||
// implementations:
|
||||
//
|
||||
// Duration: "1m", time.Duration: "1m0s"
|
||||
// Duration: "1h", time.Duration: "1h0m0s"
|
||||
// Duration: "1h1m", time.Duration: "1h1m0s"
|
||||
//
|
||||
func (d Duration) String() (str string) {
|
||||
str = d.Duration.String()
|
||||
secs := d.Seconds()
|
||||
var secsInt int
|
||||
if secsInt = int(secs); float64(secsInt) != secs || secsInt%60 != 0 {
|
||||
return str
|
||||
}
|
||||
|
||||
const (
|
||||
tailMin = len(`0s`)
|
||||
tailMinSec = len(`0m0s`)
|
||||
)
|
||||
|
||||
if (secsInt%3600)/60 != 0 {
|
||||
return str[:len(str)-tailMin]
|
||||
}
|
||||
|
||||
return str[:len(str)-tailMinSec]
|
||||
}
|
||||
|
||||
// MarshalText implements the encoding.TextMarshaler interface for Duration.
|
||||
func (d Duration) MarshalText() (text []byte, err error) {
|
||||
return []byte(d.String()), nil
|
||||
@@ -19,6 +48,8 @@ func (d Duration) MarshalText() (text []byte, err error) {
|
||||
|
||||
// UnmarshalText implements the encoding.TextUnmarshaler interface for
|
||||
// *Duration.
|
||||
//
|
||||
// TODO(e.burkov): Make it able to parse larger units like days.
|
||||
func (d *Duration) UnmarshalText(b []byte) (err error) {
|
||||
defer func() { err = errors.Annotate(err, "unmarshalling duration: %w") }()
|
||||
|
||||
|
||||
@@ -12,6 +12,50 @@ import (
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func TestDuration_String(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
val time.Duration
|
||||
}{{
|
||||
name: "1s",
|
||||
val: time.Second,
|
||||
}, {
|
||||
name: "1m",
|
||||
val: time.Minute,
|
||||
}, {
|
||||
name: "1h",
|
||||
val: time.Hour,
|
||||
}, {
|
||||
name: "1m1s",
|
||||
val: time.Minute + time.Second,
|
||||
}, {
|
||||
name: "1h1m",
|
||||
val: time.Hour + time.Minute,
|
||||
}, {
|
||||
name: "1h0m1s",
|
||||
val: time.Hour + time.Second,
|
||||
}, {
|
||||
name: "1ms",
|
||||
val: time.Millisecond,
|
||||
}, {
|
||||
name: "1h0m0.001s",
|
||||
val: time.Hour + time.Millisecond,
|
||||
}, {
|
||||
name: "1.001s",
|
||||
val: time.Second + time.Millisecond,
|
||||
}, {
|
||||
name: "1m1.001s",
|
||||
val: time.Minute + time.Second + time.Millisecond,
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
d := Duration{Duration: tc.val}
|
||||
assert.Equal(t, tc.name, d.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// durationEncodingTester is a helper struct to simplify testing different
|
||||
// Duration marshalling and unmarshalling cases.
|
||||
type durationEncodingTester struct {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
@@ -19,7 +20,7 @@ import (
|
||||
)
|
||||
|
||||
// currentSchemaVersion is the current schema version.
|
||||
const currentSchemaVersion = 11
|
||||
const currentSchemaVersion = 12
|
||||
|
||||
// These aliases are provided for convenience.
|
||||
type (
|
||||
@@ -82,6 +83,7 @@ func upgradeConfigSchema(oldVersion int, diskConf yobj) (err error) {
|
||||
upgradeSchema8to9,
|
||||
upgradeSchema9to10,
|
||||
upgradeSchema10to11,
|
||||
upgradeSchema11to12,
|
||||
}
|
||||
|
||||
n := 0
|
||||
@@ -647,6 +649,46 @@ func upgradeSchema10to11(diskConf yobj) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// upgradeSchema11to12 performs the following changes:
|
||||
//
|
||||
// # BEFORE:
|
||||
// 'querylog_interval': 90
|
||||
//
|
||||
// # AFTER:
|
||||
// 'querylog_interval': '2160h'
|
||||
//
|
||||
func upgradeSchema11to12(diskConf yobj) (err error) {
|
||||
log.Printf("Upgrade yaml: 11 to 12")
|
||||
diskConf["schema_version"] = 12
|
||||
|
||||
dnsVal, ok := diskConf["dns"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
var dns yobj
|
||||
dns, ok = dnsVal.(yobj)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type of dns: %T", dnsVal)
|
||||
}
|
||||
|
||||
const field = "querylog_interval"
|
||||
|
||||
// Set the initial value from home.initConfig function.
|
||||
qlogIvl := 90
|
||||
qlogIvlVal, ok := dns[field]
|
||||
if ok {
|
||||
qlogIvl, ok = qlogIvlVal.(int)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type of %s: %T", field, qlogIvlVal)
|
||||
}
|
||||
}
|
||||
|
||||
dns[field] = Duration{Duration: time.Duration(qlogIvl) * 24 * time.Hour}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(a.garipov): Replace with log.Output when we port it to our logging
|
||||
// package.
|
||||
func funcName() string {
|
||||
|
||||
@@ -2,6 +2,7 @@ package home
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -415,3 +416,98 @@ func TestUpgradeSchema10to11(t *testing.T) {
|
||||
check(t, conf)
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpgradeSchema11to12(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ivl any
|
||||
want any
|
||||
wantErr string
|
||||
name string
|
||||
}{{
|
||||
ivl: 1,
|
||||
want: Duration{Duration: 24 * time.Hour},
|
||||
wantErr: "",
|
||||
name: "success",
|
||||
}, {
|
||||
ivl: 0.25,
|
||||
want: 0,
|
||||
wantErr: "unexpected type of querylog_interval: float64",
|
||||
name: "fail",
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
conf := yobj{
|
||||
"dns": yobj{
|
||||
"querylog_interval": tc.ivl,
|
||||
},
|
||||
"schema_version": 11,
|
||||
}
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := upgradeSchema11to12(conf)
|
||||
|
||||
if tc.wantErr != "" {
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, tc.wantErr, err.Error())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, conf["schema_version"], 12)
|
||||
|
||||
dnsVal, ok := conf["dns"]
|
||||
require.True(t, ok)
|
||||
|
||||
var newDNSConf yobj
|
||||
newDNSConf, ok = dnsVal.(yobj)
|
||||
require.True(t, ok)
|
||||
|
||||
var newIvl Duration
|
||||
newIvl, ok = newDNSConf["querylog_interval"].(Duration)
|
||||
require.True(t, ok)
|
||||
|
||||
assert.Equal(t, tc.want, newIvl)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("no_dns", func(t *testing.T) {
|
||||
err := upgradeSchema11to12(yobj{})
|
||||
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("bad_dns", func(t *testing.T) {
|
||||
err := upgradeSchema11to12(yobj{
|
||||
"dns": 0,
|
||||
})
|
||||
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, "unexpected type of dns: int", err.Error())
|
||||
})
|
||||
|
||||
t.Run("no_field", func(t *testing.T) {
|
||||
conf := yobj{
|
||||
"dns": yobj{},
|
||||
}
|
||||
|
||||
err := upgradeSchema11to12(conf)
|
||||
require.NoError(t, err)
|
||||
|
||||
dns, ok := conf["dns"]
|
||||
require.True(t, ok)
|
||||
|
||||
var dnsVal yobj
|
||||
dnsVal, ok = dns.(yobj)
|
||||
require.True(t, ok)
|
||||
|
||||
var ivl interface{}
|
||||
ivl, ok = dnsVal["querylog_interval"]
|
||||
require.True(t, ok)
|
||||
|
||||
var ivlVal Duration
|
||||
ivlVal, ok = ivl.(Duration)
|
||||
require.True(t, ok)
|
||||
|
||||
assert.Equal(t, 90*24*time.Hour, ivlVal.Duration)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user