diff --git a/dnscrypt-proxy/monitoring_ui.go b/dnscrypt-proxy/monitoring_ui.go index 8cfe80e742..e68f40814f 100644 --- a/dnscrypt-proxy/monitoring_ui.go +++ b/dnscrypt-proxy/monitoring_ui.go @@ -123,6 +123,7 @@ type MonitoringUI struct { clients map[*websocket.Conn]bool clientsMutex sync.Mutex proxy *Proxy + tasks chan *PluginsState // Mutex for all WebSocket write operations to prevent races writesMutex sync.Mutex @@ -202,6 +203,7 @@ func NewMonitoringUI(proxy *Proxy) *MonitoringUI { }, clients: make(map[*websocket.Conn]bool), proxy: proxy, + tasks: make(chan *PluginsState, proxy.maxClients), // Initialize broadcast rate limiting with 100ms minimum delay broadcastMinDelay: 100 * time.Millisecond, // Initialize Prometheus path @@ -256,6 +258,8 @@ func (ui *MonitoringUI) Start() error { } }() + go ui.WatchTasks() + return nil } @@ -267,8 +271,18 @@ func (ui *MonitoringUI) Stop() error { return nil } +// WatchTasks - Consumes the query result queue +func (ui *MonitoringUI) WatchTasks() { + for { + select { + case pluginsState := <-ui.tasks: + ui.UpdateMetrics(pluginsState) + } + } +} + // UpdateMetrics - Updates metrics with a new query -func (ui *MonitoringUI) UpdateMetrics(pluginsState PluginsState, msg *dns.Msg) { +func (ui *MonitoringUI) UpdateMetrics(pluginsState *PluginsState) { if !ui.config.Enabled { return } @@ -323,6 +337,7 @@ func (ui *MonitoringUI) UpdateMetrics(pluginsState PluginsState, msg *dns.Msg) { mc.invalidateCache() // Update query types - separate lock + msg := pluginsState.questionMsg if msg != nil && len(msg.Question) > 0 { question := msg.Question[0] qType, ok := dns.TypeToString[question.Qtype] @@ -1056,7 +1071,7 @@ func (ui *MonitoringUI) handleTestQuery(w http.ResponseWriter, r *http.Request) } // Update metrics - ui.UpdateMetrics(pluginsState, msg) + ui.tasks <- &pluginsState // Return success w.Header().Set("Content-Type", "text/plain") diff --git a/dnscrypt-proxy/query_processing.go b/dnscrypt-proxy/query_processing.go index 8ebf27673b..f01d432e60 100644 --- a/dnscrypt-proxy/query_processing.go +++ b/dnscrypt-proxy/query_processing.go @@ -349,7 +349,7 @@ func updateMonitoringMetrics( ) { if proxy.monitoringUI.Enabled && proxy.monitoringInstance != nil && pluginsState.questionMsg != nil { dlog.Debugf("Calling UpdateMetrics for query: %s", pluginsState.qName) - proxy.monitoringInstance.UpdateMetrics(*pluginsState, pluginsState.questionMsg) + proxy.monitoringInstance.tasks <- pluginsState } else { if pluginsState.questionMsg == nil { dlog.Debugf("Question message is nil")