Pull request: 3890 fix anonymization

Merge in DNS/adguard-home from 3890-fix-stats to master

Updates #3890.

Squashed commit of the following:

commit a77a6204bc8a58f62a4fac70efdcae4267a64810
Merge: 834493a2 90e65b66
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 6 17:22:16 2021 +0300

    Merge branch 'master' into 3890-fix-stats

commit 834493a22ae79199efcc44e0715e2ac6f6272963
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 6 17:09:30 2021 +0300

    querylog: load once

commit b8000e7ba7a998fcd4553230ec5e5f9c90106e31
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 6 16:54:41 2021 +0300

    querylog: fix docs

commit 7db99ccfa19b58100950c11d67b23bca7af3e5cb
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 6 16:51:31 2021 +0300

    querylog: imp docs

commit 2a84650bd7ac5195730a7ab47b9562a83f721499
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 6 15:48:09 2021 +0300

    querylog: imp anonyization

commit 0f63feb1ff5f006fc528c3b681ef3b9d2199581e
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 6 14:44:37 2021 +0300

    all: imp code & docs

commit c4ccdcbb7248897edd178fd5cb77127e39ada73d
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 6 14:24:30 2021 +0300

    all: log changes

commit 60bb777a5aff36bba129a078fa11ae566298178a
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 6 14:08:41 2021 +0300

    all: use atomic value

commit c45886bd20eee2212b42686ff369830d8c08fe36
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Nov 30 18:50:02 2021 +0300

    all: anonymize separately
This commit is contained in:
Eugene Burkov
2021-12-06 17:26:43 +03:00
parent 90e65b662c
commit d2cf3233b8
16 changed files with 279 additions and 111 deletions

View File

@@ -16,10 +16,9 @@ type DiskConfig struct {
// Config - module configuration
type Config struct {
Filename string // database file name
LimitDays uint32 // time limit (in days)
UnitID unitIDCallback // user function to get the current unit ID. If nil, the current time hour is used.
AnonymizeClientIP bool // anonymize clients' IP addresses
Filename string // database file name
LimitDays uint32 // time limit (in days)
UnitID unitIDCallback // user function to get the current unit ID. If nil, the current time hour is used.
// Called when the configuration is changed by HTTP request
ConfigModified func()

View File

@@ -26,11 +26,13 @@ const (
// statsCtx - global context
type statsCtx struct {
// mu protects unit.
mu *sync.Mutex
// current is the actual statistics collection result.
current *unit
db *bolt.DB
conf *Config
unit *unit // the current unit
unitLock sync.Mutex // protect 'unit'
}
// data for 1 time unit
@@ -66,7 +68,9 @@ type unitDB struct {
}
func createObject(conf Config) (s *statsCtx, err error) {
s = &statsCtx{}
s = &statsCtx{
mu: &sync.Mutex{},
}
if !checkInterval(conf.LimitDays) {
conf.LimitDays = 1
}
@@ -112,7 +116,7 @@ func createObject(conf Config) (s *statsCtx, err error) {
if udb != nil {
deserialize(&u, udb)
}
s.unit = &u
s.current = &u
log.Debug("stats: initialized")
@@ -178,11 +182,13 @@ func (s *statsCtx) dbOpen() bool {
// Atomically swap the currently active unit with a new value
// Return old value
func (s *statsCtx) swapUnit(new *unit) *unit {
s.unitLock.Lock()
u := s.unit
s.unit = new
s.unitLock.Unlock()
func (s *statsCtx) swapUnit(new *unit) (u *unit) {
s.mu.Lock()
defer s.mu.Unlock()
u = s.current
s.current = new
return u
}
@@ -250,6 +256,13 @@ func unitNameToID(name []byte) (id uint32, ok bool) {
return uint32(binary.BigEndian.Uint64(name)), true
}
func (s *statsCtx) ongoing() (u *unit) {
s.mu.Lock()
defer s.mu.Unlock()
return s.current
}
// Flush the current unit to DB and delete an old unit when a new hour is started
// If a unit must be flushed:
// . lock DB
@@ -260,10 +273,7 @@ func unitNameToID(name []byte) (id uint32, ok bool) {
// . unlock DB
func (s *statsCtx) periodicFlush() {
for {
s.unitLock.Lock()
ptr := s.unit
s.unitLock.Unlock()
ptr := s.ongoing()
if ptr == nil {
break
}
@@ -491,22 +501,6 @@ func (s *statsCtx) clear() {
log.Debug("stats: cleared")
}
// Get Client IP address
func (s *statsCtx) getClientIP(ip net.IP) (clientIP net.IP) {
if s.conf.AnonymizeClientIP && ip != nil {
const AnonymizeClientIP4Mask = 16
const AnonymizeClientIP6Mask = 112
if ip.To4() != nil {
return ip.Mask(net.CIDRMask(AnonymizeClientIP4Mask, 32))
}
return ip.Mask(net.CIDRMask(AnonymizeClientIP6Mask, 128))
}
return ip
}
func (s *statsCtx) Update(e Entry) {
if s.conf.limit == 0 {
return
@@ -521,14 +515,13 @@ func (s *statsCtx) Update(e Entry) {
clientID := e.Client
if ip := net.ParseIP(clientID); ip != nil {
ip = s.getClientIP(ip)
clientID = ip.String()
}
s.unitLock.Lock()
defer s.unitLock.Unlock()
s.mu.Lock()
defer s.mu.Unlock()
u := s.unit
u := s.current
u.nResult[e.Result]++
@@ -549,10 +542,8 @@ func (s *statsCtx) loadUnits(limit uint32) ([]*unitDB, uint32) {
return nil, 0
}
s.unitLock.Lock()
curUnit := serialize(s.unit)
curID := s.unit.id
s.unitLock.Unlock()
cur := s.ongoing()
curID := cur.id
// Per-hour units.
units := []*unitDB{}
@@ -568,7 +559,7 @@ func (s *statsCtx) loadUnits(limit uint32) ([]*unitDB, uint32) {
_ = tx.Rollback()
units = append(units, curUnit)
units = append(units, serialize(cur))
if len(units) != int(limit) {
log.Fatalf("len(units) != limit: %d %d", len(units), limit)