Files
zeekayandHanzo Dev 8ee8950230 Go 1.27.1, and the code it can say more simply
The module declares go 1.27.1 and the adapter image follows. go fix
applied the modernizers and left ptrString and ptrBool with no callers,
so they are gone; omitzero is not applied, since it changes what the
JSON says.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 19:52:31 -07:00

151 lines
3.7 KiB
Go

package main
import (
"fmt"
"net/http"
"os"
"os/signal"
"strings"
"sync/atomic"
"syscall"
"time"
"github.com/hanzoai/insights-go"
)
const etagPollInterval = 5 * time.Second
// loggingTransport wraps an http.RoundTripper to log ETag-related headers
type loggingTransport struct {
wrapped http.RoundTripper
requestCount atomic.Int64
}
func (t *loggingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
// Only log for local_evaluation endpoint
if !strings.Contains(req.URL.Path, "local_evaluation") {
return t.wrapped.RoundTrip(req)
}
reqNum := t.requestCount.Add(1)
timestamp := time.Now().Format(time.RFC3339)
ifNoneMatch := req.Header.Get("If-None-Match")
if ifNoneMatch == "" {
ifNoneMatch = "(none)"
}
fmt.Printf("[%s] Request #%d\n", timestamp, reqNum)
fmt.Printf(" If-None-Match: %s\n", ifNoneMatch)
resp, err := t.wrapped.RoundTrip(req)
if err != nil {
fmt.Printf(" Error: %v\n\n", err)
return resp, err
}
etag := resp.Header.Get("ETag")
if etag == "" {
etag = "(none)"
}
statusText := ""
if resp.StatusCode == http.StatusNotModified {
statusText = " (Not Modified)"
}
fmt.Printf(" Status: %d%s\n", resp.StatusCode, statusText)
fmt.Printf(" ETag: %s\n", etag)
if resp.StatusCode == http.StatusNotModified {
fmt.Println(" -> Using cached flags (no data transfer)")
} else if resp.StatusCode == http.StatusOK {
fmt.Println(" -> Received fresh flags")
}
fmt.Println()
return resp, err
}
// TestETagPolling demonstrates ETag support for local evaluation polling.
// It polls every 5 seconds and logs the ETag behavior to show when
// 304 Not Modified responses occur (indicating no data transfer).
func TestETagPolling(projectAPIKey, personalAPIKey, endpointURL string) {
fmt.Println(strings.Repeat("=", 60))
fmt.Println("ETag Polling Test")
fmt.Println(strings.Repeat("=", 60))
fmt.Printf("Host: %s\n", endpointURL)
fmt.Printf("Poll interval: %v\n", etagPollInterval)
fmt.Println(strings.Repeat("=", 60))
fmt.Println()
// Create a logging transport that wraps the default transport
transport := &loggingTransport{
wrapped: http.DefaultTransport,
}
client, err := insights.NewWithConfig(projectAPIKey, insights.Config{
PersonalApiKey: personalAPIKey,
Endpoint: endpointURL,
DefaultFeatureFlagsPollingInterval: etagPollInterval,
Transport: transport,
Verbose: false,
})
if err != nil {
fmt.Printf("Error creating client: %v\n", err)
return
}
fmt.Println("Waiting for initial flag load...")
fmt.Println()
// Wait a moment for initial load
time.Sleep(2 * time.Second)
// Set up graceful shutdown
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
fmt.Println("Press Ctrl+C to stop")
fmt.Println()
// Periodically log flag state
ticker := time.NewTicker(etagPollInterval + time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
logETagFlagState(client)
case <-sigChan:
fmt.Println("\nShutting down...")
client.Close()
return
}
}
}
func logETagFlagState(client insights.Client) {
fmt.Println(strings.Repeat("-", 40))
// Disable $feature_flag_called events to avoid /batch/ requests
sendEvents := false
// Test a flag to verify the client is working
result, err := client.IsFeatureEnabled(insights.FeatureFlagPayload{
Key: "test-flag",
DistinctId: "test-user",
OnlyEvaluateLocally: true,
SendFeatureFlagEvents: &sendEvents,
})
if err != nil {
fmt.Printf("Flag evaluation error: %v\n", err)
} else {
fmt.Printf("Sample flag 'test-flag': %v\n", result)
}
fmt.Println(strings.Repeat("-", 40))
fmt.Println()
}