Skip to content

Commit 7f3d6cd

Browse files
committed
history: add loadTrace function and support for loading Nth trace
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
1 parent 1d8a5ae commit 7f3d6cd

File tree

1 file changed

+73
-44
lines changed

1 file changed

+73
-44
lines changed

commands/history/trace.go

Lines changed: 73 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"net"
1010
"os"
1111
"slices"
12+
"strconv"
13+
"strings"
1214
"time"
1315

1416
"github.com/containerd/console"
@@ -34,51 +36,55 @@ type traceOptions struct {
3436
addr string
3537
}
3638

37-
func runTrace(ctx context.Context, dockerCli command.Cli, opts traceOptions) error {
38-
b, err := builder.New(dockerCli, builder.WithName(opts.builder))
39-
if err != nil {
40-
return err
41-
}
42-
43-
nodes, err := b.LoadNodes(ctx)
44-
if err != nil {
45-
return err
46-
}
47-
for _, node := range nodes {
48-
if node.Err != nil {
49-
return node.Err
39+
func loadTrace(ctx context.Context, ref string, nodes []builder.Node) (string, []byte, error) {
40+
var offset *int
41+
if strings.HasPrefix(ref, "^") {
42+
off, err := strconv.Atoi(ref[1:])
43+
if err != nil {
44+
return "", nil, errors.Wrapf(err, "invalid offset %q", ref)
5045
}
46+
offset = &off
47+
ref = ""
5148
}
5249

53-
recs, err := queryRecords(ctx, opts.ref, nodes)
50+
recs, err := queryRecords(ctx, ref, nodes)
5451
if err != nil {
55-
return err
52+
return "", nil, err
5653
}
5754

5855
var rec *historyRecord
5956

60-
if opts.ref == "" {
57+
if ref == "" {
6158
slices.SortFunc(recs, func(a, b historyRecord) int {
6259
return b.CreatedAt.AsTime().Compare(a.CreatedAt.AsTime())
6360
})
6461
for _, r := range recs {
6562
if r.CompletedAt != nil {
63+
if offset != nil {
64+
if *offset > 0 {
65+
*offset--
66+
continue
67+
}
68+
}
6669
rec = &r
6770
break
6871
}
6972
}
73+
if offset != nil && *offset > 0 {
74+
return "", nil, errors.Errorf("no completed build found with offset %d", *offset)
75+
}
7076
} else {
7177
rec = &recs[0]
7278
}
7379
if rec == nil {
74-
if opts.ref == "" {
75-
return errors.New("no records found")
80+
if ref == "" {
81+
return "", nil, errors.New("no records found")
7682
}
77-
return errors.Errorf("no record found for ref %q", opts.ref)
83+
return "", nil, errors.Errorf("no record found for ref %q", ref)
7884
}
7985

8086
if rec.CompletedAt == nil {
81-
return errors.Errorf("build %q is not completed, only completed builds can be traced", rec.Ref)
87+
return "", nil, errors.Errorf("build %q is not completed, only completed builds can be traced", rec.Ref)
8288
}
8389

8490
if rec.Trace == nil {
@@ -87,34 +93,34 @@ func runTrace(ctx context.Context, dockerCli command.Cli, opts traceOptions) err
8793

8894
c, err := rec.node.Driver.Client(ctx)
8995
if err != nil {
90-
return err
96+
return "", nil, err
9197
}
9298
_, err = c.ControlClient().UpdateBuildHistory(ctx, &controlapi.UpdateBuildHistoryRequest{
9399
Ref: rec.Ref,
94100
Finalize: true,
95101
})
96102
if err != nil {
97-
return err
103+
return "", nil, err
98104
}
99105

100106
recs, err := queryRecords(ctx, rec.Ref, []builder.Node{*rec.node})
101107
if err != nil {
102-
return err
108+
return "", nil, err
103109
}
104110

105111
if len(recs) == 0 {
106-
return errors.Errorf("build record %q was deleted", rec.Ref)
112+
return "", nil, errors.Errorf("build record %q was deleted", rec.Ref)
107113
}
108114

109115
rec = &recs[0]
110116
if rec.Trace == nil {
111-
return errors.Errorf("build record %q is missing a trace", rec.Ref)
117+
return "", nil, errors.Errorf("build record %q is missing a trace", rec.Ref)
112118
}
113119
}
114120

115121
c, err := rec.node.Driver.Client(ctx)
116122
if err != nil {
117-
return err
123+
return "", nil, err
118124
}
119125

120126
store := proxy.NewContentStore(c.ContentClient())
@@ -125,12 +131,12 @@ func runTrace(ctx context.Context, dockerCli command.Cli, opts traceOptions) err
125131
Size: rec.Trace.Size,
126132
})
127133
if err != nil {
128-
return err
134+
return "", nil, err
129135
}
130136

131137
spans, err := otelutil.ParseSpanStubs(io.NewSectionReader(ra, 0, ra.Size()))
132138
if err != nil {
133-
return err
139+
return "", nil, err
134140
}
135141

136142
wrapper := struct {
@@ -139,31 +145,54 @@ func runTrace(ctx context.Context, dockerCli command.Cli, opts traceOptions) err
139145
Data: spans.JaegerData().Data,
140146
}
141147

142-
var term bool
143-
if _, err := console.ConsoleFromFile(os.Stdout); err == nil {
144-
term = true
145-
}
146-
147148
if len(wrapper.Data) == 0 {
148-
return errors.New("no trace data")
149-
}
150-
151-
if !term {
152-
enc := json.NewEncoder(dockerCli.Out())
153-
enc.SetIndent("", " ")
154-
return enc.Encode(wrapper)
149+
return "", nil, errors.New("no trace data")
155150
}
156151

157-
srv := jaegerui.NewServer(jaegerui.Config{})
158-
159152
buf := &bytes.Buffer{}
160153
enc := json.NewEncoder(buf)
161154
enc.SetIndent("", " ")
162155
if err := enc.Encode(wrapper); err != nil {
156+
return "", nil, err
157+
}
158+
159+
return string(wrapper.Data[0].TraceID), buf.Bytes(), nil
160+
}
161+
162+
func runTrace(ctx context.Context, dockerCli command.Cli, opts traceOptions) error {
163+
b, err := builder.New(dockerCli, builder.WithName(opts.builder))
164+
if err != nil {
165+
return err
166+
}
167+
168+
nodes, err := b.LoadNodes(ctx)
169+
if err != nil {
170+
return err
171+
}
172+
for _, node := range nodes {
173+
if node.Err != nil {
174+
return node.Err
175+
}
176+
}
177+
178+
traceid, data, err := loadTrace(ctx, opts.ref, nodes)
179+
if err != nil {
163180
return err
164181
}
165182

166-
if err := srv.AddTrace(string(wrapper.Data[0].TraceID), bytes.NewReader(buf.Bytes())); err != nil {
183+
var term bool
184+
if _, err := console.ConsoleFromFile(os.Stdout); err == nil {
185+
term = true
186+
}
187+
188+
if !term {
189+
fmt.Fprintln(dockerCli.Out(), string(data))
190+
return nil
191+
}
192+
193+
srv := jaegerui.NewServer(jaegerui.Config{})
194+
195+
if err := srv.AddTrace(traceid, bytes.NewReader(data)); err != nil {
167196
return err
168197
}
169198

@@ -172,7 +201,7 @@ func runTrace(ctx context.Context, dockerCli command.Cli, opts traceOptions) err
172201
return err
173202
}
174203

175-
url := "http://" + ln.Addr().String() + "/trace/" + string(wrapper.Data[0].TraceID)
204+
url := "http://" + ln.Addr().String() + "/trace/" + traceid
176205

177206
go func() {
178207
time.Sleep(100 * time.Millisecond)

0 commit comments

Comments
 (0)