@@ -26,8 +26,6 @@ import (
2626 "github.com/daeuniverse/outbound/protocol/direct"
2727 "gopkg.in/natefinch/lumberjack.v2"
2828
29- _ "net/http/pprof"
30-
3129 "github.com/daeuniverse/dae/cmd/internal"
3230 "github.com/daeuniverse/dae/common"
3331 "github.com/daeuniverse/dae/common/consts"
@@ -37,6 +35,7 @@ import (
3735 "github.com/daeuniverse/dae/control"
3836 "github.com/daeuniverse/dae/pkg/config_parser"
3937 "github.com/daeuniverse/dae/pkg/logger"
38+ "github.com/daeuniverse/dae/pkg/metrics"
4039 "github.com/mohae/deepcopy"
4140 "github.com/okzk/sdnotify"
4241 "github.com/sirupsen/logrus"
@@ -134,12 +133,25 @@ func Run(log *logrus.Logger, conf *config.Config, externGeoDataDirs []string) (e
134133 return err
135134 }
136135
137- var pprofServer * http.Server
138- if conf .Global .PprofPort != 0 {
139- pprofAddr := fmt .Sprintf ("localhost:%d" , conf .Global .PprofPort )
140- pprofServer = & http.Server {Addr : pprofAddr , Handler : nil }
141- go pprofServer .ListenAndServe ()
136+ metricsState := metrics .NewState ()
137+ metricsState .SetControlPlane (c )
138+ metricsRegistry := metrics .NewRegistry (metricsState )
139+
140+ var endpointServer * http.Server
141+ startEndpointServer := func (cfg metrics.EndpointConfig ) {
142+ if cfg .ListenAddress == "" {
143+ endpointServer = nil
144+ return
145+ }
146+ endpointServer = metrics .NewEndpointServer (cfg , metricsRegistry )
147+ go func (server * http.Server , endpointCfg metrics.EndpointConfig ) {
148+ if e := metrics .StartEndpointServer (server , endpointCfg ); e != nil && ! errors .Is (e , http .ErrServerClosed ) {
149+ log .WithError (e ).Errorln ("Endpoint server stopped with error" )
150+ }
151+ }(endpointServer , cfg )
142152 }
153+ endpointCfg := endpointConfigFromGlobal (conf , log )
154+ startEndpointServer (endpointCfg )
143155
144156 // Serve tproxy TCP/UDP server util signals.
145157 var listener * control.Listener
@@ -259,6 +271,10 @@ loop:
259271 // Only keep dns cache when ip version preference not change.
260272 dnsCache = c .CloneDnsCache ()
261273 }
274+ // Stop old DNS listener before creating new one to avoid port conflicts
275+ if err := c .StopDNSListener (); err != nil {
276+ log .Warnf ("[Reload] Failed to stop old DNS listener: %v" , err )
277+ }
262278 log .Warnln ("[Reload] Load new control plane" )
263279 newC , err := newControlPlane (log , obj , dnsCache , newConf , externGeoDataDirs )
264280 if err != nil {
@@ -290,21 +306,21 @@ loop:
290306 c = newC
291307 conf = newConf
292308 reloading = true
309+ metricsState .SetControlPlane (newC )
293310
294311 // Ready to close.
295312 if abortConnections {
296313 oldC .AbortConnections ()
297314 }
298315 oldC .Close ()
299316
300- if pprofServer != nil {
301- pprofServer .Shutdown (context .Background ())
302- pprofServer = nil
303- }
304- if newConf .Global .PprofPort != 0 {
305- pprofAddr := fmt .Sprintf ("localhost:%d" , conf .Global .PprofPort )
306- pprofServer = & http.Server {Addr : pprofAddr , Handler : nil }
307- go pprofServer .ListenAndServe ()
317+ newEndpointCfg := endpointConfigFromGlobal (newConf , log )
318+ if endpointConfigChanged (endpointCfg , newEndpointCfg ) {
319+ if endpointServer != nil {
320+ _ = endpointServer .Shutdown (context .Background ())
321+ }
322+ endpointCfg = newEndpointCfg
323+ startEndpointServer (endpointCfg )
308324 }
309325 case syscall .SIGHUP :
310326 // Ignore.
@@ -316,12 +332,37 @@ loop:
316332 }
317333 defer os .Remove (PidFilePath )
318334 defer control .GetDaeNetns ().Close ()
335+ if endpointServer != nil {
336+ _ = endpointServer .Shutdown (context .Background ())
337+ }
319338 if e := c .Close (); e != nil {
320339 return fmt .Errorf ("close control plane: %w" , e )
321340 }
322341 return nil
323342}
324343
344+ func endpointConfigFromGlobal (conf * config.Config , log * logrus.Logger ) metrics.EndpointConfig {
345+ cfg := metrics.EndpointConfig {
346+ ListenAddress : conf .Global .EndpointListenAddress ,
347+ Username : conf .Global .EndpointUsername ,
348+ Password : conf .Global .EndpointPassword ,
349+ TlsCertificate : conf .Global .EndpointTlsCertificate ,
350+ TlsKey : conf .Global .EndpointTlsKey ,
351+ PrometheusEnabled : conf .Global .EndpointPrometheusEnabled ,
352+ PrometheusPath : conf .Global .EndpointPrometheusPath ,
353+ PprofEnabled : conf .Global .PprofPort != 0 ,
354+ }
355+ if cfg .ListenAddress == "" && conf .Global .PprofPort != 0 {
356+ log .Warnln ("pprof_port is deprecated, please use endpoint_listen_address instead" )
357+ cfg .ListenAddress = fmt .Sprintf ("localhost:%d" , conf .Global .PprofPort )
358+ }
359+ return cfg
360+ }
361+
362+ func endpointConfigChanged (a , b metrics.EndpointConfig ) bool {
363+ return a != b
364+ }
365+
325366func newControlPlane (log * logrus.Logger , bpf interface {}, dnsCache map [string ]* control.DnsCache , conf * config.Config , externGeoDataDirs []string ) (c * control.ControlPlane , err error ) {
326367 // Deep copy to prevent modification.
327368 conf = deepcopy .Copy (conf ).(* config.Config )
0 commit comments