Skip to content

Commit 2860ce2

Browse files
committed
feat(gax): call logNetworkAttempt and logCall in createApiCall
1 parent 6d9dc09 commit 2860ce2

3 files changed

Lines changed: 469 additions & 49 deletions

File tree

‎core/packages/gax/src/createApiCall.ts‎

Lines changed: 104 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ import {
4141
traceAttempt,
4242
ResendRecorder,
4343
} from './observability/TracerHelper';
44-
import {checkTracingEnabled} from './observability/util';
44+
import {logCall, logNetworkAttempt} from './observability/LoggerHelper';
45+
import {checkLoggingEnabled, checkTracingEnabled} from './observability/util';
4546
import {
4647
StaticTraceContext,
4748
DynamicTraceContext,
@@ -84,21 +85,24 @@ export function createApiCall(
8485
const apiCaller = createAPICaller(settings, descriptor);
8586

8687
const tracingEnabled = checkTracingEnabled(settings);
87-
const staticArgs: StaticTraceContext | undefined = tracingEnabled
88-
? resolveStaticTraceContext(settings)
89-
: undefined;
88+
const loggingEnabled = checkLoggingEnabled(settings);
89+
const staticArgs: StaticTraceContext | undefined =
90+
tracingEnabled || loggingEnabled
91+
? resolveStaticTraceContext(settings)
92+
: undefined;
9093
const serviceName = settings.apiName?.split('.').pop() ?? '';
9194
const isFallback = Boolean(_fallback);
92-
const dynamicArgs: DynamicTraceContext | undefined = tracingEnabled
93-
? {
94-
clientName: serviceName ? `${serviceName}Client` : '',
95-
methodName: settings.otherArgs?.internalMethodName ?? '',
96-
rpcType: isFallback ? 'http' : 'grpc',
97-
}
98-
: undefined;
95+
const dynamicArgs: DynamicTraceContext | undefined =
96+
tracingEnabled || loggingEnabled
97+
? {
98+
clientName: serviceName ? `${serviceName}Client` : '',
99+
methodName: settings.otherArgs?.internalMethodName ?? '',
100+
rpcType: isFallback ? 'http' : 'grpc',
101+
}
102+
: undefined;
99103
// Context for per-attempt low level network CLIENT spans.
100104
const attemptDynamicArgs: AttemptTraceContext | undefined =
101-
tracingEnabled && dynamicArgs
105+
(tracingEnabled || loggingEnabled) && dynamicArgs
102106
? {
103107
...dynamicArgs,
104108
apiName: settings.apiName ?? '',
@@ -163,33 +167,60 @@ export function createApiCall(
163167
?.streaming;
164168

165169
// Wrap the transport call so each attempt (initial send and retries) emits a low level network CLIENT span.
166-
if (tracingEnabled && attemptDynamicArgs && staticArgs) {
170+
if (
171+
(tracingEnabled || loggingEnabled) &&
172+
attemptDynamicArgs &&
173+
staticArgs
174+
) {
167175
const callerWrappedFunc = wrappedFunc;
168176
wrappedFunc = (
169177
argument: {},
170178
metadata: {},
171179
options: {},
172180
attemptCallback: APICallback,
173181
): GRPCCallResult => {
174-
if (!isRetryAttempt) {
175-
attemptResendCount = 0;
182+
let attemptExecution = (cb: APICallback): GRPCCallResult =>
183+
Reflect.apply(callerWrappedFunc, undefined, [
184+
argument,
185+
metadata,
186+
options,
187+
cb,
188+
]);
189+
190+
// If logging is enabled, wrap with L4 attempt error logging
191+
if (loggingEnabled) {
192+
const originalAttemptExecution = attemptExecution;
193+
attemptExecution = (cb: APICallback) =>
194+
logNetworkAttempt(
195+
attemptDynamicArgs,
196+
staticArgs,
197+
loggedCallback =>
198+
originalAttemptExecution(loggedCallback ?? cb),
199+
Boolean(streaming),
200+
cb,
201+
);
176202
}
177-
isRetryAttempt = false;
178-
const resendCount = attemptResendCount;
179-
return traceAttempt(
180-
{...attemptDynamicArgs, resendCount},
181-
staticArgs,
182-
tracedAttemptCallback =>
183-
Reflect.apply(callerWrappedFunc, undefined, [
184-
argument,
185-
metadata,
186-
options,
187-
tracedAttemptCallback ?? attemptCallback,
188-
]),
189-
Boolean(streaming),
190-
attemptCallback,
191-
parentContext,
192-
);
203+
204+
if (tracingEnabled) {
205+
if (!isRetryAttempt) {
206+
attemptResendCount = 0;
207+
}
208+
isRetryAttempt = false;
209+
const resendCount = attemptResendCount;
210+
const originalAttemptExecution = attemptExecution;
211+
attemptExecution = (cb: APICallback) =>
212+
traceAttempt(
213+
{...attemptDynamicArgs, resendCount},
214+
staticArgs,
215+
tracedAttemptCallback =>
216+
originalAttemptExecution(tracedAttemptCallback ?? cb),
217+
Boolean(streaming),
218+
cb,
219+
parentContext,
220+
);
221+
}
222+
223+
return attemptExecution(attemptCallback);
193224
};
194225
}
195226

@@ -261,27 +292,54 @@ export function createApiCall(
261292
return currentApiCaller.result(ongoingCall);
262293
};
263294

264-
if (tracingEnabled && dynamicArgs && staticArgs) {
295+
if (
296+
(tracingEnabled || loggingEnabled) &&
297+
dynamicArgs &&
298+
attemptDynamicArgs &&
299+
staticArgs
300+
) {
265301
const isStreamingCall = apiCaller instanceof StreamingApiCaller;
266302
return (
267303
request: RequestType,
268304
callOptions?: CallOptions,
269305
callback?: APICallback,
270306
) => {
271-
return traceCall(
272-
dynamicArgs,
273-
staticArgs,
274-
(tracedCallback?: APICallback) => {
275-
// `traceCall` wraps the user's callback whenever one was supplied,
276-
// for stream and non-stream calls alike, and that wrapper is what
277-
// closes the span. It is undefined only when there is no callback to
278-
// wrap, in which case the span is bound to the returned promise or
279-
// stream instead; the fallback keeps this correct either way.
280-
return invokeCall(request, callOptions, tracedCallback ?? callback);
281-
},
282-
isStreamingCall,
283-
callback,
284-
);
307+
let callExecution = (cb?: APICallback) =>
308+
invokeCall(request, callOptions, cb);
309+
310+
// Wrap with L3 terminal logging
311+
if (loggingEnabled) {
312+
const originalCallExecution = callExecution;
313+
callExecution = (cb?: APICallback) =>
314+
logCall(
315+
attemptDynamicArgs,
316+
staticArgs,
317+
loggedCallback => originalCallExecution(loggedCallback ?? cb),
318+
isStreamingCall,
319+
cb,
320+
);
321+
}
322+
323+
if (tracingEnabled) {
324+
const originalCallExecution = callExecution;
325+
callExecution = (cb?: APICallback) =>
326+
traceCall(
327+
dynamicArgs,
328+
staticArgs,
329+
(tracedCallback?: APICallback) => {
330+
// `traceCall` wraps the user's callback whenever one was supplied,
331+
// for stream and non-stream calls alike, and that wrapper is what
332+
// closes the span. It is undefined only when there is no callback to
333+
// wrap, in which case the span is bound to the returned promise or
334+
// stream instead; the fallback keeps this correct either way.
335+
return originalCallExecution(tracedCallback ?? cb);
336+
},
337+
isStreamingCall,
338+
cb,
339+
);
340+
}
341+
342+
return callExecution(callback);
285343
};
286344
} else {
287345
return invokeCall;

0 commit comments

Comments
 (0)