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

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

Issue 2681393008: Accommodate Swarming try number into log stream. (Closed)
Patch Set: 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
« no previous file with comments | « no previous file | milo/appengine/swarming/buildinfo_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 swarming 5 package swarming
6 6
7 import ( 7 import (
8 "strconv"
8 "strings" 9 "strings"
10 "unicode/utf8"
9 11
10 swarming "github.com/luci/luci-go/common/api/swarming/swarming/v1" 12 swarming "github.com/luci/luci-go/common/api/swarming/swarming/v1"
13 "github.com/luci/luci-go/common/errors"
11 "github.com/luci/luci-go/common/logging" 14 "github.com/luci/luci-go/common/logging"
12 miloProto "github.com/luci/luci-go/common/proto/milo" 15 miloProto "github.com/luci/luci-go/common/proto/milo"
13 "github.com/luci/luci-go/grpc/grpcutil" 16 "github.com/luci/luci-go/grpc/grpcutil"
14 "github.com/luci/luci-go/logdog/client/coordinator" 17 "github.com/luci/luci-go/logdog/client/coordinator"
15 "github.com/luci/luci-go/logdog/common/types" 18 "github.com/luci/luci-go/logdog/common/types"
16 "github.com/luci/luci-go/luci_config/common/cfgtypes" 19 "github.com/luci/luci-go/luci_config/common/cfgtypes"
17 milo "github.com/luci/luci-go/milo/api/proto" 20 milo "github.com/luci/luci-go/milo/api/proto"
18 "github.com/luci/luci-go/milo/appengine/logdog" 21 "github.com/luci/luci-go/milo/appengine/logdog"
19 22
20 "golang.org/x/net/context" 23 "golang.org/x/net/context"
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 return nil, grpcutil.NotFound 82 return nil, grpcutil.NotFound
80 } 83 }
81 84
82 logging.WithError(err).Errorf(c, "Failed to load Swarming task." ) 85 logging.WithError(err).Errorf(c, "Failed to load Swarming task." )
83 return nil, grpcutil.Internal 86 return nil, grpcutil.Internal
84 } 87 }
85 88
86 // Determine the LogDog annotation stream path for this Swarming task. 89 // Determine the LogDog annotation stream path for this Swarming task.
87 // 90 //
88 // On failure, will return a gRPC error. 91 // On failure, will return a gRPC error.
89 » as, err := resolveLogDogAnnotations(c, fr.req, projectHint, host, req.Ta sk) 92 » as, err := resolveLogDogAnnotations(c, fr.req, projectHint, host, req.Ta sk, fr.res.TryNumber)
90 if err != nil { 93 if err != nil {
91 logging.WithError(err).Warningf(c, "Failed to get annotation str eam parameters.") 94 logging.WithError(err).Warningf(c, "Failed to get annotation str eam parameters.")
92 return nil, err 95 return nil, err
93 } 96 }
94 if err := as.Normalize(); err != nil { 97 if err := as.Normalize(); err != nil {
95 logging.WithError(err).Warningf(c, "Failed to normalize annotati on stream parameters.") 98 logging.WithError(err).Warningf(c, "Failed to normalize annotati on stream parameters.")
96 return nil, grpcutil.Internal 99 return nil, grpcutil.Internal
97 } 100 }
98 101
102 logging.Fields{
103 "project": as.Project,
104 "path": as.Path,
105 }.Infof(c, "Resolved annotation stream.")
106
99 client, err := p.newLogdogClient(c) 107 client, err := p.newLogdogClient(c)
100 if err != nil { 108 if err != nil {
101 logging.WithError(err).Errorf(c, "Failed to create LogDog client .") 109 logging.WithError(err).Errorf(c, "Failed to create LogDog client .")
102 return nil, grpcutil.Internal 110 return nil, grpcutil.Internal
103 } 111 }
104 112
105 // Fetch LogDog annotation stream data. 113 // Fetch LogDog annotation stream data.
106 as.Client = client 114 as.Client = client
107 step, err := as.Load(c) 115 step, err := as.Load(c)
108 if err != nil { 116 if err != nil {
(...skipping 20 matching lines...) Expand all
129 137
130 // resolveLogDogAnnotations returns a configured AnnotationStream given the inpu t 138 // resolveLogDogAnnotations returns a configured AnnotationStream given the inpu t
131 // parameters. 139 // parameters.
132 // 140 //
133 // This will return a gRPC error on failure. 141 // This will return a gRPC error on failure.
134 // 142 //
135 // This function is messy and implementation-specific. That's the point of this 143 // This function is messy and implementation-specific. That's the point of this
136 // endpoint, though. All of the nastiness here should be replaced with something 144 // endpoint, though. All of the nastiness here should be replaced with something
137 // more elegant once that becomes available. In the meantime... 145 // more elegant once that becomes available. In the meantime...
138 func resolveLogDogAnnotations(c context.Context, sr *swarming.SwarmingRpcsTaskRe quest, projectHint cfgtypes.ProjectName, 146 func resolveLogDogAnnotations(c context.Context, sr *swarming.SwarmingRpcsTaskRe quest, projectHint cfgtypes.ProjectName,
139 » host, taskID string) (*logdog.AnnotationStream, error) { 147 » host, taskID string, tryNumber int64) (*logdog.AnnotationStream, error) {
140 148
141 // If this is a Kitchen command, maybe we can infer our LogDog project f rom 149 // If this is a Kitchen command, maybe we can infer our LogDog project f rom
142 // the command-line. 150 // the command-line.
143 var as logdog.AnnotationStream 151 var as logdog.AnnotationStream
144 if sr.Properties == nil { 152 if sr.Properties == nil {
145 logging.Warningf(c, "No request properties, can't infer annotati on stream path.") 153 logging.Warningf(c, "No request properties, can't infer annotati on stream path.")
146 return nil, grpcutil.NotFound 154 return nil, grpcutil.NotFound
147 } 155 }
148 156
149 var isKitchen bool 157 var isKitchen bool
150 if as.Project, isKitchen = getLogDogProjectFromKitchen(sr.Properties.Com mand); !isKitchen { 158 if as.Project, isKitchen = getLogDogProjectFromKitchen(sr.Properties.Com mand); !isKitchen {
151 logging.Warningf(c, "Not a Kitchen CLI, can't infer annotation s tream path.") 159 logging.Warningf(c, "Not a Kitchen CLI, can't infer annotation s tream path.")
152 return nil, grpcutil.NotFound 160 return nil, grpcutil.NotFound
153 } 161 }
154 162
155 if as.Project == "" { 163 if as.Project == "" {
156 as.Project = projectHint 164 as.Project = projectHint
157 } 165 }
158 if as.Project == "" { 166 if as.Project == "" {
159 logging.Warningf(c, "Don't know how to get annotation stream pat h.") 167 logging.Warningf(c, "Don't know how to get annotation stream pat h.")
160 return nil, grpcutil.NotFound 168 return nil, grpcutil.NotFound
161 } 169 }
162 170
163 // This is a Kitchen run, and it has a project! Construct the annotation 171 // This is a Kitchen run, and it has a project! Construct the annotation
164 // stream path. 172 // stream path.
165 // 173 //
166 // This is an implementation of: 174 // This is an implementation of:
167 // https://chromium.googlesource.com/infra/infra/+/a7032e3e240d4b81a1912 bfaf29a20d02f665cc1/go/src/infra/tools/kitchen/cook_logdog.go#129 175 // https://chromium.googlesource.com/infra/infra/+/a7032e3e240d4b81a1912 bfaf29a20d02f665cc1/go/src/infra/tools/kitchen/cook_logdog.go#129
168 » prefix, err := types.MakeStreamName("", "swarm", host, taskID) 176 » runID, err := getRunID(taskID, tryNumber)
177 » if err != nil {
178 » » logging.Fields{
179 » » » logging.ErrorKey: err,
180 » » » "taskID": taskID,
181 » » » "tryNumber": tryNumber,
182 » » }.Errorf(c, "Failed to get Run ID for task/try.")
183 » » return nil, grpcutil.Internal
184 » }
185
186 » prefix, err := types.MakeStreamName("", "swarm", host, runID)
169 if err != nil { 187 if err != nil {
170 logging.WithError(err).Errorf(c, "Failed to generate Swarming pr efix.") 188 logging.WithError(err).Errorf(c, "Failed to generate Swarming pr efix.")
171 return nil, grpcutil.Internal 189 return nil, grpcutil.Internal
172 } 190 }
173 as.Path = prefix.Join("annotations") 191 as.Path = prefix.Join("annotations")
174 return &as, nil 192 return &as, nil
175 } 193 }
176 194
177 func getLogDogProjectFromKitchen(cmd []string) (proj cfgtypes.ProjectName, isKit chen bool) { 195 func getLogDogProjectFromKitchen(cmd []string) (proj cfgtypes.ProjectName, isKit chen bool) {
178 // Is this a Kitchen command? 196 // Is this a Kitchen command?
(...skipping 11 matching lines...) Expand all
190 if arg == "-logdog-project" { 208 if arg == "-logdog-project" {
191 if i < len(cmd)-2 { 209 if i < len(cmd)-2 {
192 proj = cfgtypes.ProjectName(cmd[i+1]) 210 proj = cfgtypes.ProjectName(cmd[i+1])
193 return 211 return
194 } 212 }
195 break 213 break
196 } 214 }
197 } 215 }
198 return 216 return
199 } 217 }
218
219 // getRunID converts a Swarming task ID and try number into a Swarming Run ID.
220 //
221 // The run ID is a permutation of the last four bits of the Swarming Task ID.
222 // Therefore, we chop it off of the string, mutate it, and then add it back.
223 //
224 // TODO(dnj): Replace this with Swarming API call once finished.
225 func getRunID(taskID string, tryNumber int64) (string, error) {
226 // Slice off the last character form the task ID.
227 if len(taskID) == 0 {
228 return "", errors.New("swarming task ID is empty")
229 }
230
231 // Parse "tryNumber" as a hex string.
232 if tryNumber < 0 || tryNumber > 0x0F {
233 return "", errors.Reason("try number %(try)d exceeds 4 bits").
234 D("try", tryNumber).
235 Err()
236 }
237
238 lastChar, lastCharSize := utf8.DecodeLastRuneInString(taskID)
239 v, err := strconv.ParseUint(string(lastChar), 16, 8)
240 if err != nil {
241 return "", errors.Annotate(err).Reason("failed to parse hex from rune: %(rune)r").
242 D("rune", lastChar).
243 Err()
244 }
245
246 return taskID[:len(taskID)-lastCharSize] + strconv.FormatUint((v|uint64( tryNumber)), 16), nil
247 }
OLDNEW
« no previous file with comments | « no previous file | milo/appengine/swarming/buildinfo_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698