@@ -706,6 +706,7 @@ func TestBeatsReceiverLogs(t *testing.T) {
706706 },
707707 Stack : nil ,
708708 })
709+
709710 type configOptions struct {
710711 RuntimeExperimental string
711712 }
@@ -732,66 +733,85 @@ agent.monitoring.enabled: false
732733 require .NoError (t ,
733734 template .Must (template .New ("config" ).Parse (configTemplate )).Execute (& configBuffer ,
734735 configOptions {
735- RuntimeExperimental : "process" ,
736+ RuntimeExperimental : string ( component . ProcessRuntimeManager ) ,
736737 }))
737738 processConfig := configBuffer .Bytes ()
738739 require .NoError (t ,
739740 template .Must (template .New ("config" ).Parse (configTemplate )).Execute (& configBuffer ,
740741 configOptions {
741- RuntimeExperimental : "otel" ,
742+ RuntimeExperimental : string ( component . OtelRuntimeManager ) ,
742743 }))
743744 receiverConfig := configBuffer .Bytes ()
744745 // this is the context for the whole test, with a global timeout defined
745746 ctx , cancel := testcontext .WithDeadline (t , t .Context (), time .Now ().Add (5 * time .Minute ))
746747 defer cancel ()
747748
748- // use a subcontext for the agent
749- agentProcessCtx , agentProcessCancel := context .WithCancel (ctx )
750- fixture , cmd , output := prepareAgentCmd (t , agentProcessCtx , processConfig )
749+ // since we set the output to a nonexistent ES endpoint, we expect it to be degraded, but the input to be healthy
750+ assertBeatsReady := func (t * assert.CollectT , status * atesting.AgentStatusOutput , runtime component.RuntimeManager ) {
751+ var componentVersionInfoName string
752+ switch runtime {
753+ case component .OtelRuntimeManager :
754+ componentVersionInfoName = "beats-receiver"
755+ default :
756+ componentVersionInfoName = "beat-v2-client"
757+ }
751758
752- require .NoError (t , cmd .Start ())
759+ // we don't actually care about anything here other than the receiver itself
760+ assert .Equal (t , 1 , len (status .Components ))
761+
762+ // all the components should be degraded, their output units should be degraded, the input units should be healthy,
763+ // and should identify themselves appropriately via their version info
764+ for _ , comp := range status .Components {
765+ assert .Equal (t , componentVersionInfoName , comp .VersionInfo .Name )
766+ for _ , unit := range comp .Units {
767+ if unit .UnitType == int (cproto .UnitType_INPUT ) {
768+ assert .Equal (t , int (cproto .State_HEALTHY ), unit .State ,
769+ "expected state of unit %s to be %s, got %s" ,
770+ unit .UnitID , cproto .State_HEALTHY .String (), cproto .State (unit .State ).String ())
771+ }
772+ }
773+ }
774+ }
753775
754- require .EventuallyWithT (t , func (collect * assert.CollectT ) {
755- var statusErr error
756- status , statusErr := fixture .ExecStatus (agentProcessCtx )
757- assert .NoError (collect , statusErr )
758- assertBeatsHealthy (collect , & status , component .ProcessRuntimeManager , 1 )
759- return
760- }, 1 * time .Minute , 1 * time .Second )
776+ // set up a standalone agent
777+ fixture , err := define .NewFixtureFromLocalBuild (t , define .Version ())
778+ require .NoError (t , err )
761779
762- agentProcessCancel ( )
763- require .Error (t , cmd . Wait () )
764- processLogsString := output . String ( )
765- output . Reset ( )
780+ err = fixture . Prepare ( ctx )
781+ require .NoError (t , err )
782+ err = fixture . Configure ( ctx , processConfig )
783+ require . NoError ( t , err )
766784
767- // use a subcontext for the agent
768- agentReceiverCtx , agentReceiverCancel := context .WithCancel (ctx )
769- fixture , cmd , output = prepareAgentCmd (t , agentReceiverCtx , receiverConfig )
785+ output , err := fixture .Install (ctx , & atesting.InstallOpts {Privileged : true , Force : true })
786+ require .NoError (t , err , "failed to install agent: %s" , output )
770787
771- require .NoError (t , cmd .Start ())
788+ require .EventuallyWithT (t , func (collect * assert.CollectT ) {
789+ var statusErr error
790+ status , statusErr := fixture .ExecStatus (ctx )
791+ require .NoError (collect , statusErr )
792+ assertBeatsReady (collect , & status , component .ProcessRuntimeManager )
793+ return
794+ }, 2 * time .Minute , 5 * time .Second )
772795
773- t .Cleanup (func () {
774- if t .Failed () {
775- t .Log ("Elastic-Agent output:" )
776- t .Log (output .String ())
777- }
778- })
796+ // change configuration and wait until the beats receiver is healthy
797+ err = fixture .Configure (ctx , receiverConfig )
798+ require .NoError (t , err )
779799
780800 require .EventuallyWithT (t , func (collect * assert.CollectT ) {
781801 var statusErr error
782- status , statusErr := fixture .ExecStatus (agentReceiverCtx )
783- assert .NoError (collect , statusErr )
784- assertBeatsHealthy (collect , & status , component .OtelRuntimeManager , 1 )
802+ status , statusErr := fixture .ExecStatus (ctx )
803+ require .NoError (collect , statusErr )
804+ assertBeatsReady (collect , & status , component .OtelRuntimeManager )
785805 return
786- }, 1 * time .Minute , 1 * time .Second )
787- agentReceiverCancel ()
788- require . Error ( t , cmd . Wait () )
789- receiverLogsString := output . String ( )
806+ }, 2 * time .Minute , 5 * time .Second )
807+
808+ logsBytes , err := fixture . Exec ( ctx , [] string { "logs" , "-n" , "1000" , "--exclude-events" } )
809+ require . NoError ( t , err , "failed to read logs: %v" , err )
790810
791- processLog := getBeatStartLogRecord ( processLogsString )
792- assert . NotEmpty ( t , processLog )
793- receiverLog := getBeatStartLogRecord ( receiverLogsString )
794- assert . NotEmpty ( t , receiverLog )
811+ beatStartLogs := getBeatStartLogRecords ( string ( logsBytes ) )
812+
813+ require . Len ( t , beatStartLogs , 2 , "expected to find one log line for each configuration" )
814+ processLog , receiverLog := beatStartLogs [ 0 ], beatStartLogs [ 1 ]
795815
796816 // Check that the process log is a subset of the receiver log
797817 for key , value := range processLog {
@@ -835,9 +855,10 @@ func assertBeatsHealthy(t *assert.CollectT, status *atesting.AgentStatusOutput,
835855 }
836856}
837857
838- // getBeatStartLogRecord returns the log record for the a particular log line emitted when the beat starts
858+ // getBeatStartLogRecords returns the log records for a particular log line emitted when the beat starts
839859// This log line is identical between beats processes and receivers, so it's a good point of comparison
840- func getBeatStartLogRecord (logs string ) map [string ]any {
860+ func getBeatStartLogRecords (logs string ) []map [string ]any {
861+ var logRecords []map [string ]any
841862 for _ , line := range strings .Split (logs , "\n " ) {
842863 line = strings .TrimSpace (line )
843864 if line == "" {
@@ -848,13 +869,11 @@ func getBeatStartLogRecord(logs string) map[string]any {
848869 continue
849870 }
850871
851- if message , ok := logRecord ["message" ].(string ); ! ok || ! strings .HasPrefix (message , "Beat name:" ) {
852- continue
872+ if message , ok := logRecord ["message" ].(string ); ok && strings .HasPrefix (message , "Beat name:" ) {
873+ logRecords = append ( logRecords , logRecord )
853874 }
854-
855- return logRecord
856875 }
857- return nil
876+ return logRecords
858877}
859878
860879func prepareAgentCmd (t * testing.T , ctx context.Context , config []byte ) (* atesting.Fixture , * exec.Cmd , * strings.Builder ) {
0 commit comments