Skip to content

Commit ea7e1bf

Browse files
authored
Use Random port for listener in collector ext (#1751)
1 parent 1f1778c commit ea7e1bf

File tree

1 file changed

+44
-8
lines changed

1 file changed

+44
-8
lines changed

collector/internal/telemetryapi/listener.go

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,32 @@ package telemetryapi
1717
import (
1818
"context"
1919
"encoding/json"
20+
"errors"
2021
"fmt"
2122
"io"
23+
"math/rand"
24+
"net"
2225
"net/http"
2326
"os"
27+
"syscall"
2428
"time"
2529

2630
"github.com/golang-collections/go-datastructures/queue"
2731
"go.uber.org/zap"
2832
)
2933

30-
const defaultListenerPort = "53612"
31-
const initialQueueSize = 5
34+
const (
35+
initialQueueSize = 5
36+
maxRetries = 5
37+
// Define ephemeral port range (typical range is 49152-65535)
38+
minPort = 49152
39+
maxPort = 65535
40+
)
41+
42+
// getRandomPort returns a random port number within the ephemeral range
43+
func getRandomPort() string {
44+
return fmt.Sprintf("%d", rand.Intn(maxPort-minPort)+minPort)
45+
}
3246

3347
// Listener is used to listen to the Telemetry API
3448
type Listener struct {
@@ -46,26 +60,48 @@ func NewListener(logger *zap.Logger) *Listener {
4660
}
4761
}
4862

49-
func listenOnAddress() string {
63+
func (s *Listener) tryBindPort() (net.Listener, string, error) {
64+
for i := 0; i < maxRetries; i++ {
65+
port := getRandomPort()
66+
address := listenOnAddress(port)
67+
68+
l, err := net.Listen("tcp", address)
69+
if err != nil {
70+
if errors.Is(err, syscall.EADDRINUSE) {
71+
s.logger.Debug("Port in use, trying another",
72+
zap.String("address", address))
73+
continue
74+
}
75+
return nil, "", err
76+
}
77+
return l, address, nil
78+
}
79+
80+
return nil, "", fmt.Errorf("failed to find available port after %d attempts", maxRetries)
81+
}
82+
83+
func listenOnAddress(port string) string {
5084
envAwsLocal, ok := os.LookupEnv("AWS_SAM_LOCAL")
5185
var addr string
5286
if ok && envAwsLocal == "true" {
53-
addr = ":" + defaultListenerPort
87+
addr = ":" + port
5488
} else {
55-
addr = "sandbox.localdomain:" + defaultListenerPort
89+
addr = "sandbox.localdomain:" + port
5690
}
57-
5891
return addr
5992
}
6093

6194
// Start the server in a goroutine where the log events will be sent
6295
func (s *Listener) Start() (string, error) {
63-
address := listenOnAddress()
96+
listener, address, err := s.tryBindPort()
97+
if err != nil {
98+
return "", fmt.Errorf("failed to find available port: %w", err)
99+
}
64100
s.logger.Info("Listening for requests", zap.String("address", address))
65101
s.httpServer = &http.Server{Addr: address}
66102
http.HandleFunc("/", s.httpHandler)
67103
go func() {
68-
err := s.httpServer.ListenAndServe()
104+
err := s.httpServer.Serve(listener)
69105
if err != http.ErrServerClosed {
70106
s.logger.Error("Unexpected stop on HTTP Server", zap.Error(err))
71107
s.Shutdown()

0 commit comments

Comments
 (0)