golang.org/x/build@v0.0.0-20240506185731-218518f32b70/internal/coordinator/pool/log.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build linux || darwin 6 7 package pool 8 9 import ( 10 "context" 11 "fmt" 12 "log" 13 "sync" 14 "time" 15 16 "cloud.google.com/go/datastore" 17 "golang.org/x/build/internal/spanlog" 18 "golang.org/x/build/types" 19 ) 20 21 // EventTimeLogger is the logging interface used to log 22 // an event at a point in time. 23 type EventTimeLogger interface { 24 LogEventTime(event string, optText ...string) 25 } 26 27 // Logger is the logging interface used within the coordinator. 28 // It can both log a message at a point in time, as well 29 // as log a span (something having a start and end time, as well as 30 // a final success status). 31 type Logger interface { 32 EventTimeLogger // point in time 33 spanlog.Logger // action spanning time 34 } 35 36 type Process struct { 37 processID string 38 processStartTime time.Time 39 } 40 41 var ( 42 process *Process 43 once sync.Once 44 ) 45 46 // SetProcessMetadata sets metadata about the process. This should be called before any 47 // event logging operations. 48 func SetProcessMetadata(id string, startTime time.Time) *Process { 49 once.Do(func() { 50 process = &Process{ 51 processID: id, 52 processStartTime: startTime, 53 } 54 }) 55 return process 56 } 57 58 // CoordinatorProcess returns the package level process logger. 59 func CoordinatorProcess() *Process { 60 return process 61 } 62 63 // ProcessRecord is a datastore record about the lifetime of a coordinator process. 64 // 65 // Example GQL query: 66 // SELECT * From Process where LastHeartbeat > datetime("2016-01-01T00:00:00Z") 67 type ProcessRecord struct { 68 ID string 69 Start time.Time 70 LastHeartbeat time.Time 71 72 // TODO: version, who deployed, CoreOS version, Docker version, 73 // GCE instance type? 74 } 75 76 func (p *Process) UpdateInstanceRecord() { 77 dsClient := NewGCEConfiguration().DSClient() 78 if dsClient == nil { 79 return 80 } 81 ctx := context.Background() 82 for { 83 key := datastore.NameKey("Process", p.processID, nil) 84 _, err := dsClient.Put(ctx, key, &ProcessRecord{ 85 ID: p.processID, 86 Start: p.processStartTime, 87 LastHeartbeat: time.Now(), 88 }) 89 if err != nil { 90 log.Printf("datastore Process Put: %v", err) 91 } 92 time.Sleep(30 * time.Second) 93 } 94 } 95 96 func (p *Process) PutBuildRecord(br *types.BuildRecord) { 97 dsClient := NewGCEConfiguration().DSClient() 98 if dsClient == nil { 99 return 100 } 101 ctx := context.Background() 102 key := datastore.NameKey("Build", br.ID, nil) 103 if _, err := dsClient.Put(ctx, key, br); err != nil { 104 log.Printf("datastore Build Put: %v", err) 105 } 106 } 107 108 func (p *Process) PutSpanRecord(sr *types.SpanRecord) { 109 dsClient := NewGCEConfiguration().DSClient() 110 if dsClient == nil { 111 return 112 } 113 ctx := context.Background() 114 key := datastore.NameKey("Span", fmt.Sprintf("%s-%v-%v", sr.BuildID, sr.StartTime.UnixNano(), sr.Event), nil) 115 if _, err := dsClient.Put(ctx, key, sr); err != nil { 116 log.Printf("datastore Span Put: %v", err) 117 } 118 }