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

Side by Side Diff: appengine/cmd/milo/logdog/logDogBuild.go

Issue 2191693003: Milo: Add LogDog annotation stream support. (Closed) Base URL: https://github.com/luci/luci-go@master
Patch Set: Fix successful build state, derive more Swarming parameters from milo proto common code. Created 4 years, 4 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
1 // Copyright 2016 The LUCI Authors. All rights reserved. 1 // Copyright 2016 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package logdog 5 package logdog
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "strings"
10 "time" 9 "time"
11 10
12 "golang.org/x/net/context" 11 "golang.org/x/net/context"
13 12
14 "github.com/luci/luci-go/appengine/cmd/milo/resp" 13 "github.com/luci/luci-go/appengine/cmd/milo/resp"
15 "github.com/luci/luci-go/common/clock" 14 "github.com/luci/luci-go/common/clock"
16 "github.com/luci/luci-go/common/logging"
17 miloProto "github.com/luci/luci-go/common/proto/milo" 15 miloProto "github.com/luci/luci-go/common/proto/milo"
18 ) 16 )
19 17
18 // URLBuilder constructs URLs for various link types.
19 type URLBuilder interface {
20 // LinkURL returns the URL associated with the supplied Link.
21 //
22 // If no URL could be built for that Link, nil will be returned.
23 BuildLink(l *miloProto.Link) *resp.Link
24 }
25
20 // miloBuildStep converts a logdog/milo step to a BuildComponent struct. 26 // miloBuildStep converts a logdog/milo step to a BuildComponent struct.
21 // buildCompletedTime must be zero if build did not complete yet. 27 // buildCompletedTime must be zero if build did not complete yet.
22 func miloBuildStep(c context.Context, linkBase string, anno *miloProto.Step, bui ldCompletedTime time.Time) *resp.BuildComponent { 28 func miloBuildStep(c context.Context, ub URLBuilder, anno *miloProto.Step, now t ime.Time) *resp.BuildComponent {
23 » linkBase = strings.TrimSuffix(linkBase, "/")
24 comp := &resp.BuildComponent{Label: anno.Name} 29 comp := &resp.BuildComponent{Label: anno.Name}
25 switch anno.Status { 30 switch anno.Status {
26 case miloProto.Status_RUNNING: 31 case miloProto.Status_RUNNING:
27 comp.Status = resp.Running 32 comp.Status = resp.Running
28 33
29 case miloProto.Status_SUCCESS: 34 case miloProto.Status_SUCCESS:
30 comp.Status = resp.Success 35 comp.Status = resp.Success
31 36
32 case miloProto.Status_FAILURE: 37 case miloProto.Status_FAILURE:
33 » » if anno.GetFailureDetails() != nil { 38 » » if fd := anno.GetFailureDetails(); fd != nil {
34 » » » switch anno.GetFailureDetails().Type { 39 » » » switch fd.Type {
35 case miloProto.FailureDetails_EXCEPTION, miloProto.Failu reDetails_INFRA: 40 case miloProto.FailureDetails_EXCEPTION, miloProto.Failu reDetails_INFRA:
36 comp.Status = resp.InfraFailure 41 comp.Status = resp.InfraFailure
37 42
38 case miloProto.FailureDetails_DM_DEPENDENCY_FAILED: 43 case miloProto.FailureDetails_DM_DEPENDENCY_FAILED:
39 comp.Status = resp.DependencyFailure 44 comp.Status = resp.DependencyFailure
40 45
41 default: 46 default:
42 comp.Status = resp.Failure 47 comp.Status = resp.Failure
43 } 48 }
49
50 if fd.Text != "" {
51 comp.Text = append(comp.Text, fd.Text)
52 }
44 } else { 53 } else {
45 comp.Status = resp.Failure 54 comp.Status = resp.Failure
46 } 55 }
47 56
57 case miloProto.Status_PENDING:
58 comp.Status = resp.NotRun
59
48 // Missing the case of waiting on unfinished dependency... 60 // Missing the case of waiting on unfinished dependency...
49 default: 61 default:
50 comp.Status = resp.NotRun 62 comp.Status = resp.NotRun
51 } 63 }
52 64
53 » if !buildCompletedTime.IsZero() && !comp.Status.Terminal() { 65 » if !anno.Ended.Time().IsZero() && !comp.Status.Terminal() {
54 // we cannot have unfinished steps in finished builds. 66 // we cannot have unfinished steps in finished builds.
55 comp.Status = resp.InfraFailure 67 comp.Status = resp.InfraFailure
56 } 68 }
57 69
58 // Sub link is for one link per log that isn't stdout.
59 for _, link := range anno.GetOtherLinks() {
60 lds := link.GetLogdogStream()
61 if lds == nil {
62 logging.Warningf(c, "Warning: %v of %v has an empty logd og stream.", link, anno)
63 continue // DNE???
64 }
65 newLink := &resp.Link{
66 Label: lds.Name,
67 URL: linkBase + "/" + lds.Name,
68 }
69 comp.SubLink = append(comp.SubLink, newLink)
70 }
71
72 // Main link is a link to the stdout. 70 // Main link is a link to the stdout.
71 var stdoutLink *miloProto.Link
73 if anno.StdoutStream != nil { 72 if anno.StdoutStream != nil {
74 » » comp.MainLink = &resp.Link{ 73 » » stdoutLink = &miloProto.Link{
75 Label: "stdout", 74 Label: "stdout",
76 » » » URL: linkBase + "/" + anno.StdoutStream.Name, 75 » » » Value: &miloProto.Link_LogdogStream{
76 » » » » LogdogStream: anno.StdoutStream,
77 » » » },
77 } 78 }
78 } 79 }
79 80
81 if anno.Link != nil {
82 comp.MainLink = ub.BuildLink(anno.Link)
83
84 // If we also have a STDOUT stream, add it to our OtherLinks.
85 if stdoutLink != nil {
86 anno.OtherLinks = append([]*miloProto.Link{stdoutLink}, anno.OtherLinks...)
87 }
88 } else if stdoutLink != nil {
89 comp.MainLink = ub.BuildLink(stdoutLink)
90 }
91
92 // Sub link is for one link per log that isn't stdout.
93 for _, link := range anno.GetOtherLinks() {
94 if l := ub.BuildLink(link); l != nil {
95 comp.SubLink = append(comp.SubLink, l)
96 }
97 }
98
80 // This should always be a step. 99 // This should always be a step.
81 comp.Type = resp.Step 100 comp.Type = resp.Step
82 101
83 // This should always be 0 102 // This should always be 0
84 comp.LevelsDeep = 0 103 comp.LevelsDeep = 0
85 104
86 // Timestamps 105 // Timestamps
87 comp.Started = anno.Started.Time() 106 comp.Started = anno.Started.Time()
88 comp.Finished = anno.Ended.Time() 107 comp.Finished = anno.Ended.Time()
89 108
109 latestTime := comp.Finished
110 if latestTime.IsZero() {
111 latestTime = now
nodir 2016/07/29 18:42:06 it should not be now, but time of build completion
dnj 2016/07/29 19:57:35 Done.
112 }
113 if !comp.Started.IsZero() {
114 if d := latestTime.Sub(comp.Started); d >= 0 {
115 comp.Duration = d
116 }
117 }
118
nodir 2016/07/29 18:42:06 this block of added code solves the same problem a
dnj 2016/07/29 19:57:35 Acknowledged.
90 var till time.Time 119 var till time.Time
91 switch { 120 switch {
92 case comp.Status == resp.Running: 121 case comp.Status == resp.Running:
93 till = clock.Now(c) 122 till = clock.Now(c)
94 case !comp.Finished.IsZero(): 123 case !comp.Finished.IsZero():
95 till = comp.Finished 124 till = comp.Finished
96 default:
97 till = buildCompletedTime
98 } 125 }
99 if !comp.Started.IsZero() && !till.IsZero() { 126 if !comp.Started.IsZero() && !till.IsZero() {
100 comp.Duration = till.Sub(comp.Started) 127 comp.Duration = till.Sub(comp.Started)
101 } 128 }
102 129
103 // This should be the exact same thing. 130 // This should be the exact same thing.
104 » comp.Text = anno.Text 131 » comp.Text = append(comp.Text, anno.Text...)
105 132
106 return comp 133 return comp
107 } 134 }
108 135
109 // AddLogDogToBuild takes a set of logdog streams and populate a milo build. 136 // AddLogDogToBuild takes a set of logdog streams and populate a milo build.
110 // build.Summary.Finished must be set. 137 // build.Summary.Finished must be set.
111 func AddLogDogToBuild(c context.Context, linkBase string, s *Streams, build *res p.MiloBuild) { 138 func AddLogDogToBuild(c context.Context, ub URLBuilder, s *Streams, build *resp. MiloBuild) {
112 if s.MainStream == nil { 139 if s.MainStream == nil {
113 panic("missing main stream") 140 panic("missing main stream")
114 } 141 }
115 // Now Fetch the main annotation of the build. 142 // Now Fetch the main annotation of the build.
116 » mainAnno := s.MainStream.Data 143 » var (
144 » » mainAnno = s.MainStream.Data
145 » » now = clock.Now(c)
146 » )
117 147
118 // Now fill in each of the step components. 148 // Now fill in each of the step components.
119 // TODO(hinoka): This is totes cachable. 149 // TODO(hinoka): This is totes cachable.
150 build.Summary = *(miloBuildStep(c, ub, mainAnno, now))
120 for _, substepContainer := range mainAnno.Substep { 151 for _, substepContainer := range mainAnno.Substep {
121 anno := substepContainer.GetStep() 152 anno := substepContainer.GetStep()
122 if anno == nil { 153 if anno == nil {
123 // TODO: We ignore non-embedded substeps for now. 154 // TODO: We ignore non-embedded substeps for now.
124 continue 155 continue
125 } 156 }
126 157
127 » » bs := miloBuildStep(c, linkBase, anno, build.Summary.Finished) 158 » » bs := miloBuildStep(c, ub, anno, now)
128 » » if bs.Status != resp.Success && bs.Status != resp.NotRun { 159 » » if bs.Status != resp.Success {
129 build.Summary.Text = append( 160 build.Summary.Text = append(
130 build.Summary.Text, fmt.Sprintf("%s %s", bs.Stat us, bs.Label)) 161 build.Summary.Text, fmt.Sprintf("%s %s", bs.Stat us, bs.Label))
131 } 162 }
132 build.Components = append(build.Components, bs) 163 build.Components = append(build.Components, bs)
133 propGroup := &resp.PropertyGroup{GroupName: bs.Label} 164 propGroup := &resp.PropertyGroup{GroupName: bs.Label}
134 for _, prop := range anno.Property { 165 for _, prop := range anno.Property {
135 propGroup.Property = append(propGroup.Property, &resp.Pr operty{ 166 propGroup.Property = append(propGroup.Property, &resp.Pr operty{
136 Key: prop.Name, 167 Key: prop.Name,
137 Value: prop.Value, 168 Value: prop.Value,
138 }) 169 })
139 } 170 }
140 build.PropertyGroup = append(build.PropertyGroup, propGroup) 171 build.PropertyGroup = append(build.PropertyGroup, propGroup)
141 } 172 }
142 173
143 // Take care of properties 174 // Take care of properties
144 propGroup := &resp.PropertyGroup{GroupName: "Main"} 175 propGroup := &resp.PropertyGroup{GroupName: "Main"}
145 for _, prop := range mainAnno.Property { 176 for _, prop := range mainAnno.Property {
146 propGroup.Property = append(propGroup.Property, &resp.Property{ 177 propGroup.Property = append(propGroup.Property, &resp.Property{
147 Key: prop.Name, 178 Key: prop.Name,
148 Value: prop.Value, 179 Value: prop.Value,
149 }) 180 })
150 } 181 }
151 build.PropertyGroup = append(build.PropertyGroup, propGroup) 182 build.PropertyGroup = append(build.PropertyGroup, propGroup)
152 183
153 return 184 return
154 } 185 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698