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

Side by Side Diff: milo/appengine/buildbot/buildinfo.go

Issue 2695383002: milo: Enable Swarming LogDog log loading. (Closed)
Patch Set: Comments, fix links. Created 3 years, 10 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 2017 The LUCI Authors. All rights reserved. 1 // Copyright 2017 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 buildbot 5 package buildbot
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "strconv" 9 "strconv"
10 "strings" 10 "strings"
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 // Create a new LogDog client. 75 // Create a new LogDog client.
76 client, err := p.newLogdogClient(c) 76 client, err := p.newLogdogClient(c)
77 if err != nil { 77 if err != nil {
78 logging.WithError(err).Errorf(c, "Failed to create LogDog client .") 78 logging.WithError(err).Errorf(c, "Failed to create LogDog client .")
79 return nil, grpcutil.Internal 79 return nil, grpcutil.Internal
80 } 80 }
81 81
82 // Identify the LogDog annotation stream from the build. 82 // Identify the LogDog annotation stream from the build.
83 // 83 //
84 // This will return a gRPC error on failure. 84 // This will return a gRPC error on failure.
85 » as, err := getLogDogAnnotations(c, client, build, projectHint) 85 » addr, err := getLogDogAnnotationAddr(c, client, build, projectHint)
86 if err != nil { 86 if err != nil {
87 return nil, err 87 return nil, err
88 } 88 }
89 » logging.Infof(c, "Resolved annotation stream: %s / %s", as.Project, as.P ath) 89 » logging.Infof(c, "Resolved annotation stream: %s / %s", addr.Project, ad dr.Path)
90 90
91 // Load the annotation protobuf. 91 // Load the annotation protobuf.
92 » as.Client = client 92 » as := logdog.AnnotationStream{
93 » » Client: client,
94 » » Path: addr.Path,
95 » » Project: addr.Project,
96 » }
93 if err := as.Normalize(); err != nil { 97 if err := as.Normalize(); err != nil {
94 logging.WithError(err).Errorf(c, "Failed to normalize annotation stream.") 98 logging.WithError(err).Errorf(c, "Failed to normalize annotation stream.")
95 return nil, grpcutil.Internal 99 return nil, grpcutil.Internal
96 } 100 }
97 101
98 » step, err := as.Load(c) 102 » step, err := as.Fetch(c)
99 if err != nil { 103 if err != nil {
100 logging.WithError(err).Errorf(c, "Failed to load annotation stre am.") 104 logging.WithError(err).Errorf(c, "Failed to load annotation stre am.")
101 return nil, grpcutil.Errf(codes.Internal, "failed to load LogDog annotation stream from: %s", as.Path) 105 return nil, grpcutil.Errf(codes.Internal, "failed to load LogDog annotation stream from: %s", as.Path)
102 } 106 }
103 107
104 // Merge the information together. 108 // Merge the information together.
105 if err := mergeBuildIntoAnnotation(c, step, build); err != nil { 109 if err := mergeBuildIntoAnnotation(c, step, build); err != nil {
106 logging.WithError(err).Errorf(c, "Failed to merge annotation wit h build.") 110 logging.WithError(err).Errorf(c, "Failed to merge annotation wit h build.")
107 return nil, grpcutil.Errf(codes.Internal, "failed to merge annot ation and build data") 111 return nil, grpcutil.Errf(codes.Internal, "failed to merge annot ation and build data")
108 } 112 }
(...skipping 11 matching lines...) Expand all
120 } 124 }
121 125
122 // Resolve BuildBot and LogDog build information. We do this 126 // Resolve BuildBot and LogDog build information. We do this
123 // 127 //
124 // This returns an AnnotationStream instance with its project and path 128 // This returns an AnnotationStream instance with its project and path
125 // populated. 129 // populated.
126 // 130 //
127 // This function is messy and implementation-specific. That's the point of this 131 // This function is messy and implementation-specific. That's the point of this
128 // endpoint, though. All of the nastiness here should be replaced with something 132 // endpoint, though. All of the nastiness here should be replaced with something
129 // more elegant once that becomes available. In the meantime... 133 // more elegant once that becomes available. In the meantime...
130 func getLogDogAnnotations(c context.Context, client *coordinator.Client, build * buildbotBuild, 134 func getLogDogAnnotationAddr(c context.Context, client *coordinator.Client, buil d *buildbotBuild,
131 » projectHint cfgtypes.ProjectName) (*logdog.AnnotationStream, error) { 135 » projectHint cfgtypes.ProjectName) (*types.StreamAddr, error) {
132 136
133 // Modern builds will have this information in their build properties. 137 // Modern builds will have this information in their build properties.
134 » var as logdog.AnnotationStream 138 » var addr types.StreamAddr
135 prefix, _ := build.getPropertyValue("logdog_prefix").(string) 139 prefix, _ := build.getPropertyValue("logdog_prefix").(string)
136 project, _ := build.getPropertyValue("logdog_project").(string) 140 project, _ := build.getPropertyValue("logdog_project").(string)
137 if prefix != "" && project != "" { 141 if prefix != "" && project != "" {
138 // Construct the full annotation path. 142 // Construct the full annotation path.
139 » » as.Project = cfgtypes.ProjectName(project) 143 » » addr.Project = cfgtypes.ProjectName(project)
140 » » as.Path = types.StreamName(prefix).Join("annotations") 144 » » addr.Path = types.StreamName(prefix).Join("annotations")
141 145
142 logging.Debugf(c, "Resolved path/project from build properties." ) 146 logging.Debugf(c, "Resolved path/project from build properties." )
143 » » return &as, nil 147 » » return &addr, nil
144 } 148 }
145 149
146 // From here on out, we will need a project hint. 150 // From here on out, we will need a project hint.
147 if projectHint == "" { 151 if projectHint == "" {
148 return nil, grpcutil.Errf(codes.NotFound, "annotation stream not found") 152 return nil, grpcutil.Errf(codes.NotFound, "annotation stream not found")
149 } 153 }
150 » as.Project = projectHint 154 » addr.Project = projectHint
151 155
152 // Execute a LogDog service query to see if we can identify the stream. 156 // Execute a LogDog service query to see if we can identify the stream.
153 err := func() error { 157 err := func() error {
154 var annotationStream *coordinator.LogStream 158 var annotationStream *coordinator.LogStream
155 » » err := client.Query(c, as.Project, "", coordinator.QueryOptions{ 159 » » err := client.Query(c, addr.Project, "", coordinator.QueryOption s{
156 Tags: map[string]string{ 160 Tags: map[string]string{
157 "buildbot.master": build.Master, 161 "buildbot.master": build.Master,
158 "buildbot.builder": build.Buildername, 162 "buildbot.builder": build.Buildername,
159 "buildbot.buildnumber": strconv.Itoa(build.Numbe r), 163 "buildbot.buildnumber": strconv.Itoa(build.Numbe r),
160 }, 164 },
161 ContentType: miloProto.ContentTypeAnnotations, 165 ContentType: miloProto.ContentTypeAnnotations,
162 }, func(ls *coordinator.LogStream) bool { 166 }, func(ls *coordinator.LogStream) bool {
163 // Only need the first (hopefully only?) result. 167 // Only need the first (hopefully only?) result.
164 annotationStream = ls 168 annotationStream = ls
165 return false 169 return false
166 }) 170 })
167 if err != nil { 171 if err != nil {
168 logging.WithError(err).Errorf(c, "Failed to issue log st ream query.") 172 logging.WithError(err).Errorf(c, "Failed to issue log st ream query.")
169 return grpcutil.Internal 173 return grpcutil.Internal
170 } 174 }
171 175
172 if annotationStream != nil { 176 if annotationStream != nil {
173 » » » as.Path = annotationStream.Path 177 » » » addr.Path = annotationStream.Path
174 } 178 }
175 return nil 179 return nil
176 }() 180 }()
177 if err != nil { 181 if err != nil {
178 return nil, err 182 return nil, err
179 } 183 }
180 » if as.Path != "" { 184 » if addr.Path != "" {
181 logging.Debugf(c, "Resolved path/project via tag query.") 185 logging.Debugf(c, "Resolved path/project via tag query.")
182 » » return &as, nil 186 » » return &addr, nil
183 } 187 }
184 188
185 // Last-ditch effort: generate a prefix based on the build properties. T his 189 // Last-ditch effort: generate a prefix based on the build properties. T his
186 // re-implements the "_build_prefix" function in: 190 // re-implements the "_build_prefix" function in:
187 // https://chromium.googlesource.com/chromium/tools/build/+/2d23e5284cc3 1f31c6bc07aa1d3fc5b1c454c3b4/scripts/slave/logdog_bootstrap.py#363 191 // https://chromium.googlesource.com/chromium/tools/build/+/2d23e5284cc3 1f31c6bc07aa1d3fc5b1c454c3b4/scripts/slave/logdog_bootstrap.py#363
188 isAlnum := func(r rune) bool { 192 isAlnum := func(r rune) bool {
189 return ((r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r > = '0' && r <= '9')) 193 return ((r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r > = '0' && r <= '9'))
190 } 194 }
191 normalize := func(v string) string { 195 normalize := func(v string) string {
192 v = strings.Map(func(r rune) rune { 196 v = strings.Map(func(r rune) rune {
193 if isAlnum(r) { 197 if isAlnum(r) {
194 return r 198 return r
195 } 199 }
196 switch r { 200 switch r {
197 case ':', '_', '-', '.': 201 case ':', '_', '-', '.':
198 return r 202 return r
199 default: 203 default:
200 return '_' 204 return '_'
201 } 205 }
202 }, v) 206 }, v)
203 if r, _ := utf8.DecodeRuneInString(v); r == utf8.RuneError || !i sAlnum(r) { 207 if r, _ := utf8.DecodeRuneInString(v); r == utf8.RuneError || !i sAlnum(r) {
204 v = "s_" + v 208 v = "s_" + v
205 } 209 }
206 return v 210 return v
207 } 211 }
208 » as.Path = types.StreamPath(fmt.Sprintf("bb/%s/%s/%s/+/annotations", 212 » addr.Path = types.StreamPath(fmt.Sprintf("bb/%s/%s/%s/+/annotations",
209 normalize(build.Master), normalize(build.Buildername), normalize (strconv.Itoa(build.Number)))) 213 normalize(build.Master), normalize(build.Buildername), normalize (strconv.Itoa(build.Number))))
210 214
211 logging.Debugf(c, "Generated path/project algorithmically.") 215 logging.Debugf(c, "Generated path/project algorithmically.")
212 » return &as, nil 216 » return &addr, nil
213 } 217 }
214 218
215 // mergeBuildInfoIntoAnnotation merges BuildBot-specific build informtion into 219 // mergeBuildInfoIntoAnnotation merges BuildBot-specific build informtion into
216 // a LogDog annotation protobuf. 220 // a LogDog annotation protobuf.
217 // 221 //
218 // This consists of augmenting the Step's properties with BuildBot's properties, 222 // This consists of augmenting the Step's properties with BuildBot's properties,
219 // favoring the Step's version of the properties if there are two with the same 223 // favoring the Step's version of the properties if there are two with the same
220 // name. 224 // name.
221 func mergeBuildIntoAnnotation(c context.Context, step *miloProto.Step, build *bu ildbotBuild) error { 225 func mergeBuildIntoAnnotation(c context.Context, step *miloProto.Step, build *bu ildbotBuild) error {
222 allProps := stringset.New(len(step.Property) + len(build.Properties)) 226 allProps := stringset.New(len(step.Property) + len(build.Properties))
223 for _, prop := range step.Property { 227 for _, prop := range step.Property {
224 allProps.Add(prop.Name) 228 allProps.Add(prop.Name)
225 } 229 }
226 for _, prop := range build.Properties { 230 for _, prop := range build.Properties {
227 // Annotation protobuf overrides BuildBot properties. 231 // Annotation protobuf overrides BuildBot properties.
228 if allProps.Has(prop.Name) { 232 if allProps.Has(prop.Name) {
229 continue 233 continue
230 } 234 }
231 allProps.Add(prop.Name) 235 allProps.Add(prop.Name)
232 236
233 step.Property = append(step.Property, &miloProto.Step_Property{ 237 step.Property = append(step.Property, &miloProto.Step_Property{
234 Name: prop.Name, 238 Name: prop.Name,
235 Value: fmt.Sprintf("%v", prop.Value), 239 Value: fmt.Sprintf("%v", prop.Value),
236 }) 240 })
237 } 241 }
238 242
239 return nil 243 return nil
240 } 244 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698