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

Side by Side Diff: logdog/server/service/service.go

Issue 2648433007: LogDog: Use datastore config cache when available. (Closed)
Patch Set: Updated patchset dependency Created 3 years, 11 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 service 5 package service
6 6
7 import ( 7 import (
8 "flag" 8 "flag"
9 "fmt" 9 "fmt"
10 "net/http" 10 "net/http"
11 "net/url" 11 "net/url"
12 "os" 12 "os"
13 "os/signal" 13 "os/signal"
14 "path/filepath" 14 "path/filepath"
15 "runtime/pprof" 15 "runtime/pprof"
16 "sync/atomic" 16 "sync/atomic"
17 "time" 17 "time"
18 18
19 "github.com/luci/luci-go/appengine/gaesettings"
19 "github.com/luci/luci-go/client/authcli" 20 "github.com/luci/luci-go/client/authcli"
20 "github.com/luci/luci-go/common/auth" 21 "github.com/luci/luci-go/common/auth"
21 "github.com/luci/luci-go/common/clock/clockflag" 22 "github.com/luci/luci-go/common/clock/clockflag"
22 "github.com/luci/luci-go/common/config/impl/filesystem" 23 "github.com/luci/luci-go/common/config/impl/filesystem"
23 "github.com/luci/luci-go/common/data/caching/proccache" 24 "github.com/luci/luci-go/common/data/caching/proccache"
24 "github.com/luci/luci-go/common/errors" 25 "github.com/luci/luci-go/common/errors"
25 "github.com/luci/luci-go/common/gcloud/gs" 26 "github.com/luci/luci-go/common/gcloud/gs"
26 log "github.com/luci/luci-go/common/logging" 27 log "github.com/luci/luci-go/common/logging"
27 "github.com/luci/luci-go/common/logging/gologger" 28 "github.com/luci/luci-go/common/logging/gologger"
28 "github.com/luci/luci-go/common/proto/google" 29 "github.com/luci/luci-go/common/proto/google"
29 "github.com/luci/luci-go/common/tsmon" 30 "github.com/luci/luci-go/common/tsmon"
30 "github.com/luci/luci-go/common/tsmon/target" 31 "github.com/luci/luci-go/common/tsmon/target"
31 "github.com/luci/luci-go/grpc/prpc" 32 "github.com/luci/luci-go/grpc/prpc"
32 "github.com/luci/luci-go/logdog/api/config/svcconfig" 33 "github.com/luci/luci-go/logdog/api/config/svcconfig"
33 "github.com/luci/luci-go/logdog/api/endpoints/coordinator/services/v1" 34 "github.com/luci/luci-go/logdog/api/endpoints/coordinator/services/v1"
34 "github.com/luci/luci-go/logdog/common/storage" 35 "github.com/luci/luci-go/logdog/common/storage"
35 "github.com/luci/luci-go/logdog/common/storage/bigtable" 36 "github.com/luci/luci-go/logdog/common/storage/bigtable"
36 "github.com/luci/luci-go/logdog/server/retryServicesClient" 37 "github.com/luci/luci-go/logdog/server/retryServicesClient"
37 "github.com/luci/luci-go/logdog/server/service/config" 38 "github.com/luci/luci-go/logdog/server/service/config"
38 "github.com/luci/luci-go/luci_config/common/cfgtypes" 39 "github.com/luci/luci-go/luci_config/common/cfgtypes"
39 "github.com/luci/luci-go/luci_config/server/cfgclient" 40 "github.com/luci/luci-go/luci_config/server/cfgclient"
40 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/client" 41 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/client"
41 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/testconfig " 42 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/testconfig "
42 "github.com/luci/luci-go/luci_config/server/cfgclient/textproto" 43 "github.com/luci/luci-go/luci_config/server/cfgclient/textproto"
44 "github.com/luci/luci-go/server/settings"
45
46 "github.com/luci/gae/impl/cloud"
43 47
44 "cloud.google.com/go/compute/metadata" 48 "cloud.google.com/go/compute/metadata"
49 "cloud.google.com/go/datastore"
45 "golang.org/x/net/context" 50 "golang.org/x/net/context"
46 "golang.org/x/oauth2" 51 "golang.org/x/oauth2"
47 "google.golang.org/api/option" 52 "google.golang.org/api/option"
48 ) 53 )
49 54
50 var ( 55 var (
51 // ErrInvalidConfig is an error that is returned when the supplied 56 // ErrInvalidConfig is an error that is returned when the supplied
52 // configuration is invalid. 57 // configuration is invalid.
53 ErrInvalidConfig = errors.New("invalid configuration") 58 ErrInvalidConfig = errors.New("invalid configuration")
54 59
(...skipping 30 matching lines...) Expand all
85 authFlags authcli.Flags 90 authFlags authcli.Flags
86 tsMonFlags tsmon.Flags 91 tsMonFlags tsmon.Flags
87 92
88 coordinatorHost string 93 coordinatorHost string
89 coordinatorInsecure bool 94 coordinatorInsecure bool
90 storageCredentialJSONPath string 95 storageCredentialJSONPath string
91 cpuProfilePath string 96 cpuProfilePath string
92 heapProfilePath string 97 heapProfilePath string
93 98
94 // onGCE is true if we're on GCE. We probe this exactly once. 99 // onGCE is true if we're on GCE. We probe this exactly once.
95 » onGCE bool 100 » onGCE bool
101 » hasDatastore bool
96 102
97 killCheckInterval clockflag.Duration 103 killCheckInterval clockflag.Duration
98 configFilePath string 104 configFilePath string
99 serviceConfig svcconfig.Config 105 serviceConfig svcconfig.Config
100 configCache config.ProcCache 106 configCache config.ProcCache
101 107
102 // serviceID is the cloud project ID, which is also this service's uniqu e 108 // serviceID is the cloud project ID, which is also this service's uniqu e
103 // ID. This can be specified by flag or, if on GCE, will automatically b e 109 // ID. This can be specified by flag or, if on GCE, will automatically b e
104 // probed from metadata. 110 // probed from metadata.
105 serviceID string 111 serviceID string
(...skipping 14 matching lines...) Expand all
120 126
121 rc := 0 127 rc := 0
122 if err := s.runImpl(c, f); err != nil { 128 if err := s.runImpl(c, f); err != nil {
123 log.WithError(err).Errorf(c, "Application exiting with error.") 129 log.WithError(err).Errorf(c, "Application exiting with error.")
124 rc = 1 130 rc = 1
125 } 131 }
126 os.Exit(rc) 132 os.Exit(rc)
127 } 133 }
128 134
129 func (s *Service) runImpl(c context.Context, f func(context.Context) error) erro r { 135 func (s *Service) runImpl(c context.Context, f func(context.Context) error) erro r {
136 // Probe our environment for default values.
137 s.probeGCEEnvironment(c)
iannucci 2017/01/21 00:32:24 should this have been in the previous CL?
dnj 2017/01/21 02:00:02 Ugh, looks like it was removed when I split. Oh we
138
139 // Install service flags and parse.
130 s.addFlags(c, &s.Flags) 140 s.addFlags(c, &s.Flags)
131 if err := s.Flags.Parse(os.Args[1:]); err != nil { 141 if err := s.Flags.Parse(os.Args[1:]); err != nil {
132 log.WithError(err).Errorf(c, "Failed to parse command-line.") 142 log.WithError(err).Errorf(c, "Failed to parse command-line.")
133 return err 143 return err
134 } 144 }
135 145
136 // Install logging configuration. 146 // Install logging configuration.
137 c = s.loggingFlags.Set(c) 147 c = s.loggingFlags.Set(c)
138 148
139 if p := s.cpuProfilePath; p != "" { 149 if p := s.cpuProfilePath; p != "" {
(...skipping 25 matching lines...) Expand all
165 175
166 if err := pprof.WriteHeapProfile(fd); err != nil { 176 if err := pprof.WriteHeapProfile(fd); err != nil {
167 log.Fields{ 177 log.Fields{
168 log.ErrorKey: err, 178 log.ErrorKey: err,
169 "path": p, 179 "path": p,
170 }.Warningf(c, "Failed to write heap profile.") 180 }.Warningf(c, "Failed to write heap profile.")
171 } 181 }
172 }() 182 }()
173 } 183 }
174 184
185 // Cancel our Context after we're done our run loop.
186 c, cancelFunc := context.WithCancel(c)
187 defer cancelFunc()
188
175 // Validate the runtime environment. 189 // Validate the runtime environment.
176 if s.serviceID == "" { 190 if s.serviceID == "" {
177 return errors.New("no service ID was configured (-service-id)") 191 return errors.New("no service ID was configured (-service-id)")
178 } 192 }
179 193
194 // Install a cloud datastore client. This is non-fatal if it fails.
195 dsClient, err := s.initDatastoreClient(c)
196 if err == nil {
197 defer dsClient.Close()
198
199 ccfg := cloud.Config{
200 DS: dsClient,
201 }
202 c = ccfg.Use(c)
203 c = settings.Use(c, settings.New(gaesettings.Storage{}))
204
205 s.hasDatastore = true
206 log.Infof(c, "Enabled cloud datastore access.")
207 } else {
208 log.WithError(err).Debugf(c, "Failed to create cloud datastore c lient.")
iannucci 2017/01/21 00:32:24 wdyt about reversing the severities? maybe debug f
dnj 2017/01/21 02:00:02 Okay.
209 }
210
180 // Install a process-wide cache. 211 // Install a process-wide cache.
181 c = proccache.Use(c, &proccache.Cache{}) 212 c = proccache.Use(c, &proccache.Cache{})
182 213
183 // Configure our signal handler. It will listen for terminating signals and 214 // Configure our signal handler. It will listen for terminating signals and
184 // issue a shutdown signal if one is received. 215 // issue a shutdown signal if one is received.
185 signalC := make(chan os.Signal) 216 signalC := make(chan os.Signal)
186 go func(c context.Context) { 217 go func(c context.Context) {
187 hasShutdownAlready := false 218 hasShutdownAlready := false
188 for sig := range signalC { 219 for sig := range signalC {
189 if !hasShutdownAlready { 220 if !hasShutdownAlready {
(...skipping 17 matching lines...) Expand all
207 238
208 // Initialize our tsmon library. 239 // Initialize our tsmon library.
209 c = tsmon.WithState(c, tsmon.NewState()) 240 c = tsmon.WithState(c, tsmon.NewState())
210 241
211 if err := tsmon.InitializeFromFlags(c, &s.tsMonFlags); err != nil { 242 if err := tsmon.InitializeFromFlags(c, &s.tsMonFlags); err != nil {
212 log.WithError(err).Warningf(c, "Failed to initialize monitoring; will continue without metrics.") 243 log.WithError(err).Warningf(c, "Failed to initialize monitoring; will continue without metrics.")
213 } 244 }
214 defer tsmon.Shutdown(c) 245 defer tsmon.Shutdown(c)
215 246
216 // Initialize our Client instantiations. 247 // Initialize our Client instantiations.
217 var err error
218 if s.coord, err = s.initCoordinatorClient(c); err != nil { 248 if s.coord, err = s.initCoordinatorClient(c); err != nil {
219 log.WithError(err).Errorf(c, "Failed to setup Coordinator client .") 249 log.WithError(err).Errorf(c, "Failed to setup Coordinator client .")
220 return err 250 return err
221 } 251 }
222 252
223 // Initialize and install our config service and caching layers, and loa d our 253 // Initialize and install our config service and caching layers, and loa d our
224 // initial service config. 254 // initial service config.
225 if err := s.initConfig(&c); err != nil { 255 if err := s.initConfig(&c); err != nil {
226 log.WithError(err).Errorf(c, "Failed to setup configuration.") 256 log.WithError(err).Errorf(c, "Failed to setup configuration.")
227 return err 257 return err
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 "If supplied, enable CPU profiling and write the profile here.") 294 "If supplied, enable CPU profiling and write the profile here.")
265 fs.Var(&s.killCheckInterval, "config-kill-interval", 295 fs.Var(&s.killCheckInterval, "config-kill-interval",
266 "If non-zero, poll for configuration changes and kill the applic ation if one is detected.") 296 "If non-zero, poll for configuration changes and kill the applic ation if one is detected.")
267 fs.StringVar(&s.configFilePath, "config-file-path", "", 297 fs.StringVar(&s.configFilePath, "config-file-path", "",
268 "If set, load configuration from a local filesystem rooted here. ") 298 "If set, load configuration from a local filesystem rooted here. ")
269 } 299 }
270 300
271 // probeGCEEnvironment fills in any parameters that can be probed from Google 301 // probeGCEEnvironment fills in any parameters that can be probed from Google
272 // Compute Engine metadata. 302 // Compute Engine metadata.
273 // 303 //
274 // If we're not running on GCE, this will return nil. An error will only be 304 // If we're not running on GCE, this will do nothing. It is non-fatal if any
275 // returned if an operation that is expected to work fails. 305 // given GCE field fails to be probed.
276 func (s *Service) probeGCEEnvironment(c context.Context) error { 306 func (s *Service) probeGCEEnvironment(c context.Context) {
277 s.onGCE = metadata.OnGCE() 307 s.onGCE = metadata.OnGCE()
278 if !s.onGCE { 308 if !s.onGCE {
279 » » return nil 309 » » return
280 } 310 }
281 311
282 // Determine our service ID from metadata. The service ID will equal the cloud 312 // Determine our service ID from metadata. The service ID will equal the cloud
283 // project ID. 313 // project ID.
284 if s.serviceID == "" { 314 if s.serviceID == "" {
285 var err error 315 var err error
286 if s.serviceID, err = metadata.ProjectID(); err != nil { 316 if s.serviceID, err = metadata.ProjectID(); err != nil {
287 » » » log.WithError(err).Errorf(c, "Failed to probe GCE projec t ID.") 317 » » » log.WithError(err).Warningf(c, "Failed to probe GCE proj ect ID.")
288 » » » return err
289 } 318 }
290 } 319 }
291 » return nil 320 }
321
322 func (s *Service) initDatastoreClient(c context.Context) (*datastore.Client, err or) {
323 » // Initialize Storage authentication.
324 » tokenSource, err := s.TokenSource(c, func(o *auth.Options) {
325 » » o.Scopes = []string{datastore.ScopeDatastore}
326 » })
327 » if err != nil {
328 » » log.WithError(err).Errorf(c, "Failed to create datastore TokenSo urce.")
329 » » return nil, err
330 » }
331
332 » return datastore.NewClient(c, s.serviceID,
333 » » option.WithTokenSource(tokenSource))
292 } 334 }
293 335
294 func (s *Service) initCoordinatorClient(c context.Context) (logdog.ServicesClien t, error) { 336 func (s *Service) initCoordinatorClient(c context.Context) (logdog.ServicesClien t, error) {
295 if s.coordinatorHost == "" { 337 if s.coordinatorHost == "" {
296 log.Errorf(c, "Missing Coordinator URL (-coordinator).") 338 log.Errorf(c, "Missing Coordinator URL (-coordinator).")
297 return nil, ErrInvalidConfig 339 return nil, ErrInvalidConfig
298 } 340 }
299 341
300 httpClient, err := s.AuthenticatedClient(c, func(o *auth.Options) { 342 httpClient, err := s.AuthenticatedClient(c, func(o *auth.Options) {
301 o.Scopes = CoordinatorScopes 343 o.Scopes = CoordinatorScopes
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 if ccfg.ConfigSet == "" { 395 if ccfg.ConfigSet == "" {
354 return errors.New("coordinator does not specify a config set") 396 return errors.New("coordinator does not specify a config set")
355 } 397 }
356 398
357 log.Fields{ 399 log.Fields{
358 "host": host, 400 "host": host,
359 }.Debugf(*c, "Using remote configuration service client.") 401 }.Debugf(*c, "Using remote configuration service client.")
360 p = &client.RemoteProvider{ 402 p = &client.RemoteProvider{
361 Host: host, 403 Host: host,
362 } 404 }
405
406 // If using a remote config provider, enable datastore access an d caching.
407 opts.DatastoreCacheAvailable = s.hasDatastore
363 } else { 408 } else {
364 // Test / Local: use filesystem config path. 409 // Test / Local: use filesystem config path.
365 ci, err := filesystem.New(s.configFilePath) 410 ci, err := filesystem.New(s.configFilePath)
366 if err != nil { 411 if err != nil {
367 return err 412 return err
368 } 413 }
369 p = &testconfig.Provider{Base: ci} 414 p = &testconfig.Provider{Base: ci}
370 } 415 }
371 416
372 // Add config caching layers. 417 // Add config caching layers.
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 // 604 //
560 // An optional permutation function can be provided to modify those Options 605 // An optional permutation function can be provided to modify those Options
561 // before the Authenticator is created. 606 // before the Authenticator is created.
562 func (s *Service) TokenSource(c context.Context, f func(o *auth.Options)) (oauth 2.TokenSource, error) { 607 func (s *Service) TokenSource(c context.Context, f func(o *auth.Options)) (oauth 2.TokenSource, error) {
563 a, err := s.Authenticator(c, f) 608 a, err := s.Authenticator(c, f)
564 if err != nil { 609 if err != nil {
565 return nil, err 610 return nil, err
566 } 611 }
567 return a.TokenSource() 612 return a.TokenSource()
568 } 613 }
OLDNEW
« logdog/server/service/config/opts.go ('K') | « logdog/server/service/config/opts.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698