63 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
		
		
			
		
	
	
			63 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
| 
								 | 
							
								// Copyright 2024 The Prometheus Authors
							 | 
						||
| 
								 | 
							
								// Licensed under the Apache License, Version 2.0 (the "License");
							 | 
						||
| 
								 | 
							
								// you may not use this file except in compliance with the License.
							 | 
						||
| 
								 | 
							
								// You may obtain a copy of the License at
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// http://www.apache.org/licenses/LICENSE-2.0
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Unless required by applicable law or agreed to in writing, software
							 | 
						||
| 
								 | 
							
								// distributed under the License is distributed on an "AS IS" BASIS,
							 | 
						||
| 
								 | 
							
								// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
							 | 
						||
| 
								 | 
							
								// See the License for the specific language governing permissions and
							 | 
						||
| 
								 | 
							
								// limitations under the License.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								package remote
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"context"
							 | 
						||
| 
								 | 
							
									"math/rand"
							 | 
						||
| 
								 | 
							
									"net"
							 | 
						||
| 
								 | 
							
									"net/http"
							 | 
						||
| 
								 | 
							
									"time"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									"github.com/prometheus/common/config"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								type hostResolver interface {
							 | 
						||
| 
								 | 
							
									LookupHost(context.Context, string) ([]string, error)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								type dialContextWithRoundRobinDNS struct {
							 | 
						||
| 
								 | 
							
									dialContext config.DialContextFunc
							 | 
						||
| 
								 | 
							
									resolver    hostResolver
							 | 
						||
| 
								 | 
							
									rand        *rand.Rand
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// newDialContextWithRoundRobinDNS creates a new dialContextWithRoundRobinDNS.
							 | 
						||
| 
								 | 
							
								// We discourage creating new instances of struct dialContextWithRoundRobinDNS by explicitly setting its members,
							 | 
						||
| 
								 | 
							
								// except for testing purposes, and recommend using newDialContextWithRoundRobinDNS.
							 | 
						||
| 
								 | 
							
								func newDialContextWithRoundRobinDNS() *dialContextWithRoundRobinDNS {
							 | 
						||
| 
								 | 
							
									return &dialContextWithRoundRobinDNS{
							 | 
						||
| 
								 | 
							
										dialContext: http.DefaultTransport.(*http.Transport).DialContext,
							 | 
						||
| 
								 | 
							
										resolver:    net.DefaultResolver,
							 | 
						||
| 
								 | 
							
										rand:        rand.New(rand.NewSource(time.Now().Unix())),
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (dc *dialContextWithRoundRobinDNS) dialContextFn() config.DialContextFunc {
							 | 
						||
| 
								 | 
							
									return func(ctx context.Context, network, addr string) (net.Conn, error) {
							 | 
						||
| 
								 | 
							
										host, port, err := net.SplitHostPort(addr)
							 | 
						||
| 
								 | 
							
										if err != nil {
							 | 
						||
| 
								 | 
							
											return dc.dialContext(ctx, network, addr)
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										addrs, err := dc.resolver.LookupHost(ctx, host)
							 | 
						||
| 
								 | 
							
										if err != nil || len(addrs) == 0 {
							 | 
						||
| 
								 | 
							
											return dc.dialContext(ctx, network, addr)
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										randomAddr := net.JoinHostPort(addrs[dc.rand.Intn(len(addrs))], port)
							 | 
						||
| 
								 | 
							
										return dc.dialContext(ctx, network, randomAddr)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |