diff --git a/balancer/balancer.go b/balancer/balancer.go index 3f96dc26..bc4faa90 100644 --- a/balancer/balancer.go +++ b/balancer/balancer.go @@ -1,6 +1,7 @@ package balancer import ( + "context" "math" "math/rand" "sort" @@ -18,7 +19,7 @@ var _ Balancer = (*rttBasedBalancer)(nil) // Balancer is interface for load balancers type Balancer interface { // Pick picks a qualified nodes - Pick(network string) string + Pick(ctx context.Context, network string) string // Networks returns the supported network types Networks() []string } @@ -27,6 +28,7 @@ type rttBasedBalancer struct { nodes []*Node rttFunc rttFunc options *option.BalancerOutboundOptions + logger log.ContextLogger *HealthCheck costs *WeightManager @@ -43,6 +45,7 @@ func newRTTBasedBalancer( return &rttBasedBalancer{ rttFunc: rttFunc, options: &options, + logger: logger, HealthCheck: NewHealthCheck(router, options.Outbounds, logger, &options.Check), costs: NewWeightManager( logger, options.Pick.Costs, 1, @@ -94,7 +97,7 @@ func (s *rttBasedBalancer) Networks() []string { } // Select selects qualified nodes -func (s *rttBasedBalancer) Pick(network string) string { +func (s *rttBasedBalancer) Pick(ctx context.Context, network string) string { nodes := s.HealthCheck.Nodes(network) var candidates []*Node if len(nodes.Qualified) > 0 { @@ -113,8 +116,10 @@ func (s *rttBasedBalancer) Pick(network string) string { return "" } picked := selects[rand.Intn(count)] - s.logger.Debug( - "pick [", picked.Tag, "]", + s.logger.DebugContext( + ctx, + "(network=", network, ", candidates=", count, ")", + " => [", picked.Tag, "]", " +W=", picked.Weighted, " STD=", picked.Deviation, " AVG=", picked.Average, diff --git a/outbound/balancer.go b/outbound/balancer.go index 387e0b5f..0b753201 100644 --- a/outbound/balancer.go +++ b/outbound/balancer.go @@ -87,7 +87,7 @@ func (s *Balancer) Network() []string { // Now implements adapter.OutboundGroup func (s *Balancer) Now() string { - return s.pick("").Tag() + return s.pick(context.Background(), "").Tag() } // All implements adapter.OutboundGroup @@ -97,22 +97,22 @@ func (s *Balancer) All() []string { // DialContext implements adapter.Outbound func (s *Balancer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { - return s.pick(network).DialContext(ctx, network, destination) + return s.pick(ctx, network).DialContext(ctx, network, destination) } // ListenPacket implements adapter.Outbound func (s *Balancer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { - return s.pick(N.NetworkUDP).ListenPacket(ctx, destination) + return s.pick(ctx, N.NetworkUDP).ListenPacket(ctx, destination) } // NewConnection implements adapter.Outbound func (s *Balancer) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return s.pick(N.NetworkTCP).NewConnection(ctx, conn, metadata) + return s.pick(ctx, N.NetworkTCP).NewConnection(ctx, conn, metadata) } // NewPacketConnection implements adapter.Outbound func (s *Balancer) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return s.pick(N.NetworkUDP).NewPacketConnection(ctx, conn, metadata) + return s.pick(ctx, N.NetworkUDP).NewPacketConnection(ctx, conn, metadata) } // Close implements io.Closer @@ -149,24 +149,26 @@ func (s *Balancer) setBalancer(b balancer.Balancer) error { return nil } -func (s *Balancer) pick(network string) adapter.Outbound { - tag := s.pickTag(network) +func (s *Balancer) pick(ctx context.Context, network string) adapter.Outbound { + tag := s.pickTag(ctx, network) if tag == "" { + s.logger.DebugContext(ctx, "(network=", network, ", candidates=0) => fallback [", s.fallbackTag, "]") return s.fallback } outbound, ok := s.router.Outbound(tag) if !ok { + s.logger.DebugContext(ctx, "[", tag, "] not exist, fallback to [", s.fallbackTag, "]") return s.fallback } return outbound } -func (s *Balancer) pickTag(network string) string { +func (s *Balancer) pickTag(ctx context.Context, network string) string { if s.Balancer == nil { // not started yet, pick a random one return s.randomTag() } - tag := s.Balancer.Pick(network) + tag := s.Balancer.Pick(ctx, network) if tag == "" { return "" }