func()

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
}