blob: 7023c451ff4f53fbac17410d411c5dac5fac45ff [file] [log] [blame]
// Copyright 2017 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package execlog
import (
"context"
"fmt"
"go.opencensus.io/stats"
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
"go.chromium.org/goma/server/log"
gomapb "go.chromium.org/goma/server/proto/api"
execlogpb "go.chromium.org/goma/server/proto/execlog"
)
// DefaultMaxReqMsgSize is max request message size for execlog service.
// execlog server may receives > 8MB.
// grpc's default is 4MB.
const DefaultMaxReqMsgSize = 10 * 1024 * 1024
var (
requests = stats.Int64(
"go.chromium.org/goma/execlog/requests",
"number of execlog entries",
stats.UnitDimensionless)
osFamilyKey = tag.MustNewKey("os_family")
serviceAccountKey = tag.MustNewKey("service_account")
gomaErrorKey = tag.MustNewKey("goma_error")
compilerProxyErrorKey = tag.MustNewKey("compiler_proxy_error")
cacheHitKey = tag.MustNewKey("cache_hit")
depscacheUsedKey = tag.MustNewKey("depscache_used")
localRunKey = tag.MustNewKey("local_run")
execExitStatusKey = tag.MustNewKey("exec_exit_status")
execRequestRetryKey = tag.MustNewKey("exec_request_retry")
handlerTime = stats.Float64(
"go.chromium.org/goma/execlog/handler_time",
"Time in compiler_proxy handler",
stats.UnitMilliseconds)
pendingTime = stats.Float64(
"go.chromium.org/goma/execlog/pending_time",
"Time in pending queue in compiler_proxy",
stats.UnitMilliseconds)
// need compiler_info_process_time?
includeProcessorWaitTime = stats.Float64(
"go.chromium.org/goma/execlog/include_processor_wait_time",
"Time to wait include processor",
stats.UnitMilliseconds)
includeProcessorRunTime = stats.Float64(
"go.chromium.org/goma/execlog/include_processor_run_time",
"Time to run include processor",
stats.UnitMilliseconds)
includePreprocessTotalFiles = stats.Int64(
"go.chromium.org/goma/execlog/include_preprocess_total_files",
"Number of files processed in include preprocess",
stats.UnitDimensionless)
includeFileloadPendingTime = stats.Float64(
"go.chromium.org/goma/execlog/include_fileload_pending_time",
"Time to wait upload input files",
stats.UnitMilliseconds)
includeFileloadRunTime = stats.Float64(
"go.chromium.org/goma/execlog/include_fileload_run_time",
"Time to upload input files",
stats.UnitMilliseconds)
rpcThrottleTime = stats.Float64(
"go.chromium.org/goma/execlog/rpc_throttle_time",
"Time to wait to call Exec by throttling (backoff by error)",
stats.UnitMilliseconds)
rpcPendingTime = stats.Float64(
"go.chromium.org/goma/execlog/rpc_pending_time",
"Time to wait to call Exec (too many requests)",
stats.UnitMilliseconds)
rpcWaitTime = stats.Float64(
"go.chromium.org/goma/execlog/rpc_wait_time",
"Time to wait Exec call response (i.e. server latency)",
stats.UnitMilliseconds)
fileResponseTime = stats.Float64(
"go.chromium.org/goma/execlog/file_response_time",
"Time to process output files",
stats.UnitMilliseconds)
localDelayTime = stats.Float64(
"go.chromium.org/goma/execlog/local_delay_time",
"Time delayed to start run locally",
stats.UnitMilliseconds)
localPendingTime = stats.Float64(
"go.chromium.org/goma/execlog/local_penging_time",
"Time to wait to run locally",
stats.UnitMilliseconds)
localRunTime = stats.Float64(
"go.chromium.org/goma/execlog/local_run_time",
"Time to run locally",
stats.UnitMilliseconds)
defaultLatencyDistribution = view.Distribution(1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 25, 30, 40, 50, 65, 80, 100, 130, 160, 200, 250, 300, 400, 500, 650, 800, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000)
tagKeys = []tag.Key{
osFamilyKey,
serviceAccountKey,
cacheHitKey,
depscacheUsedKey,
localRunKey,
execExitStatusKey,
}
DefaultViews = []*view.View{
{
TagKeys: []tag.Key{
osFamilyKey,
serviceAccountKey,
gomaErrorKey,
compilerProxyErrorKey,
cacheHitKey,
depscacheUsedKey,
localRunKey,
execExitStatusKey,
execRequestRetryKey,
},
Measure: requests,
Aggregation: view.Sum(),
},
{
TagKeys: tagKeys,
Measure: handlerTime,
Aggregation: defaultLatencyDistribution,
},
{
TagKeys: tagKeys,
Measure: pendingTime,
Aggregation: defaultLatencyDistribution,
},
{
TagKeys: tagKeys,
Measure: includeProcessorWaitTime,
Aggregation: defaultLatencyDistribution,
},
{
TagKeys: tagKeys,
Measure: includeProcessorRunTime,
Aggregation: defaultLatencyDistribution,
},
{
TagKeys: tagKeys,
Measure: includePreprocessTotalFiles,
Aggregation: view.Sum(),
},
{
TagKeys: tagKeys,
Measure: includeFileloadPendingTime,
Aggregation: defaultLatencyDistribution,
},
{
TagKeys: tagKeys,
Measure: includeFileloadRunTime,
Aggregation: defaultLatencyDistribution,
},
{
TagKeys: tagKeys,
Measure: rpcThrottleTime,
Aggregation: defaultLatencyDistribution,
},
{
TagKeys: tagKeys,
Measure: rpcPendingTime,
Aggregation: defaultLatencyDistribution,
},
{
TagKeys: tagKeys,
Measure: rpcWaitTime,
Aggregation: defaultLatencyDistribution,
},
{
TagKeys: tagKeys,
Measure: fileResponseTime,
Aggregation: defaultLatencyDistribution,
},
{
TagKeys: tagKeys,
Measure: localDelayTime,
Aggregation: defaultLatencyDistribution,
},
{
TagKeys: tagKeys,
Measure: localPendingTime,
Aggregation: defaultLatencyDistribution,
},
{
TagKeys: tagKeys,
Measure: localRunTime,
Aggregation: defaultLatencyDistribution,
},
}
)
// Service represents goma execlog service.
type Service struct {
execlogpb.UnimplementedLogServiceServer
}
func osFamily(e *gomapb.ExecLog) string {
oi := e.GetOsInfo().GetOsInfoOneof()
switch oi.(type) {
case *gomapb.OSInfo_LinuxInfo_:
return "Linux"
case *gomapb.OSInfo_WinInfo_:
return "Windows"
case *gomapb.OSInfo_MacInfo_:
return "Mac"
default:
return "Unknown"
}
}
// SaveLog emits some metrics.
// * go.chromium.org/goma/execlog/requests
// {os_family, ,goma_error, compiler_proxy_error,
// cache_hit, depscache_used, local_run,
// exec_exit_status, exec_request_retry}
// * go.chromium.org/goma/execlog/handler_time
// TODO: implement saving logic to GCS?
func (Service) SaveLog(ctx context.Context, req *gomapb.SaveLogReq) (*gomapb.SaveLogResp, error) {
logger := log.FromContext(ctx)
for _, e := range req.GetExecLog() {
os := osFamily(e)
serviceAccount := e.GetServiceAccountId()
localRun := e.GetLocalRunTime() > 0
tags := []tag.Mutator{
tag.Upsert(osFamilyKey, os),
tag.Upsert(serviceAccountKey, serviceAccount),
tag.Upsert(cacheHitKey, fmt.Sprint(e.GetCacheHit())),
tag.Upsert(depscacheUsedKey, fmt.Sprint(e.GetDepscacheUsed())),
tag.Upsert(localRunKey, fmt.Sprint(localRun)),
tag.Upsert(execExitStatusKey, fmt.Sprint(e.GetExecExitStatus())),
}
ctx, err := tag.New(ctx, tags...)
if err != nil {
logger.Errorf("Failed to set tags for savelog: %v", err)
continue
}
stats.RecordWithTags(ctx, []tag.Mutator{
tag.Upsert(gomaErrorKey, fmt.Sprint(e.GetGomaError())),
tag.Upsert(compilerProxyErrorKey, fmt.Sprint(e.GetCompilerProxyError())),
tag.Upsert(execRequestRetryKey, fmt.Sprint(e.GetExecRequestRetry())),
}, requests.M(1))
stats.Record(ctx, handlerTime.M(float64(e.GetHandlerTime())))
stats.Record(ctx, pendingTime.M(float64(e.GetPendingTime())))
stats.Record(ctx, includeProcessorWaitTime.M(float64(e.GetIncludeProcessorWaitTime())))
stats.Record(ctx, includeProcessorRunTime.M(float64(e.GetIncludeProcessorRunTime())))
stats.Record(ctx, includePreprocessTotalFiles.M(int64(e.GetIncludePreprocessTotalFiles())))
for _, t := range e.GetIncludeFileloadPendingTime() {
stats.Record(ctx, includeFileloadPendingTime.M(float64(t)))
}
for _, t := range e.GetIncludeFileloadRunTime() {
stats.Record(ctx, includeFileloadRunTime.M(float64(t)))
}
for _, t := range e.GetRpcThrottleTime() {
stats.Record(ctx, rpcThrottleTime.M(float64(t)))
}
for _, t := range e.GetRpcPendingTime() {
stats.Record(ctx, rpcPendingTime.M(float64(t)))
}
for _, t := range e.GetRpcWaitTime() {
stats.Record(ctx, rpcWaitTime.M(float64(t)))
}
stats.Record(ctx, fileResponseTime.M(float64(e.GetFileResponseTime())))
stats.Record(ctx, localDelayTime.M(float64(e.GetLocalDelayTime())))
stats.Record(ctx, localPendingTime.M(float64(e.GetLocalPendingTime())))
stats.Record(ctx, localRunTime.M(float64(e.GetLocalRunTime())))
}
return &gomapb.SaveLogResp{}, nil
}