Pull request 2145: 5992-stats-qlog-custom-dir
Updates #5992. Squashed commit of the following: commit 39d3df705ef68672ec9406d81e00daf52a3b3c70 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Mon Feb 12 15:25:22 2024 +0300 all: fix typo commit 21e03e4d5a7624a68add53734a127652053845a2 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Mon Feb 12 15:22:35 2024 +0300 all: upd docs commit 11180061619f4352774d4bc8c85b481ae28f0d0b Merge: ac5fd8dc87f8370744
Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Mon Feb 12 14:57:35 2024 +0300 Merge branch 'master' into 5992-stats-qlog-custom-dir commit ac5fd8dc82c9c6e88a182cd6e6aed07bf3548639 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Wed Feb 7 14:55:51 2024 +0300 all: upd chlog commit fe00652e158db65e0e735a19cf88aa999ece3e62 Merge: 21ad1ecf756b98080f
Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Wed Feb 7 14:53:24 2024 +0300 Merge branch 'master' into 5992-stats-qlog-custom-dir commit 21ad1ecf7b30c3c8f45d54210d7297966126b0f7 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Wed Feb 7 14:52:12 2024 +0300 home: imp docs commit 739b158de77e673ef80efdaa523044939ea879d5 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Mon Feb 5 20:15:50 2024 +0300 home: add stats qlog custom dir
This commit is contained in:
parent
7f83707449
commit
d338451faf
|
@ -30,6 +30,8 @@ NOTE: Add new changes BELOW THIS COMMENT.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Ability to define custom directories for storage of query log files and
|
||||||
|
statistics ([#5992]).
|
||||||
- Context menu item in the Query Log to add a Client to the Persistent client
|
- Context menu item in the Query Log to add a Client to the Persistent client
|
||||||
list ([#6679]).
|
list ([#6679]).
|
||||||
|
|
||||||
|
@ -59,6 +61,7 @@ NOTE: Add new changes BELOW THIS COMMENT.
|
||||||
|
|
||||||
- Go 1.20 support, as it has reached end of life.
|
- Go 1.20 support, as it has reached end of life.
|
||||||
|
|
||||||
|
[#5992]: https://github.com/AdguardTeam/AdGuardHome/issues/5992
|
||||||
[#6679]: https://github.com/AdguardTeam/AdGuardHome/issues/6679
|
[#6679]: https://github.com/AdguardTeam/AdGuardHome/issues/6679
|
||||||
|
|
||||||
[go-toolchain]: https://go.dev/blog/toolchain
|
[go-toolchain]: https://go.dev/blog/toolchain
|
||||||
|
|
|
@ -154,8 +154,8 @@ func pathsToPatterns(fsys fs.FS, paths []string) (patterns []string, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleEvents concurrently handles the file system events. It closes the
|
// handleEvents concurrently handles the file system events. It closes the
|
||||||
// update channel of HostsContainer when finishes. It's used to be called
|
// update channel of HostsContainer when finishes. It is intended to be used as
|
||||||
// within a separate goroutine.
|
// a goroutine.
|
||||||
func (hc *HostsContainer) handleEvents() {
|
func (hc *HostsContainer) handleEvents() {
|
||||||
defer log.OnPanic(fmt.Sprintf("%s: handling events", hostsContainerPrefix))
|
defer log.OnPanic(fmt.Sprintf("%s: handling events", hostsContainerPrefix))
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ func NewOSWritesWatcher() (w FSWatcher, err error) {
|
||||||
return fsw, nil
|
return fsw, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleErrors handles accompanying errors. It used to be called in a separate
|
// handleErrors handles accompanying errors. It is intended to be used as a
|
||||||
// goroutine.
|
// goroutine.
|
||||||
func (w *osWatcher) handleErrors() {
|
func (w *osWatcher) handleErrors() {
|
||||||
defer log.OnPanic(fmt.Sprintf("%s: handling errors", osWatcherPref))
|
defer log.OnPanic(fmt.Sprintf("%s: handling errors", osWatcherPref))
|
||||||
|
@ -100,7 +100,7 @@ func (w *osWatcher) Close() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleEvents notifies about the received file system's event if needed. It
|
// handleEvents notifies about the received file system's event if needed. It
|
||||||
// used to be called in a separate goroutine.
|
// is intended to be used as a goroutine.
|
||||||
func (w *osWatcher) handleEvents() {
|
func (w *osWatcher) handleEvents() {
|
||||||
defer log.OnPanic(fmt.Sprintf("%s: handling events", osWatcherPref))
|
defer log.OnPanic(fmt.Sprintf("%s: handling events", osWatcherPref))
|
||||||
|
|
||||||
|
|
|
@ -592,7 +592,7 @@ func setOtherDHCPResult(ifaceName string, result *dhcpSearchResult) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseLease parses a lease from r. If there is no error returns DHCPServer
|
// parseLease parses a lease from r. If there is no error returns DHCPServer
|
||||||
// and *Lease. r must be non-nil.
|
// and *Lease. r must be non-nil.
|
||||||
func (s *server) parseLease(r io.Reader) (srv DHCPServer, lease *dhcpsvc.Lease, err error) {
|
func (s *server) parseLease(r io.Reader) (srv DHCPServer, lease *dhcpsvc.Lease, err error) {
|
||||||
l := &leaseStatic{}
|
l := &leaseStatic{}
|
||||||
err = json.NewDecoder(r).Decode(l)
|
err = json.NewDecoder(r).Decode(l)
|
||||||
|
|
|
@ -40,7 +40,7 @@ type ClientsContainer interface {
|
||||||
) (conf *proxy.CustomUpstreamConfig, err error)
|
) (conf *proxy.CustomUpstreamConfig, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config represents the DNS filtering configuration of AdGuard Home. The zero
|
// Config represents the DNS filtering configuration of AdGuard Home. The zero
|
||||||
// Config is empty and ready for use.
|
// Config is empty and ready for use.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// Callbacks for other modules
|
// Callbacks for other modules
|
||||||
|
|
|
@ -140,8 +140,7 @@ func (clients *clientsContainer) Init(
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleHostsUpdates receives the updates from the hosts container and adds
|
// handleHostsUpdates receives the updates from the hosts container and adds
|
||||||
// them to the clients container. It's used to be called in a separate
|
// them to the clients container. It is intended to be used as a goroutine.
|
||||||
// goroutine.
|
|
||||||
func (clients *clientsContainer) handleHostsUpdates() {
|
func (clients *clientsContainer) handleHostsUpdates() {
|
||||||
for upd := range clients.etcHosts.Upd() {
|
for upd := range clients.etcHosts.Upd() {
|
||||||
clients.addFromHostsFile(upd)
|
clients.addFromHostsFile(upd)
|
||||||
|
|
|
@ -259,6 +259,10 @@ type tlsConfigSettings struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type queryLogConfig struct {
|
type queryLogConfig struct {
|
||||||
|
// DirPath is the custom directory for logs. If it's empty the default
|
||||||
|
// directory will be used. See [homeContext.getDataDir].
|
||||||
|
DirPath string `yaml:"dir_path"`
|
||||||
|
|
||||||
// Ignored is the list of host names, which should not be written to log.
|
// Ignored is the list of host names, which should not be written to log.
|
||||||
// "." is considered to be the root domain.
|
// "." is considered to be the root domain.
|
||||||
Ignored []string `yaml:"ignored"`
|
Ignored []string `yaml:"ignored"`
|
||||||
|
@ -278,6 +282,10 @@ type queryLogConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type statsConfig struct {
|
type statsConfig struct {
|
||||||
|
// DirPath is the custom directory for statistics. If it's empty the
|
||||||
|
// default directory is used. See [homeContext.getDataDir].
|
||||||
|
DirPath string `yaml:"dir_path"`
|
||||||
|
|
||||||
// Ignored is the list of host names, which should not be counted.
|
// Ignored is the list of host names, which should not be counted.
|
||||||
Ignored []string `yaml:"ignored"`
|
Ignored []string `yaml:"ignored"`
|
||||||
|
|
||||||
|
|
|
@ -46,12 +46,15 @@ func onConfigModified() {
|
||||||
// server and initializes it at last. It also must not be called unless
|
// server and initializes it at last. It also must not be called unless
|
||||||
// [config] and [Context] are initialized.
|
// [config] and [Context] are initialized.
|
||||||
func initDNS() (err error) {
|
func initDNS() (err error) {
|
||||||
baseDir := Context.getDataDir()
|
|
||||||
|
|
||||||
anonymizer := config.anonymizer()
|
anonymizer := config.anonymizer()
|
||||||
|
|
||||||
|
statsDir, querylogDir, err := checkStatsAndQuerylogDirs(&Context, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
statsConf := stats.Config{
|
statsConf := stats.Config{
|
||||||
Filename: filepath.Join(baseDir, "stats.db"),
|
Filename: filepath.Join(statsDir, "stats.db"),
|
||||||
Limit: config.Stats.Interval.Duration,
|
Limit: config.Stats.Interval.Duration,
|
||||||
ConfigModified: onConfigModified,
|
ConfigModified: onConfigModified,
|
||||||
HTTPRegister: httpRegister,
|
HTTPRegister: httpRegister,
|
||||||
|
@ -75,7 +78,7 @@ func initDNS() (err error) {
|
||||||
ConfigModified: onConfigModified,
|
ConfigModified: onConfigModified,
|
||||||
HTTPRegister: httpRegister,
|
HTTPRegister: httpRegister,
|
||||||
FindClient: Context.clients.findMultiple,
|
FindClient: Context.clients.findMultiple,
|
||||||
BaseDir: baseDir,
|
BaseDir: querylogDir,
|
||||||
AnonymizeClientIP: config.DNS.AnonymizeClientIP,
|
AnonymizeClientIP: config.DNS.AnonymizeClientIP,
|
||||||
RotationIvl: config.QueryLog.Interval.Duration,
|
RotationIvl: config.QueryLog.Interval.Duration,
|
||||||
MemSize: config.QueryLog.MemSize,
|
MemSize: config.QueryLog.MemSize,
|
||||||
|
@ -545,3 +548,50 @@ func (r safeSearchResolver) LookupIP(
|
||||||
|
|
||||||
return ips, nil
|
return ips, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkStatsAndQuerylogDirs checks and returns directory paths to store
|
||||||
|
// statistics and query log.
|
||||||
|
func checkStatsAndQuerylogDirs(
|
||||||
|
ctx *homeContext,
|
||||||
|
conf *configuration,
|
||||||
|
) (statsDir, querylogDir string, err error) {
|
||||||
|
baseDir := ctx.getDataDir()
|
||||||
|
|
||||||
|
statsDir = conf.Stats.DirPath
|
||||||
|
if statsDir == "" {
|
||||||
|
statsDir = baseDir
|
||||||
|
} else {
|
||||||
|
err = checkDir(statsDir)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", fmt.Errorf("statistics: custom directory: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
querylogDir = conf.QueryLog.DirPath
|
||||||
|
if querylogDir == "" {
|
||||||
|
querylogDir = baseDir
|
||||||
|
} else {
|
||||||
|
err = checkDir(querylogDir)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", fmt.Errorf("querylog: custom directory: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return statsDir, querylogDir, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkDir checks if the path is a directory. It's used to check for
|
||||||
|
// misconfiguration at startup.
|
||||||
|
func checkDir(path string) (err error) {
|
||||||
|
var fi os.FileInfo
|
||||||
|
if fi, err = os.Stat(path); err != nil {
|
||||||
|
// Don't wrap the error, since it's informative enough as is.
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !fi.IsDir() {
|
||||||
|
return fmt.Errorf("%q is not a directory", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -704,9 +704,9 @@ const (
|
||||||
keyTypeRSA = "RSA"
|
keyTypeRSA = "RSA"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
|
// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
|
||||||
// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
|
// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
|
||||||
// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
|
// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Find out if this version of parsePrivateKey from the stdlib
|
// TODO(a.garipov): Find out if this version of parsePrivateKey from the stdlib
|
||||||
// is actually necessary.
|
// is actually necessary.
|
||||||
|
|
|
@ -49,8 +49,8 @@ func (l *queryLog) client(clientID, ip string, cache clientCache) (c *Client, er
|
||||||
// the total amount of records in the buffer at the moment of searching.
|
// the total amount of records in the buffer at the moment of searching.
|
||||||
// l.confMu is expected to be locked.
|
// l.confMu is expected to be locked.
|
||||||
func (l *queryLog) searchMemory(params *searchParams, cache clientCache) (entries []*logEntry, total int) {
|
func (l *queryLog) searchMemory(params *searchParams, cache clientCache) (entries []*logEntry, total int) {
|
||||||
// We use this configuration check because a buffer can contain a single log
|
// Check memory size, as the buffer can contain a single log record. See
|
||||||
// record. See [newQueryLog].
|
// [newQueryLog].
|
||||||
if l.conf.MemSize == 0 {
|
if l.conf.MemSize == 0 {
|
||||||
return nil, 0
|
return nil, 0
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ func (l *queryLog) setQLogReader(olderThan time.Time) (qr *qLogReader, err error
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// readEntries reads entries from the reader to totalLimit. By default, we do
|
// readEntries reads entries from the reader to totalLimit. By default, we do
|
||||||
// not scan more than maxFileScanEntries at once. The idea is to make search
|
// not scan more than maxFileScanEntries at once. The idea is to make search
|
||||||
// calls faster so that the UI could handle it and show something quicker.
|
// calls faster so that the UI could handle it and show something quicker.
|
||||||
// This behavior can be overridden if maxFileScanEntries is set to 0.
|
// This behavior can be overridden if maxFileScanEntries is set to 0.
|
||||||
|
|
|
@ -314,7 +314,7 @@ func (u *Updater) clean() {
|
||||||
_ = os.RemoveAll(u.updateDir)
|
_ = os.RemoveAll(u.updateDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MaxPackageFileSize is a maximum package file length in bytes. The largest
|
// MaxPackageFileSize is a maximum package file length in bytes. The largest
|
||||||
// package whose size is limited by this constant currently has the size of
|
// package whose size is limited by this constant currently has the size of
|
||||||
// approximately 9 MiB.
|
// approximately 9 MiB.
|
||||||
const MaxPackageFileSize = 32 * 1024 * 1024
|
const MaxPackageFileSize = 32 * 1024 * 1024
|
||||||
|
|
Loading…
Reference in New Issue