@@ -20,6 +20,8 @@ import (
2020 "github.com/cockroachdb/cockroach/pkg/jobs/jobspb"
2121 "github.com/cockroachdb/cockroach/pkg/jobs/jobsprofiler/profilerconstants"
2222 "github.com/cockroachdb/cockroach/pkg/sql/isql"
23+ "github.com/cockroachdb/cockroach/pkg/util/protoutil"
24+ "github.com/cockroachdb/cockroach/pkg/util/tracing/tracingpb"
2325 "github.com/cockroachdb/errors"
2426 "github.com/klauspost/compress/gzip"
2527)
@@ -82,6 +84,19 @@ func WriteExecutionDetailFile(
8284 })
8385}
8486
87+ func stringifyProtobinFile (filename string , fileContents * bytes.Buffer ) ([]byte , error ) {
88+ if strings .HasPrefix (filename , "resumer-trace" ) {
89+ td := & jobspb.TraceData {}
90+ if err := protoutil .Unmarshal (fileContents .Bytes (), td ); err != nil {
91+ return nil , err
92+ }
93+ rec := tracingpb .Recording (td .CollectedSpans )
94+ return []byte (rec .String ()), nil
95+ } else {
96+ return nil , errors .AssertionFailedf ("unknown file %s" , filename )
97+ }
98+ }
99+
85100// ReadExecutionDetailFile will stitch together all the chunks corresponding to the
86101// filename and return the uncompressed data of the file.
87102func ReadExecutionDetailFile (
@@ -91,37 +106,52 @@ func ReadExecutionDetailFile(
91106 // to the job's execution details and return the zipped bundle instead.
92107
93108 buf := bytes .NewBuffer ([]byte {})
94- if err := db .Txn (ctx , func (ctx context.Context , txn isql.Txn ) error {
95- // Reset the buf inside the txn closure to guard against txn retries.
96- buf .Reset ()
97- jobInfo := InfoStorageForJob (txn , jobID )
109+ fetchFileContent := func (file string ) error {
110+ return db .Txn (ctx , func (ctx context.Context , txn isql.Txn ) error {
111+ // Reset the buf inside the txn closure to guard against txn retries.
112+ buf .Reset ()
113+ jobInfo := InfoStorageForJob (txn , jobID )
114+
115+ // Iterate over all the chunks of the requested file and return the unzipped
116+ // chunks of data.
117+ var lastInfoKey string
118+ if err := jobInfo .Iterate (ctx , profilerconstants .MakeProfilerExecutionDetailsChunkKeyPrefix (file ),
119+ func (infoKey string , value []byte ) error {
120+ lastInfoKey = infoKey
121+ r , err := gzip .NewReader (bytes .NewBuffer (value ))
122+ if err != nil {
123+ return err
124+ }
125+ decompressed , err := io .ReadAll (r )
126+ if err != nil {
127+ return err
128+ }
129+ buf .Write (decompressed )
130+ return nil
131+ }); err != nil {
132+ return errors .Wrapf (err , "failed to iterate over chunks for job %d" , jobID )
133+ }
98134
99- // Iterate over all the chunks of the requested file and return the unzipped
100- // chunks of data.
101- var lastInfoKey string
102- if err := jobInfo .Iterate (ctx , profilerconstants .MakeProfilerExecutionDetailsChunkKeyPrefix (filename ),
103- func (infoKey string , value []byte ) error {
104- lastInfoKey = infoKey
105- r , err := gzip .NewReader (bytes .NewBuffer (value ))
106- if err != nil {
107- return err
108- }
109- decompressed , err := io .ReadAll (r )
110- if err != nil {
111- return err
112- }
113- buf .Write (decompressed )
114- return nil
115- }); err != nil {
116- return errors .Wrapf (err , "failed to iterate over chunks for job %d" , jobID )
117- }
135+ if lastInfoKey != "" && ! strings .Contains (lastInfoKey , finalChunkSuffix ) {
136+ return errors .Newf ("failed to read all chunks for file %s, last info key read was %s" , file , lastInfoKey )
137+ }
118138
119- if lastInfoKey != "" && ! strings .Contains (lastInfoKey , finalChunkSuffix ) {
120- return errors .Newf ("failed to read all chunks for file %s, last info key read was %s" , filename , lastInfoKey )
139+ return nil
140+ })
141+ }
142+
143+ // If the file requested is the `binpb.txt` format of a `binpb` file, we must
144+ // fetch the `binpb` version of the file and stringify the contents before
145+ // returning the response.
146+ if strings .HasSuffix (filename , "binpb.txt" ) {
147+ trimmedFilename := strings .TrimSuffix (filename , ".txt" )
148+ if err := fetchFileContent (trimmedFilename ); err != nil {
149+ return nil , err
121150 }
151+ return stringifyProtobinFile (filename , buf )
152+ }
122153
123- return nil
124- }); err != nil {
154+ if err := fetchFileContent (filename ); err != nil {
125155 return nil , err
126156 }
127157 return buf .Bytes (), nil
@@ -143,7 +173,13 @@ func ListExecutionDetailFiles(
143173 func (infoKey string , value []byte ) error {
144174 // Look for the final chunk of each file to find the unique file name.
145175 if strings .HasSuffix (infoKey , finalChunkSuffix ) {
146- files = append (files , strings .TrimPrefix (strings .TrimSuffix (infoKey , finalChunkSuffix ), profilerconstants .ExecutionDetailsChunkKeyPrefix ))
176+ filename := strings .TrimPrefix (strings .TrimSuffix (infoKey , finalChunkSuffix ), profilerconstants .ExecutionDetailsChunkKeyPrefix )
177+ // If we see a `.binpb` file we also want to make the string version of
178+ // the file available for consumption.
179+ if strings .HasSuffix (filename , ".binpb" ) {
180+ files = append (files , filename + ".txt" )
181+ }
182+ files = append (files , filename )
147183 }
148184 return nil
149185 }); err != nil {
0 commit comments