Skip to content

Commit 8328607

Browse files
authored
fix(konnect/tracing): Add values about Konnect sync round for tracing and logging in Konnect config syncer (#7838)
* add values about Konnect sync round for tracing and logging * update changelog
1 parent 340fa9e commit 8328607

3 files changed

Lines changed: 80 additions & 17 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,9 @@ Adding a new version? You'll need three changes:
123123
- Separate Konnect config sync concurrency from gateway Admin API concurrency via
124124
`--konnect-config-sync-concurrency` to reduce Konnect 429 rate-limit errors.
125125
[#7834](https://github.com/Kong/kubernetes-ingress-controller/pull/7834)
126-
- Do not cleanup `null`s in the configuration of plugins with Kong running in
127-
DBLess mode in the translator of ingress-controller. This enables user to use
128-
explicit `null`s in plugins.
129-
[#7751](https://github.com/Kong/kubernetes-ingress-controller/pull/7751)
130-
- Translate `healtchchecks.thershold` in `KongUpstreamPolicy` to the
131-
`healthchecks.thershold` field in Kong upstreams.
132-
(Thanks to [@elbrogan-vizio](https://github.com/elbrogan-vizio) who contributed to the fix.)
133-
[#7784](https://github.com/Kong/kubernetes-ingress-controller/pull/7784)
134-
- Reject CA Secrets with multiple PEM certs.
135-
[#7763](https://github.com/Kong/kubernetes-ingress-controller/pull/7763)
126+
- Add headers to mark the synchronization loop run in requests sent to Konnect in
127+
configuration synchronization for better tracing.
128+
[#7838](https://github.com/Kong/kubernetes-ingress-controller/pull/7838)
136129

137130
## [3.5.3]
138131

internal/konnect/config_synchronizer.go

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import (
55
"errors"
66
"fmt"
77
"sync"
8+
"sync/atomic"
9+
"time"
810

911
"github.com/go-logr/logr"
12+
"github.com/google/uuid"
1013
"github.com/kong/go-database-reconciler/pkg/file"
1114
"github.com/kong/go-kong/kong"
1215
"github.com/samber/mo"
@@ -18,6 +21,7 @@ import (
1821
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/deckgen"
1922
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/kongstate"
2023
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/sendconfig"
24+
"github.com/kong/kubernetes-ingress-controller/v3/internal/konnect/tracing"
2125
"github.com/kong/kubernetes-ingress-controller/v3/internal/logging"
2226
"github.com/kong/kubernetes-ingress-controller/v3/internal/metrics"
2327
"github.com/kong/kubernetes-ingress-controller/v3/internal/util"
@@ -45,6 +49,11 @@ type ConfigSynchronizer struct {
4549

4650
targetKongState mo.Option[TargetKongState]
4751
configLock sync.RWMutex
52+
53+
// synchronizerID is the identifier to mark the ConfigSynchronizer instance.
54+
synchronizerID string
55+
// serialNumber is the serial number to mark the loop round of config synchronization.
56+
serialNumber atomic.Uint32
4857
}
4958

5059
// TargetKongState wraps the Kong state to be uploaded to Konnect and indicates whether the configuration is a fallback
@@ -74,18 +83,23 @@ type ConfigSynchronizerParams struct {
7483
ConfigChangeDetector sendconfig.ConfigurationChangeDetector
7584
ConfigStatusNotifier clients.ConfigStatusNotifier
7685
MetricsRecorder metrics.Recorder
86+
SynchronizerID string
7787
}
7888

7989
func NewConfigSynchronizer(p ConfigSynchronizerParams) *ConfigSynchronizer {
90+
if p.SynchronizerID == "" {
91+
p.SynchronizerID = uuid.NewString()
92+
}
8093
return &ConfigSynchronizer{
81-
logger: p.Logger,
94+
logger: p.Logger.WithValues("synchronizerID", p.SynchronizerID),
8295
kongConfig: p.KongConfig,
8396
syncTicker: p.ConfigUploadTicker,
8497
konnectClientFactory: p.KonnectClientFactory,
8598
updateStrategyResolver: p.UpdateStrategyResolver,
8699
configChangeDetector: p.ConfigChangeDetector,
87100
configStatusNotifier: p.ConfigStatusNotifier,
88101
metricsRecorder: p.MetricsRecorder,
102+
synchronizerID: p.SynchronizerID,
89103
}
90104
}
91105

@@ -94,6 +108,7 @@ var _ manager.LeaderElectionRunnable = &ConfigSynchronizer{}
94108
// Start starts the loop to receive configuration and upload configuration to Konnect.
95109
func (s *ConfigSynchronizer) Start(ctx context.Context) error {
96110
s.logger.Info("Starting Konnect configuration synchronizer")
111+
ctx = context.WithValue(ctx, tracing.SynchronizerIDKey, s.synchronizerID)
97112

98113
konnectAdminClient, err := s.konnectClientFactory.NewKonnectClient(ctx)
99114
if err != nil {
@@ -199,26 +214,36 @@ func (s *ConfigSynchronizer) run(ctx context.Context) {
199214
}
200215

201216
func (s *ConfigSynchronizer) handleConfigSynchronizationTick(ctx context.Context) {
202-
s.logger.V(logging.DebugLevel).Info("Start uploading configuration to Konnect")
217+
// Add values about the sync round in the context.
218+
serialNumber := s.serialNumber.Add(1)
219+
startTimestamp := time.Now().Unix()
220+
syncRoundID := uuid.NewSHA1(uuid.Nil, fmt.Appendf([]byte{}, "%s:%d:%d", s.synchronizerID, serialNumber, startTimestamp))
221+
ctx = context.WithValue(ctx, tracing.SyncSerialNumberKey, serialNumber)
222+
ctx = context.WithValue(ctx, tracing.SyncStartTimestampKey, startTimestamp)
223+
ctx = context.WithValue(ctx, tracing.SyncRoundIDKey, syncRoundID)
224+
logger := s.logger.WithValues("syncRoundID", syncRoundID, "serialNumber", serialNumber)
225+
226+
logger.V(logging.DebugLevel).Info("Start uploading configuration to Konnect")
203227

204228
// Get the latest configuration copy to upload to Konnect. We don't want to hold the lock for a long time to prevent
205229
// blocking the update of the configuration.
206230
targetCfg, ok := s.currentContent(ctx)
207231
if !ok {
208-
s.logger.Info("No configuration received yet, skipping Konnect configuration synchronization")
232+
logger.Info("No configuration received yet, skipping Konnect configuration synchronization")
209233
return
210234
}
211235

212236
// Upload the configuration to Konnect.
213-
if err := s.uploadConfig(ctx, s.konnectAdminClient, targetCfg); err != nil {
214-
s.logger.Error(err, "Failed to upload configuration to Konnect")
215-
logKonnectErrors(s.logger, err)
237+
if err := s.uploadConfig(ctx, logger, s.konnectAdminClient, targetCfg); err != nil {
238+
logger.Error(err, "Failed to upload configuration to Konnect")
239+
logKonnectErrors(logger, err)
216240
}
217241
}
218242

219243
// uploadConfig sends the given configuration to Konnect.
220244
func (s *ConfigSynchronizer) uploadConfig(
221245
ctx context.Context,
246+
logger logr.Logger,
222247
client *adminapi.KonnectClient,
223248
targetContent TargetContent,
224249
) error {
@@ -229,7 +254,7 @@ func (s *ConfigSynchronizer) uploadConfig(
229254

230255
newSHA, err := sendconfig.PerformUpdate(
231256
ctx,
232-
s.logger,
257+
logger,
233258
client,
234259
s.kongConfig,
235260
targetContent.Content,

internal/konnect/tracing/datadog.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package tracing
33
import (
44
"context"
55
"net/http"
6+
"strconv"
67
"strings"
78

89
"github.com/go-logr/logr"
@@ -11,7 +12,30 @@ import (
1112
"github.com/kong/kubernetes-ingress-controller/v3/internal/logging"
1213
)
1314

15+
// ContextKey is the key to carry values to trace Konnect configuration sync in the context.
16+
type ContextKey string
17+
18+
const (
19+
// SynchronizerIDKey is the context key for the ID of KIC's Konnect configuration synchronizer instance.
20+
SynchronizerIDKey ContextKey = "KonnectSynchronizerID"
21+
// SyncSerialNumberKey is the context key for serial number to mark a round of configuration sync to Konnect.
22+
SyncSerialNumberKey ContextKey = "KonnectSyncSerialNumber"
23+
// SyncRoundIDKey is the context key to mark the ID of a round of configuration sync.
24+
SyncRoundIDKey ContextKey = "KonnectSyncRoundID"
25+
// SyncStartTimestampKey is the context key for timestamp (in seconds) of starting a round of configuration sync.
26+
SyncStartTimestampKey ContextKey = "KonnectSyncStartTimestamp"
27+
)
28+
1429
const (
30+
// InstanceIDHeader is the header to mark the ID of KIC's Konnect configuration synchronizer instance.
31+
InstanceIDHeader = "X-Kic-Konnect-Sync-Instance-Id"
32+
// SyncSerialNumberHeader is the header for serial number to mark a round of configuration sync to Konnect.
33+
SyncSerialNumberHeader = "X-Kic-Konnect-Sync-Serial-Number"
34+
// SyncStartTimestampHeader is the header for timestamp (in seconds) of starting a round of configuration sync.
35+
SyncStartTimestampHeader = "X-Kic-Konnect-Sync-Start-Timestamp"
36+
// SyncRoundIDHeader is the header to mark the ID of a round of configuration sync.
37+
SyncRoundIDHeader = "X-Kic-Konnect-Sync-Round-Id"
38+
1539
// B3TraceIDHeader is the header used by the B3 propagation format to pass the trace ID.
1640
B3TraceIDHeader = "X-B3-TraceId"
1741
// B3SpanIDHeader is the header used by the B3 propagation format to pass the span ID.
@@ -25,6 +49,8 @@ const (
2549

2650
// DoRequest is a helper function that sends an HTTP request and logs the result with DataDog trace ID.
2751
func DoRequest(ctx context.Context, httpClient *http.Client, req *http.Request) (*http.Response, error) {
52+
req = addHeaderFromContext(ctx, req)
53+
2854
httpResp, err := httpClient.Do(req)
2955
if err != nil {
3056
return nil, err
@@ -52,6 +78,25 @@ func DoRequest(ctx context.Context, httpClient *http.Client, req *http.Request)
5278
return httpResp, nil
5379
}
5480

81+
// addHeaderFromContext extracts the values to mark a configuration sync round in context
82+
// and set the headers in the request for tracing.
83+
func addHeaderFromContext(ctx context.Context, req *http.Request) *http.Request {
84+
if instanceID, ok := ctx.Value(SynchronizerIDKey).(string); ok {
85+
req.Header.Add(InstanceIDHeader, instanceID)
86+
}
87+
if syncRoundID, ok := ctx.Value(SyncRoundIDKey).(string); ok {
88+
req.Header.Add(SyncRoundIDHeader, syncRoundID)
89+
}
90+
if serialNumber, ok := ctx.Value(SyncSerialNumberKey).(uint32); ok {
91+
req.Header.Add(SyncSerialNumberHeader, strconv.FormatUint(uint64(serialNumber), 10))
92+
}
93+
if startTimestamp, ok := ctx.Value(SyncStartTimestampKey).(int64); ok {
94+
req.Header.Add(SyncStartTimestampHeader, strconv.FormatInt(startTimestamp, 10))
95+
}
96+
97+
return req
98+
}
99+
55100
// loggerWithDataDogTraceID creates a new logger with the DataDog tracing information extracted from the HTTP response's
56101
// headers. This data is useful for correlating logs with traces and logs in DataDog.
57102
func loggerWithDataDogTraceID(logger logr.Logger, resp *http.Response) logr.Logger {

0 commit comments

Comments
 (0)