Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(526)

Side by Side Diff: milo/appengine/job_source/raw_presentation/logDogBuild.go

Issue 2949783002: [milo] appengine/* -> * (Closed)
Patch Set: rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file.
4
5 package raw_presentation
6
7 import (
8 "fmt"
9 "time"
10
11 "golang.org/x/net/context"
12
13 "github.com/luci/luci-go/common/clock"
14 "github.com/luci/luci-go/common/proto/google"
15 miloProto "github.com/luci/luci-go/common/proto/milo"
16 "github.com/luci/luci-go/milo/api/resp"
17 "github.com/luci/luci-go/milo/appengine/common/model"
18 )
19
20 // URLBuilder constructs URLs for various link types.
21 type URLBuilder interface {
22 // LinkURL returns the URL associated with the supplied Link.
23 //
24 // If no URL could be built for that Link, nil will be returned.
25 BuildLink(l *miloProto.Link) *resp.Link
26 }
27
28 // HACK(hinoka): This should be a part of recipes, but just hardcoding a list
29 // of unimportant things for now.
30 var builtIn = map[string]struct{}{
31 "recipe bootstrap": {},
32 "setup_build": {},
33 "recipe result": {},
34 }
35
36 // miloBuildStep converts a logdog/milo step to a BuildComponent struct.
37 // buildCompletedTime must be zero if build did not complete yet.
38 func miloBuildStep(ub URLBuilder, anno *miloProto.Step, isMain bool, buildComple tedTime,
39 now time.Time) []*resp.BuildComponent {
40
41 comp := &resp.BuildComponent{Label: anno.Name}
42 switch anno.Status {
43 case miloProto.Status_RUNNING:
44 comp.Status = model.Running
45
46 case miloProto.Status_SUCCESS:
47 comp.Status = model.Success
48
49 case miloProto.Status_FAILURE:
50 if fd := anno.GetFailureDetails(); fd != nil {
51 switch fd.Type {
52 case miloProto.FailureDetails_EXCEPTION, miloProto.Failu reDetails_INFRA:
53 comp.Status = model.InfraFailure
54
55 case miloProto.FailureDetails_EXPIRED:
56 comp.Status = model.Expired
57
58 case miloProto.FailureDetails_DM_DEPENDENCY_FAILED:
59 comp.Status = model.DependencyFailure
60
61 default:
62 comp.Status = model.Failure
63 }
64
65 if fd.Text != "" {
66 comp.Text = append(comp.Text, fd.Text)
67 }
68 } else {
69 comp.Status = model.Failure
70 }
71
72 case miloProto.Status_PENDING:
73 comp.Status = model.NotRun
74
75 // Missing the case of waiting on unfinished dependency...
76 default:
77 comp.Status = model.NotRun
78 }
79
80 if !(buildCompletedTime.IsZero() || comp.Status.Terminal()) {
81 // The build has completed, but this step has not. Mark it as an
82 // infrastructure failure.
83 comp.Status = model.InfraFailure
84 }
85
86 // Hide the unimportant steps, highlight the interesting ones.
87 switch comp.Status {
88 case model.NotRun, model.Running:
89 if isMain {
90 comp.Verbosity = resp.Hidden
91 }
92
93 case model.Success:
94 if _, ok := builtIn[anno.Name]; ok || isMain {
95 comp.Verbosity = resp.Hidden
96 }
97 case model.InfraFailure, model.Failure:
98 comp.Verbosity = resp.Interesting
99 }
100
101 // Main link is a link to the stdout.
102 var stdoutLink *miloProto.Link
103 if anno.StdoutStream != nil {
104 stdoutLink = &miloProto.Link{
105 Label: "stdout",
106 Value: &miloProto.Link_LogdogStream{
107 LogdogStream: anno.StdoutStream,
108 },
109 }
110 }
111
112 if anno.Link != nil {
113 comp.MainLink = resp.LinkSet{ub.BuildLink(anno.Link)}
114
115 // If we also have a STDOUT stream, add it to our OtherLinks.
116 if stdoutLink != nil {
117 anno.OtherLinks = append([]*miloProto.Link{stdoutLink}, anno.OtherLinks...)
118 }
119 } else if stdoutLink != nil {
120 comp.MainLink = resp.LinkSet{ub.BuildLink(stdoutLink)}
121 }
122
123 // Add STDERR link, if available.
124 if anno.StderrStream != nil {
125 anno.OtherLinks = append(anno.OtherLinks, &miloProto.Link{
126 Label: "stderr",
127 Value: &miloProto.Link_LogdogStream{
128 LogdogStream: anno.StderrStream,
129 },
130 })
131 }
132
133 // Sub link is for one link per log that isn't stdout.
134 for _, link := range anno.GetOtherLinks() {
135 if l := ub.BuildLink(link); l != nil {
136 comp.SubLink = append(comp.SubLink, resp.LinkSet{l})
137 }
138 }
139
140 // This should always be a step.
141 comp.Type = resp.Step
142
143 // This should always be 0
144 comp.LevelsDeep = 0
145
146 // Timestamps
147 comp.Started = google.TimeFromProto(anno.Started)
148 comp.Finished = google.TimeFromProto(anno.Ended)
149
150 var till time.Time
151 switch {
152 case !comp.Finished.IsZero():
153 till = comp.Finished
154 case comp.Status == model.Running:
155 till = now
156 case !buildCompletedTime.IsZero():
157 till = buildCompletedTime
158 }
159 if !comp.Started.IsZero() && till.After(comp.Started) {
160 comp.Duration = till.Sub(comp.Started)
161 }
162
163 // This should be the exact same thing.
164 comp.Text = append(comp.Text, anno.Text...)
165
166 ss := anno.GetSubstep()
167 results := []*resp.BuildComponent{}
168 results = append(results, comp)
169 // Process nested steps.
170 for _, substep := range ss {
171 var subanno *miloProto.Step
172 switch s := substep.GetSubstep().(type) {
173 case *miloProto.Step_Substep_Step:
174 subanno = s.Step
175 case *miloProto.Step_Substep_AnnotationStream:
176 panic("Non-inline substeps not supported")
177 default:
178 panic(fmt.Errorf("Unknown type %v", s))
179 }
180 for _, subcomp := range miloBuildStep(ub, subanno, false, buildC ompletedTime, now) {
181 results = append(results, subcomp)
182 }
183 }
184
185 return results
186 }
187
188 // AddLogDogToBuild takes a set of logdog streams and populate a milo build.
189 // build.Summary.Finished must be set.
190 func AddLogDogToBuild(
191 c context.Context, ub URLBuilder, mainAnno *miloProto.Step, build *resp. MiloBuild) {
192 now := clock.Now(c)
193
194 // Now fill in each of the step components.
195 // TODO(hinoka): This is totes cachable.
196 buildCompletedTime := google.TimeFromProto(mainAnno.Ended)
197 build.Summary = *(miloBuildStep(ub, mainAnno, true, buildCompletedTime, now)[0])
198 for _, substepContainer := range mainAnno.Substep {
199 anno := substepContainer.GetStep()
200 if anno == nil {
201 // TODO: We ignore non-embedded substeps for now.
202 continue
203 }
204
205 bss := miloBuildStep(ub, anno, false, buildCompletedTime, now)
206 for _, bs := range bss {
207 if bs.Status != model.Success {
208 build.Summary.Text = append(
209 build.Summary.Text, fmt.Sprintf("%s %s", bs.Status, bs.Label))
210 }
211 build.Components = append(build.Components, bs)
212 propGroup := &resp.PropertyGroup{GroupName: bs.Label}
213 for _, prop := range anno.Property {
214 propGroup.Property = append(propGroup.Property, &resp.Property{
215 Key: prop.Name,
216 Value: prop.Value,
217 })
218 }
219 build.PropertyGroup = append(build.PropertyGroup, propGr oup)
220 }
221 }
222
223 // Take care of properties
224 propGroup := &resp.PropertyGroup{GroupName: "Main"}
225 for _, prop := range mainAnno.Property {
226 propGroup.Property = append(propGroup.Property, &resp.Property{
227 Key: prop.Name,
228 Value: prop.Value,
229 })
230 }
231 build.PropertyGroup = append(build.PropertyGroup, propGroup)
232
233 return
234 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698