Compare commits

...

3 Commits

Author SHA1 Message Date
bakito
fcf25538c0 make log available in api 2021-04-03 18:41:28 +02:00
bakito
aa95031136 sync stats and query log config 2021-04-03 17:52:08 +02:00
bakito
6fb2dd12a8 move log attribute to message 2021-03-31 02:34:26 +02:00
5 changed files with 162 additions and 22 deletions

View File

@@ -76,6 +76,11 @@ type Client interface {
AddClients(client ...types.Client) error
UpdateClients(client ...types.Client) error
DeleteClients(client ...types.Client) error
QueryLogConfig() (*types.QueryLogConfig, error)
SetQueryLogConfig(enabled bool, interval int, anonymizeClientIP bool) error
StatsConfig() (*types.IntervalConfig, error)
SetStatsConfig(interval int) error
}
type client struct {
@@ -147,13 +152,13 @@ func (cl *client) ToggleSafeSearch(enable bool) error {
}
func (cl *client) toggleStatus(mode string) (bool, error) {
fs := &types.FeatureStatus{}
fs := &types.EnableConfig{}
_, err := cl.client.R().EnableTrace().SetResult(fs).Get(fmt.Sprintf("/%s/status", mode))
return fs.Enabled, err
}
func (cl *client) toggleBool(mode string, enable bool) error {
cl.log.With("mode", mode, "enable", enable).Info("Toggle")
cl.log.With("enable", enable).Info(fmt.Sprintf("Toggle %s", mode))
var target string
if enable {
target = "enable"
@@ -214,7 +219,10 @@ func (cl *client) SetCustomRules(rules types.UserRules) error {
func (cl *client) ToggleFiltering(enabled bool, interval int) error {
cl.log.With("enabled", enabled, "interval", interval).Info("Toggle filtering")
_, err := cl.client.R().EnableTrace().SetBody(&types.FilteringConfig{FeatureStatus: types.FeatureStatus{Enabled: enabled}, Interval: interval}).Post("/filtering/config")
_, err := cl.client.R().EnableTrace().SetBody(&types.FilteringConfig{
EnableConfig: types.EnableConfig{Enabled: enabled},
IntervalConfig: types.IntervalConfig{Interval: interval},
}).Post("/filtering/config")
return err
}
@@ -268,3 +276,31 @@ func (cl *client) DeleteClients(clients ...types.Client) error {
}
return nil
}
func (cl *client) QueryLogConfig() (*types.QueryLogConfig, error) {
qlc := &types.QueryLogConfig{}
_, err := cl.client.R().EnableTrace().SetResult(qlc).Get("/querylog_info")
return qlc, err
}
func (cl *client) SetQueryLogConfig(enabled bool, interval int, anonymizeClientIP bool) error {
cl.log.With("enabled", enabled, "interval", interval, "anonymizeClientIP", anonymizeClientIP).Info("Set query log config")
_, err := cl.client.R().EnableTrace().SetBody(&types.QueryLogConfig{
EnableConfig: types.EnableConfig{Enabled: enabled},
IntervalConfig: types.IntervalConfig{Interval: interval},
AnonymizeClientIP: anonymizeClientIP,
}).Post("/querylog_config")
return err
}
func (cl *client) StatsConfig() (*types.IntervalConfig, error) {
stats := &types.IntervalConfig{}
_, err := cl.client.R().EnableTrace().SetResult(stats).Get("/stats_info")
return stats, err
}
func (cl *client) SetStatsConfig(interval int) error {
cl.log.With("interval", interval).Info("Set stats config")
_, err := cl.client.R().EnableTrace().SetBody(&types.IntervalConfig{Interval: interval}).Post("/stats_config")
return err
}

View File

@@ -2,9 +2,15 @@ package log
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var rootLogger *zap.Logger
const logHistorySize = 50
var (
rootLogger *zap.Logger
logs []string
)
// GetLogger returns a named logger
func GetLogger(name string) *zap.SugaredLogger {
@@ -22,7 +28,50 @@ func init() {
OutputPaths: []string{"stdout"},
ErrorOutputPaths: []string{"stderr"},
}
opt := zap.WrapCore(func(c zapcore.Core) zapcore.Core {
return zapcore.NewTee(c, &logList{enc: zapcore.NewConsoleEncoder(cfg.EncoderConfig)})
})
rootLogger, _ = cfg.Build()
rootLogger.Sugar()
rootLogger, _ = cfg.Build(opt)
}
type logList struct {
enc zapcore.Encoder
}
func (l *logList) Enabled(_ zapcore.Level) bool {
return true
}
func (l *logList) With(_ []zapcore.Field) zapcore.Core {
return l
}
func (l *logList) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
return ce.AddCore(ent, l)
}
func (l *logList) Write(ent zapcore.Entry, fields []zapcore.Field) error {
buf, err := l.enc.EncodeEntry(ent, fields)
if err != nil {
return err
}
logs = append(logs, buf.String())
if len(logs) > logHistorySize {
logs = logs[len(logs)-logHistorySize:]
}
return nil
}
func (l *logList) Sync() error {
return nil
}
func Logs() []string {
var list []string
for _, l := range logs {
list = append(list, l)
}
return list
}

View File

@@ -3,10 +3,12 @@ package sync
import (
"context"
"fmt"
"github.com/bakito/adguardhome-sync/pkg/log"
"net"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
"time"
)
@@ -25,6 +27,10 @@ func (w *worker) handleRoot(rw http.ResponseWriter, _ *http.Request) {
_, _ = rw.Write([]byte("adguardhome-sync"))
}
func (w *worker) handleLogs(rw http.ResponseWriter, _ *http.Request) {
_, _ = rw.Write([]byte(strings.Join(log.Logs(), "")))
}
func (w *worker) basicAuth(h http.HandlerFunc) http.HandlerFunc {
return func(rw http.ResponseWriter, r *http.Request) {
@@ -64,13 +70,15 @@ func (w *worker) listenAndServe() {
BaseContext: func(_ net.Listener) context.Context { return ctx },
}
var mw []func(http.HandlerFunc) http.HandlerFunc
if w.cfg.API.Username != "" && w.cfg.API.Password != "" {
mux.HandleFunc("/api/v1/sync", use(w.handleSync, w.basicAuth))
mux.HandleFunc("/", use(w.handleRoot, w.basicAuth))
} else {
mux.HandleFunc("/api/v1/sync", w.handleSync)
mux.HandleFunc("/", w.handleRoot)
mw = append(mw, w.basicAuth)
}
mux.HandleFunc("/api/v1/sync", use(w.handleSync, mw...))
mux.HandleFunc("/api/v1/logs", use(w.handleLogs, mw...))
mux.HandleFunc("/", use(w.handleRoot, mw...))
go func() {
if err := httpServer.ListenAndServe(); err != http.ErrServerClosed {
l.With("error", err).Fatalf("HTTP server ListenAndServe")

View File

@@ -109,6 +109,16 @@ func (w *worker) sync() {
sl.With("error", err).Error("Error getting origin clients")
return
}
o.queryLogConfig, err = oc.QueryLogConfig()
if err != nil {
sl.With("error", err).Error("Error getting query log config")
return
}
o.statsConfig, err = oc.StatsConfig()
if err != nil {
sl.With("error", err).Error("Error getting stats config")
return
}
replicas := w.cfg.UniqueReplicas()
for _, replica := range replicas {
@@ -295,16 +305,39 @@ func (w *worker) syncGeneralSettings(o *origin, rs *types.Status, replica client
return err
}
}
qlc, err := replica.QueryLogConfig()
if err != nil {
return err
}
if !o.queryLogConfig.Equals(qlc) {
if err = replica.SetQueryLogConfig(o.queryLogConfig.Enabled, o.queryLogConfig.Interval, o.queryLogConfig.AnonymizeClientIP); err != nil {
return err
}
}
sc, err := replica.StatsConfig()
if err != nil {
return err
}
if o.statsConfig.Interval != sc.Interval {
if err = replica.SetStatsConfig(o.statsConfig.Interval); err != nil {
return err
}
}
return nil
}
type origin struct {
status *types.Status
rewrites *types.RewriteEntries
services *types.Services
filters *types.FilteringStatus
clients *types.Clients
parental bool
safeSearch bool
safeBrowsing bool
status *types.Status
rewrites *types.RewriteEntries
services *types.Services
filters *types.FilteringStatus
clients *types.Clients
queryLogConfig *types.QueryLogConfig
statsConfig *types.IntervalConfig
parental bool
safeSearch bool
safeBrowsing bool
}

View File

@@ -125,15 +125,29 @@ func (ur UserRules) String() string {
return strings.Join(ur, "\n")
}
type FeatureStatus struct {
type EnableConfig struct {
Enabled bool `json:"enabled"`
}
type FilteringConfig struct {
FeatureStatus
type IntervalConfig struct {
Interval int `json:"interval"`
}
type FilteringConfig struct {
EnableConfig
IntervalConfig
}
type QueryLogConfig struct {
EnableConfig
IntervalConfig
AnonymizeClientIP bool `json:"anonymize_client_ip"`
}
func (qlc *QueryLogConfig) Equals(o *QueryLogConfig) bool {
return qlc.Enabled == o.Enabled && qlc.AnonymizeClientIP == o.AnonymizeClientIP && qlc.Interval == o.Interval
}
type RefreshFilter struct {
Whitelist bool `json:"whitelist"`
}