Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions listener.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
diff --git a/collector/internal/telemetryapi/listener.go b/collector/internal/telemetryapi/listener.go
index 8499d4e..62a6461 100644
--- a/collector/internal/telemetryapi/listener.go
+++ b/collector/internal/telemetryapi/listener.go
@@ -17,18 +17,32 @@ package telemetryapi
import (
"context"
"encoding/json"
+ "errors"
"fmt"
"io"
+ "math/rand"
+ "net"
"net/http"
"os"
+ "syscall"
"time"

"github.com/golang-collections/go-datastructures/queue"
"go.uber.org/zap"
)

-const defaultListenerPort = "53612"
-const initialQueueSize = 5
+const (
+ initialQueueSize = 5
+ maxRetries = 5
+ // Define ephemeral port range (typical range is 49152-65535)
+ minPort = 49152
+ maxPort = 65535
+)
+
+// getRandomPort returns a random port number within the ephemeral range
+func getRandomPort() string {
+ return fmt.Sprintf("%d", rand.Intn(maxPort-minPort)+minPort)
+}

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

-func listenOnAddress() string {
+func (s *Listener) tryBindPort() (net.Listener, string, error) {
+ for i := 0; i < maxRetries; i++ {
+ port := getRandomPort()
+ address := listenOnAddress(port)
+
+ l, err := net.Listen("tcp", address)
+ if err != nil {
+ if errors.Is(err, syscall.EADDRINUSE) {
+ s.logger.Debug("Port in use, trying another",
+ zap.String("address", address))
+ continue
+ }
+ return nil, "", err
+ }
+ return l, address, nil
+ }
+
+ return nil, "", fmt.Errorf("failed to find available port after %d attempts", maxRetries)
+}
+
+func listenOnAddress(port string) string {
envAwsLocal, ok := os.LookupEnv("AWS_SAM_LOCAL")
var addr string
if ok && envAwsLocal == "true" {
- addr = ":" + defaultListenerPort
+ addr = ":" + port
} else {
- addr = "sandbox.localdomain:" + defaultListenerPort
+ addr = "sandbox.localdomain:" + port
}
-
return addr
}

// Start the server in a goroutine where the log events will be sent
func (s *Listener) Start() (string, error) {
- address := listenOnAddress()
+ listener, address, err := s.tryBindPort()
+ if err != nil {
+ return "", fmt.Errorf("failed to find available port: %w", err)
+ }
s.logger.Info("Listening for requests", zap.String("address", address))
s.httpServer = &http.Server{Addr: address}
http.HandleFunc("/", s.httpHandler)
go func() {
- err := s.httpServer.ListenAndServe()
+ err := s.httpServer.Serve(listener)
if err != http.ErrServerClosed {
s.logger.Error("Unexpected stop on HTTP Server", zap.Error(err))
s.Shutdown()
4 changes: 4 additions & 0 deletions patch-upstream.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ patch -p2 < ../../collector.patch
# patch manager.go to remove lambdacomponents attribute
patch -p2 < ../../manager.patch


# patch listener.go to patch port usage
patch -p2 < ../../listener.patch

# Replace OTel Collector with ADOT Collector
go mod edit -replace github.com/open-telemetry/opentelemetry-lambda/collector/lambdacomponents=${CURRENT_DIR}/adot/collector/lambdacomponents

Expand Down
Loading