Skip to content

Commit

Permalink
Fix stacktrace cutoff methods initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
Spikhalskiy committed Mar 16, 2023
1 parent ee86c34 commit 133e7f6
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import io.temporal.common.converter.DataConverter;
import io.temporal.common.converter.EncodedValues;
import io.temporal.common.converter.FailureConverter;
import io.temporal.internal.activity.ActivityTaskHandlerImpl;
import io.temporal.internal.sync.POJOWorkflowImplementationFactory;
import io.temporal.serviceclient.CheckedExceptionWrapper;
import java.io.PrintWriter;
import java.io.StringWriter;
Expand All @@ -61,12 +63,13 @@ public final class DefaultFailureConverter implements FailureConverter {

/**
* Stop emitting stack trace after this line. Makes serialized stack traces more readable and
* compact as it omits most of framework level code.
* compact as it omits most of framework-level code.
*/
private static final ImmutableSet<String> CUTOFF_METHOD_NAMES =
ImmutableSet.of(
"io.temporal.internal.worker.POJOActivityImplementationFactory$POJOActivityImplementation.execute",
"io.temporal.internal.sync.POJOWorkflowTaskHandler$POJOWorkflowImplementation.execute");
ImmutableSet.<String>builder()
.addAll(ActivityTaskHandlerImpl.ACTIVITY_HANDLER_STACKTRACE_CUTOFF)
.addAll(POJOWorkflowImplementationFactory.WORKFLOW_HANDLER_STACKTRACE_CUTOFF)
.build();

/** Used to parse a stack trace line. */
private static final Pattern TRACE_ELEMENT_PATTERN =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
package io.temporal.internal.activity;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.uber.m3.tally.Scope;
import com.uber.m3.util.ImmutableMap;
import io.temporal.activity.DynamicActivity;
Expand All @@ -35,6 +36,7 @@
import io.temporal.common.metadata.POJOActivityImplMetadata;
import io.temporal.common.metadata.POJOActivityMethodMetadata;
import io.temporal.internal.activity.ActivityTaskExecutors.ActivityTaskExecutor;
import io.temporal.internal.common.env.ReflectionUtils;
import io.temporal.internal.worker.ActivityTask;
import io.temporal.internal.worker.ActivityTaskHandler;
import io.temporal.serviceclient.MetricsTag;
Expand All @@ -46,6 +48,24 @@
import javax.annotation.Nullable;

public final class ActivityTaskHandlerImpl implements ActivityTaskHandler {
public static final ImmutableSet<String> ACTIVITY_HANDLER_STACKTRACE_CUTOFF =
ImmutableSet.<String>builder()
// POJO
.add(
ReflectionUtils.getMethodNameForStackTraceCutoff(
ActivityTaskExecutors.POJOActivityImplementation.class,
"execute",
ActivityInfoInternal.class,
Scope.class))
// Dynamic
.add(
ReflectionUtils.getMethodNameForStackTraceCutoff(
ActivityTaskExecutors.DynamicActivityImplementation.class,
"execute",
ActivityInfoInternal.class,
Scope.class))
.build();

private final DataConverter dataConverter;
private final String namespace;
private final String taskQueue;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2022 Temporal Technologies, Inc. All Rights Reserved.
*
* Copyright (C) 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Modifications copyright (C) 2017 Uber Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this material except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.temporal.internal.common.env;

import com.google.common.base.Joiner;

public final class ReflectionUtils {
private ReflectionUtils() {}

public static String getMethodNameForStackTraceCutoff(
Class<?> clazz, String methodName, Class<?>... parameterTypes) throws RuntimeException {
try {
return clazz.getName() + "." + clazz.getMethod(methodName, parameterTypes).getName();
} catch (NoSuchMethodException e) {
throw new RuntimeException(
"Reflection code that publishes the methods signatures is out of sync with actual method signatures. Class '"
+ clazz.getCanonicalName()
+ "' is expected to have method '"
+ methodName
+ "' with parameters {"
+ Joiner.on(", ").join(parameterTypes)
+ "}",
e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ public Optional<Payloads> execute(Header header, Optional<Payloads> input) {
return dataConverter.toPayloads(result.getResult());
}

private class RootWorkflowInboundCallsInterceptor
extends BaseRootWorkflowInboundCallsInterceptor {
class RootWorkflowInboundCallsInterceptor extends BaseRootWorkflowInboundCallsInterceptor {
private DynamicWorkflow workflow;

public RootWorkflowInboundCallsInterceptor(SyncWorkflowContext workflowContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import static io.temporal.serviceclient.CheckedExceptionWrapper.wrap;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import io.temporal.api.common.v1.Payloads;
import io.temporal.api.common.v1.WorkflowExecution;
import io.temporal.api.common.v1.WorkflowType;
Expand All @@ -36,6 +37,7 @@
import io.temporal.common.metadata.POJOWorkflowInterfaceMetadata;
import io.temporal.common.metadata.POJOWorkflowMethodMetadata;
import io.temporal.failure.CanceledFailure;
import io.temporal.internal.common.env.ReflectionUtils;
import io.temporal.internal.replay.ReplayWorkflow;
import io.temporal.internal.replay.ReplayWorkflowFactory;
import io.temporal.internal.worker.SingleWorkerOptions;
Expand All @@ -60,6 +62,20 @@
import org.slf4j.LoggerFactory;

public final class POJOWorkflowImplementationFactory implements ReplayWorkflowFactory {
public static final ImmutableSet<String> WORKFLOW_HANDLER_STACKTRACE_CUTOFF =
ImmutableSet.<String>builder()
// POJO
.add(
ReflectionUtils.getMethodNameForStackTraceCutoff(
POJOWorkflowImplementation.class, "execute", Header.class, Optional.class))
// Dynamic
.add(
ReflectionUtils.getMethodNameForStackTraceCutoff(
DynamicSyncWorkflowDefinition.RootWorkflowInboundCallsInterceptor.class,
"execute",
WorkflowInboundCallsInterceptor.WorkflowInput.class))
.build();

private static final Logger log =
LoggerFactory.getLogger(POJOWorkflowImplementationFactory.class);
private final WorkerInterceptor[] workerInterceptors;
Expand Down
16 changes: 16 additions & 0 deletions temporal-sdk/src/main/resources/temporal-sdk/reflect-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,21 @@
{
"name":"com.fasterxml.jackson.datatype.jsr310.JavaTimeModule",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"io.temporal.internal.activity.ActivityTaskExecutors$DynamicActivityImplementation",
"methods":[{"name":"execute","parameterTypes":["io.temporal.internal.activity.ActivityInfoInternal", "com.uber.m3.tally.Scope"] }]
},
{
"name":"io.temporal.internal.activity.ActivityTaskExecutors$POJOActivityImplementation",
"methods":[{"name":"execute","parameterTypes":["io.temporal.internal.activity.ActivityInfoInternal", "com.uber.m3.tally.Scope"] }]
},
{
"name":"io.temporal.internal.sync.POJOWorkflowImplementationFactory$POJOWorkflowImplementation",
"methods":[{"name":"execute","parameterTypes":["io.temporal.common.interceptors.Header", "java.util.Optional"] }]
},
{
"name":"io.temporal.internal.sync.DynamicSyncWorkflowDefinition$RootWorkflowInboundCallsInterceptor",
"methods":[{"name":"execute","parameterTypes":["io.temporal.common.interceptors.WorkflowInboundCallsInterceptor$WorkflowInput"] }]
}
]

0 comments on commit 133e7f6

Please sign in to comment.