blob: 4878f1d4ac7894d542bd00c29f5b8856b5e1cbd9 [file]
// Copyright 2017 The LUCI Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package main
import (
"os"
"time"
"golang.org/x/net/context"
"github.com/golang/protobuf/proto"
"github.com/luci/luci-go/common/eventlog"
logpb "github.com/luci/luci-go/common/eventlog/proto"
)
type syncLogger interface {
LogSync(ctx context.Context, events ...*eventlog.ChromeInfraLogEvent) error
NewLogEvent(ctx context.Context, eventTime eventlog.TypedTime) *eventlog.ChromeInfraLogEvent
}
// An IsolateEventLogger logs eventlogs which contain stats about the data uploaded to the isolate server.
type IsolateEventLogger struct {
client syncLogger
// getEnvironmentValue looks up the value of an environment variable.
// Set this to override the default implementation for testing.
getEnvironmentValue func(key string) *string
}
// NewLogger returns an IsolateEventLogger which logs to the specified endpoint.
func NewLogger(ctx context.Context, endpoint string) *IsolateEventLogger {
l := &IsolateEventLogger{}
if host := eventlogEndpoint(endpoint); host != "" {
l.client = eventlog.NewClient(ctx, host)
}
return l
}
// logStats synchronously logs an eventlog which describes an isolate run.
func (l *IsolateEventLogger) logStats(ctx context.Context, op *logpb.IsolateClientEvent_Operation, start, end time.Time, archiveDetails *logpb.IsolateClientEvent_ArchiveDetails) error {
if l.client == nil {
return nil
}
bi := l.getBuildbotInfo()
event := l.client.NewLogEvent(ctx, eventlog.Point())
event.InfraEvent.IsolateClientEvent = &logpb.IsolateClientEvent{
Binary: &logpb.Binary{
Name: proto.String("isolate"),
VersionNumber: proto.String(version),
},
Operation: op,
ArchiveDetails: archiveDetails,
Master: bi.master,
Builder: bi.builder,
BuildId: bi.buildID,
Slave: bi.slave,
StartTsUsec: proto.Int64(int64(start.UnixNano() / 1e3)),
EndTsUsec: proto.Int64(int64(end.UnixNano() / 1e3)),
}
return l.client.LogSync(ctx, event)
}
func eventlogEndpoint(endpointFlag string) string {
switch endpointFlag {
case "test":
return eventlog.TestEndpoint
case "prod":
return eventlog.ProdEndpoint
default:
return endpointFlag
}
}
// buildbotInfo contains information about the build in which this command was run.
type buildbotInfo struct {
// Variables which are not present in the environment are nil.
master, builder, buildID, slave *string
}
// getBuildbotInfo poulates a buildbotInfo with information from the environment.
func (l *IsolateEventLogger) getBuildbotInfo() *buildbotInfo {
return &buildbotInfo{
master: l.getEnvValue("BUILDBOT_MASTERNAME"),
builder: l.getEnvValue("BUILDBOT_BUILDERNAME"),
buildID: l.getEnvValue("BUILDBOT_BUILDNUMBER"),
slave: l.getEnvValue("BUILDBOT_SLAVENAME"),
}
}
func (l *IsolateEventLogger) getEnvValue(key string) *string {
if l.getEnvironmentValue != nil {
return l.getEnvironmentValue(key)
}
if val, ok := os.LookupEnv(key); ok {
return &val
}
return nil
}