@@ -103,7 +103,8 @@ type Supervisor struct {
103
103
// Supervisor's own config.
104
104
config config.Supervisor
105
105
106
- agentDescription * atomic.Value
106
+ agentDescription * atomic.Value
107
+ availableComponents * atomic.Value
107
108
108
109
// Supervisor's persistent state
109
110
persistentState * persistentState
@@ -174,6 +175,7 @@ func NewSupervisor(logger *zap.Logger, cfg config.Supervisor) (*Supervisor, erro
174
175
cfgState : & atomic.Value {},
175
176
effectiveConfig : & atomic.Value {},
176
177
agentDescription : & atomic.Value {},
178
+ availableComponents : & atomic.Value {},
177
179
doneChan : make (chan struct {}),
178
180
customMessageToServer : make (chan * protobufs.CustomMessage , maxBufferedCustomMessages ),
179
181
agentConn : & atomic.Value {},
@@ -300,16 +302,22 @@ func (s *Supervisor) getBootstrapInfo() (err error) {
300
302
301
303
done := make (chan error , 1 )
302
304
var connected atomic.Bool
305
+ var doneReported atomic.Bool
303
306
304
307
// Start a one-shot server to get the Collector's agent description
305
- // using the Collector's OpAMP extension.
308
+ // and available components using the Collector's OpAMP extension.
306
309
err = srv .Start (flattenedSettings {
307
310
endpoint : fmt .Sprintf ("localhost:%d" , s .opampServerPort ),
308
311
onConnecting : func (_ * http.Request ) (bool , int ) {
309
312
connected .Store (true )
310
313
return true , http .StatusOK
311
314
},
312
- onMessage : func (_ serverTypes.Connection , message * protobufs.AgentToServer ) {
315
+ onMessage : func (_ serverTypes.Connection , message * protobufs.AgentToServer ) * protobufs.ServerToAgent {
316
+ response := & protobufs.ServerToAgent {}
317
+ if message .GetAvailableComponents () != nil {
318
+ s .setAvailableComponents (message .AvailableComponents )
319
+ }
320
+
313
321
if message .AgentDescription != nil {
314
322
instanceIDSeen := false
315
323
s .setAgentDescription (message .AgentDescription )
@@ -324,19 +332,47 @@ func (s *Supervisor) getBootstrapInfo() (err error) {
324
332
"the Collector's instance ID (%s) does not match with the instance ID set by the Supervisor (%s)" ,
325
333
attr .Value .GetStringValue (),
326
334
s .persistentState .InstanceID .String ())
327
- return
335
+ return response
328
336
}
329
337
instanceIDSeen = true
330
338
}
331
339
}
332
340
333
341
if ! instanceIDSeen {
334
342
done <- errors .New ("the Collector did not specify an instance ID in its AgentDescription message" )
335
- return
343
+ return response
336
344
}
345
+ }
346
+
347
+ // agent description must be defined
348
+ _ , ok := s .agentDescription .Load ().(* protobufs.AgentDescription )
349
+ if ! ok {
350
+ return response
351
+ }
352
+
353
+ // if available components have not been reported, agent description is sufficient to continue
354
+ availableComponents , availableComponentsOk := s .availableComponents .Load ().(* protobufs.AvailableComponents )
355
+ if availableComponentsOk {
356
+ // must have a full list of components if available components have been reported
357
+ if availableComponents .GetComponents () != nil {
358
+ if ! doneReported .Load () {
359
+ done <- nil
360
+ doneReported .Store (true )
361
+ }
362
+ } else {
363
+ // if we don't have a full component list, ask for it
364
+ response .Flags = uint64 (protobufs .ServerToAgentFlags_ServerToAgentFlags_ReportAvailableComponents )
365
+ }
366
+ return response
367
+ }
337
368
369
+ // need to only report done once, not on each message - otherwise, we get a hung thread
370
+ if ! doneReported .Load () {
338
371
done <- nil
372
+ doneReported .Store (true )
339
373
}
374
+
375
+ return response
340
376
},
341
377
}.toServerSettings ())
342
378
if err != nil {
@@ -456,6 +492,12 @@ func (s *Supervisor) startOpAMPClient() error {
456
492
return err
457
493
}
458
494
495
+ if ac , ok := s .availableComponents .Load ().(* protobufs.AvailableComponents ); ok && ac != nil {
496
+ if err = s .opampClient .SetAvailableComponents (ac ); err != nil {
497
+ return err
498
+ }
499
+ }
500
+
459
501
s .logger .Debug ("Starting OpAMP client..." )
460
502
if err = s .opampClient .Start (context .Background (), settings ); err != nil {
461
503
return err
@@ -505,7 +547,7 @@ func (s *Supervisor) startOpAMPServer() error {
505
547
return nil
506
548
}
507
549
508
- func (s * Supervisor ) handleAgentOpAMPMessage (conn serverTypes.Connection , message * protobufs.AgentToServer ) {
550
+ func (s * Supervisor ) handleAgentOpAMPMessage (conn serverTypes.Connection , message * protobufs.AgentToServer ) * protobufs. ServerToAgent {
509
551
s .agentConn .Store (conn )
510
552
511
553
s .logger .Debug ("Received OpAMP message from the agent" )
@@ -551,6 +593,8 @@ func (s *Supervisor) handleAgentOpAMPMessage(conn serverTypes.Connection, messag
551
593
s .logger .Debug ("Received health status from agent" , zap .Bool ("healthy" , message .Health .Healthy ))
552
594
s .lastHealthFromClient = message .Health
553
595
}
596
+
597
+ return & protobufs.ServerToAgent {}
554
598
}
555
599
556
600
func (s * Supervisor ) forwardCustomMessagesToServerLoop () {
@@ -584,6 +628,11 @@ func (s *Supervisor) setAgentDescription(ad *protobufs.AgentDescription) {
584
628
s .agentDescription .Store (ad )
585
629
}
586
630
631
+ // setAvailableComponents sets the available components of the OpAMP agent
632
+ func (s * Supervisor ) setAvailableComponents (ac * protobufs.AvailableComponents ) {
633
+ s .availableComponents .Store (ac )
634
+ }
635
+
587
636
// applyKeyValueOverrides merges the overrides map into the array of key value pairs.
588
637
// If a key from overrides already exists in the array of key value pairs, it is overwritten by the value from the overrides map.
589
638
// An array of KeyValue pair is returned, with each key value pair having a distinct key.
@@ -766,10 +815,11 @@ func (s *Supervisor) composeOpAMPExtensionConfig() []byte {
766
815
767
816
var cfg bytes.Buffer
768
817
tplVars := map [string ]any {
769
- "InstanceUid" : s .persistentState .InstanceID .String (),
770
- "SupervisorPort" : s .opampServerPort ,
771
- "PID" : s .pidProvider .PID (),
772
- "PPIDPollInterval" : orphanPollInterval ,
818
+ "InstanceUid" : s .persistentState .InstanceID .String (),
819
+ "SupervisorPort" : s .opampServerPort ,
820
+ "PID" : s .pidProvider .PID (),
821
+ "PPIDPollInterval" : orphanPollInterval ,
822
+ "ReportsAvailableComponents" : s .config .Capabilities .ReportsAvailableComponents ,
773
823
}
774
824
err := s .opampextensionTemplate .Execute (
775
825
& cfg ,
@@ -1020,7 +1070,7 @@ func (s *Supervisor) startAgent() (agentStartStatus, error) {
1020
1070
err := s .commander .Start (context .Background ())
1021
1071
if err != nil {
1022
1072
s .logger .Error ("Cannot start the agent" , zap .Error (err ))
1023
- startErr := fmt .Errorf ("Cannot start the agent: %w" , err )
1073
+ startErr := fmt .Errorf ("cannot start the agent: %w" , err )
1024
1074
err = s .opampClient .SetHealth (& protobufs.ComponentHealth {Healthy : false , LastError : startErr .Error ()})
1025
1075
if err != nil {
1026
1076
s .logger .Error ("Failed to report OpAMP client health" , zap .Error (err ))
0 commit comments