@@ -3,13 +3,15 @@ package reports
33import (
44 "bufio"
55 "bytes"
6+ "encoding/binary"
67 "encoding/json"
78 "errors"
89 "fmt"
910 "io"
1011 "os"
1112 "path/filepath"
1213 "strings"
14+ "sync"
1315 "time"
1416
1517 "github.com/go-resty/resty/v2"
@@ -519,31 +521,28 @@ func sendDataToSplunk(opts *aggregateOptions, report TestReport) error {
519521 SetHeader ("Content-Type" , "application/json" ).
520522 SetLogger (ZerologRestyLogger {})
521523
522- log .Debug ().Str ("report id" , report .ID ).Int ("results" , len (report .Results )).Msg ("Sending aggregated data to Splunk" )
524+ log .Debug ().Str ("report id" , report .ID ).Int ("results" , len (results )).Msg ("Sending aggregated data to Splunk" )
525+
526+ const (
527+ resultsBatchSize = 10
528+ splunkSizeLimitBytes = 100_000_000 // 100MB. Actual limit is over 800MB, but that's excessive
529+ exampleSplunkReportFileName = "example_results/example_splunk_report.json"
530+ exampleSplunkResultsFileName = "example_results/example_splunk_results_batch_%d.json"
531+ )
523532
524533 var (
525534 splunkErrs = []error {}
526- resultsBatchSize = 10
527535 resultsBatch = []SplunkTestResult {}
528536 successfulResultsSent = 0
537+ batchNum = 1
529538 )
530539
531- var (
532- exampleSplunkResultsFileName = "example_results/example_splunk_results.json"
533- exampleSplunkResultsFile * os.File
534- exampleSplunkReportFileName = "example_results/example_splunk_report.json"
535- exampleSplunkReportFile * os.File
536- err error
537- )
538-
539- if isExampleRun {
540- exampleSplunkResultsFile , err = os .Create (exampleSplunkResultsFileName )
541- if err != nil {
542- return fmt .Errorf ("error creating example Splunk results file: %w" , err )
543- }
544- defer exampleSplunkResultsFile .Close ()
545- }
546540 for resultCount , result := range results {
541+ // No need to send log outputs to Splunk
542+ result .FailedOutputs = nil
543+ result .PassedOutputs = nil
544+ result .PackageOutputs = nil
545+
547546 resultsBatch = append (resultsBatch , SplunkTestResult {
548547 Event : SplunkTestResultEvent {
549548 Event : opts .splunkEvent ,
@@ -554,13 +553,21 @@ func sendDataToSplunk(opts *aggregateOptions, report TestReport) error {
554553 Index : SplunkIndex ,
555554 })
556555
557- if len (resultsBatch ) >= resultsBatchSize || resultCount == len (results )- 1 {
556+ if len (resultsBatch ) >= resultsBatchSize ||
557+ resultCount == len (results )- 1 ||
558+ binary .Size (resultsBatch ) >= splunkSizeLimitBytes {
559+
558560 batchData , testNames , err := batchSplunkResults (resultsBatch )
559561 if err != nil {
560562 return fmt .Errorf ("error batching results: %w" , err )
561563 }
562564
563565 if isExampleRun {
566+ exampleSplunkResultsFileName := fmt .Sprintf (exampleSplunkResultsFileName , batchNum )
567+ exampleSplunkResultsFile , err := os .Create (exampleSplunkResultsFileName )
568+ if err != nil {
569+ return fmt .Errorf ("error creating example Splunk results file: %w" , err )
570+ }
564571 for _ , result := range resultsBatch {
565572 jsonResult , err := json .Marshal (result )
566573 if err != nil {
@@ -571,6 +578,10 @@ func sendDataToSplunk(opts *aggregateOptions, report TestReport) error {
571578 return fmt .Errorf ("error writing result for '%s' to file: %w" , result .Event .Data .TestName , err )
572579 }
573580 }
581+ err = exampleSplunkResultsFile .Close ()
582+ if err != nil {
583+ return fmt .Errorf ("error closing example Splunk results file: %w" , err )
584+ }
574585 } else {
575586 resp , err := client .R ().SetBody (batchData .String ()).Post ("" )
576587 if err != nil {
@@ -588,11 +599,12 @@ func sendDataToSplunk(opts *aggregateOptions, report TestReport) error {
588599 }
589600 }
590601 resultsBatch = []SplunkTestResult {}
602+ batchNum ++
591603 }
592604 }
593605
594606 if isExampleRun {
595- log .Info ().Msgf ("Example Run. See '%s ' for the results that would be sent to splunk" , exampleSplunkResultsFileName )
607+ log .Info ().Msg ("Example Run. See 'example_results/splunk_results ' for the results that would be sent to splunk" )
596608 }
597609
598610 reportData := SplunkTestReport {
@@ -607,7 +619,7 @@ func sendDataToSplunk(opts *aggregateOptions, report TestReport) error {
607619 }
608620
609621 if isExampleRun {
610- exampleSplunkReportFile , err = os .Create (exampleSplunkReportFileName )
622+ exampleSplunkReportFile , err : = os .Create (exampleSplunkReportFileName )
611623 if err != nil {
612624 return fmt .Errorf ("error creating example Splunk report file: %w" , err )
613625 }
@@ -642,6 +654,7 @@ func sendDataToSplunk(opts *aggregateOptions, report TestReport) error {
642654 log .Debug ().
643655 Int ("successfully sent" , successfulResultsSent ).
644656 Int ("total results" , len (results )).
657+ Int ("result batches" , batchNum ).
645658 Str ("duration" , time .Since (start ).String ()).
646659 Str ("report id" , report .ID ).
647660 Msg ("All results sent successfully to Splunk" )
@@ -672,20 +685,34 @@ func batchSplunkResults(results []SplunkTestResult) (batchData bytes.Buffer, res
672685
673686// unBatchSplunkResults un-batches a batch of TestResult objects into a slice of TestResult objects
674687func unBatchSplunkResults (batch []byte ) ([]* SplunkTestResult , error ) {
675- var results []* SplunkTestResult
676- scanner := bufio .NewScanner (bufio .NewReader (bytes .NewReader (batch )))
688+ results := make ([]* SplunkTestResult , 0 , bytes .Count (batch , []byte {'\n' }))
689+ scanner := bufio .NewScanner (bytes .NewReader (batch ))
690+
691+ maxCapacity := 1024 * 1024 // 1 MB
692+ buf := make ([]byte , maxCapacity )
693+ scanner .Buffer (buf , maxCapacity )
694+
695+ var pool sync.Pool
696+ pool .New = func () interface {} { return new (SplunkTestResult ) }
697+
677698 for scanner .Scan () {
678- line := scanner .Text ()
679- if strings .TrimSpace (line ) == "" {
699+ line := scanner .Bytes ()
700+ if len ( bytes .TrimSpace (line )) == 0 {
680701 continue // Skip empty lines
681702 }
682- var result * SplunkTestResult
683- if err := json .Unmarshal ([]byte (line ), & result ); err != nil {
703+
704+ result := pool .Get ().(* SplunkTestResult )
705+ if err := json .Unmarshal (line , result ); err != nil {
684706 return results , fmt .Errorf ("error unmarshaling result: %w" , err )
685707 }
686708 results = append (results , result )
687709 }
688- return results , scanner .Err ()
710+
711+ if err := scanner .Err (); err != nil {
712+ return results , fmt .Errorf ("error scanning: %w" , err )
713+ }
714+
715+ return results , nil
689716}
690717
691718// aggregateReports aggregates multiple TestReport objects into a single TestReport
0 commit comments