Bug
In SimpleFunctionRegistry.FunctionInvocationWrapper.apply(), the FunctionInvocationWrapper.wrapped flag is set to true before delegating to doApply() (to prevent re-entrant wrapping). It is reset to false afterwards — but not in a finally block:
Object result = this.doApply(input, targetFunction);
targetFunction.wrapped = false; // ← skipped if doApply throws
return result;
When a function invocation throws, wrapped stays true forever. Every subsequent message finds wrapped = true and bypasses the ObservationFunctionAroundWrapper entirely.
This means ObservationFunctionAroundWrapper — and therefore the spring_cloud_function_seconds Micrometer timer — only records the very first message invocation which leads to an error. Every subsequent message bypasses the observation entirely.
Symptom
spring_cloud_function_seconds_count with an error is permanently stuck at 1 regardless of how many more messages result in an error. Confirmed with OTLP cumulative temporality (default), no pod restarts.
Expected behaviour
spring_cloud_function_seconds_count increments on every function invocation which leads to an error.
Actual behaviour
spring_cloud_function_seconds_count is always 1 after the first invocation which led to an error — further invocations are not observed.
Versions
spring-cloud-function-context:4.3.0
- Also confirmed present in
main branch (same lines 622–623 in SimpleFunctionRegistry.java)
Suggested fix
Reset this.wrapped = false after the wrapper call returns, e.g. in a finally block:
this.wrapped = true;
try {
result = functionAroundWrapper.apply(input, this);
}
finally {
this.wrapped = false;
}
}
Bug
In
SimpleFunctionRegistry.FunctionInvocationWrapper.apply(), theFunctionInvocationWrapper.wrappedflag is set totruebefore delegating todoApply()(to prevent re-entrant wrapping). It is reset tofalseafterwards — but not in afinallyblock:When a function invocation throws,
wrappedstaystrueforever. Every subsequent message findswrapped = trueand bypasses theObservationFunctionAroundWrapperentirely.This means
ObservationFunctionAroundWrapper— and therefore thespring_cloud_function_secondsMicrometer timer — only records the very first message invocation which leads to an error. Every subsequent message bypasses the observation entirely.Symptom
spring_cloud_function_seconds_countwith an error is permanently stuck at1regardless of how many more messages result in an error. Confirmed with OTLP cumulative temporality (default), no pod restarts.Expected behaviour
spring_cloud_function_seconds_countincrements on every function invocation which leads to an error.Actual behaviour
spring_cloud_function_seconds_countis always1after the first invocation which led to an error — further invocations are not observed.Versions
spring-cloud-function-context:4.3.0mainbranch (same lines 622–623 inSimpleFunctionRegistry.java)Suggested fix
Reset
this.wrapped = falseafter the wrapper call returns, e.g. in afinallyblock: