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  }