in components/google-built-opentelemetry-collector/exporter/googleservicecontrolexporter/exporter.go [199:241]
func (e *Exporter) pushReportRequest(ctx context.Context, req *scpb.ReportRequest) error {
// Check if we need to add the debug encrypted header
if e.enableDebugHeaders {
e.debugHeaderMutex.Lock()
if e.nowFunc().Before(e.debugHeaderExpirationTime) {
ctx = metadata.AppendToOutgoingContext(ctx, debugHeaderKey, debugHeaderVal)
}
e.debugHeaderMutex.Unlock()
}
// This is thread-safe due to https://grpc.io/docs/languages/go/generated-code/:
// "client-side RPC invocations and server-side RPC handlers are thread-safe and are meant to be run on concurrent goroutines".
resp, err := e.client.Report(ctx, req)
if err != nil {
// ReportStatus tells health check that we had an error.
componentstatus.ReportStatus(e.host, componentstatus.NewRecoverableErrorEvent(err))
e.logFailedReportReq(req, err)
if shouldRetry(err) {
if e.enableDebugHeaders {
// Get retriable error and enable debug header: Add encrypted debug header for 3 min
e.debugHeaderMutex.Lock()
if e.nowFunc().After(e.debugHeaderExpirationTime) {
e.debugHeaderExpirationTime = e.nowFunc().Add(debugHeaderTimeoutMinutes * time.Minute)
}
e.debugHeaderMutex.Unlock()
}
return err
}
// "Permanent" tells OTel retry machinery that request should not be retried.
return consumererror.NewPermanent(err)
}
for _, re := range resp.GetReportErrors() {
e.logger.Warnf("Service Control Report() partially failed, operation %s rejected: %+v", re.OperationId, re.Status)
}
// ReportStatus tells health check that everything is OK.
componentstatus.ReportStatus(e.host, componentstatus.NewEvent(componentstatus.StatusOK))
return nil
}