) method -> AnnotationUtils.findAnnotation(method,
annotationClass));
}
}
}
================================================
FILE: spring-cloud-task-core/src/main/java/org/springframework/cloud/task/listener/TaskObservations.java
================================================
/*
* Copyright 2019-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 org.springframework.cloud.task.listener;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationConvention;
import io.micrometer.observation.ObservationRegistry;
import org.springframework.cloud.task.configuration.TaskObservationCloudKeyValues;
import org.springframework.cloud.task.repository.TaskExecution;
/**
* Utility class for publishing Spring Cloud Task specific Observations via Micrometer.
* Intended for internal use only.
*
* @author Christian Tzolov
* @author Glenn Renfro
* @since 2.2
*/
public class TaskObservations {
/**
* Successful task execution status indicator.
*/
public static final String STATUS_SUCCESS = "success";
/**
* Failing task execution status indicator.
*/
public static final String STATUS_FAILURE = "failure";
/**
* Default for when value is not present.
*/
public static final String UNKNOWN = "unknown";
private ObservationRegistry observationRegistry;
private ObservationConvention customObservationConvention;
public TaskObservations(ObservationRegistry observationRegistry,
TaskObservationCloudKeyValues taskObservationCloudKeyValues,
ObservationConvention customObservationConvention) {
this.observationRegistry = observationRegistry;
this.taskObservationCloudKeyValues = taskObservationCloudKeyValues;
this.customObservationConvention = customObservationConvention;
}
private Observation.Scope scope;
private TaskExecutionObservationConvention observationsProvider = new DefaultTaskExecutionObservationConvention();
private TaskExecutionObservationContext taskObservationContext;
TaskObservationCloudKeyValues taskObservationCloudKeyValues;
public void onTaskStartup(TaskExecution taskExecution) {
this.taskObservationContext = new TaskExecutionObservationContext(taskExecution);
Observation observation = TaskExecutionObservation.TASK_ACTIVE
.observation(this.customObservationConvention, new DefaultTaskExecutionObservationConvention(),
this.taskObservationContext, this.observationRegistry)
.contextualName(String.valueOf(taskExecution.getExecutionId()))
.observationConvention(this.observationsProvider)
.lowCardinalityKeyValue(TaskExecutionObservation.TaskKeyValues.TASK_NAME.asString(),
getValueOrDefault(taskExecution.getTaskName()))
.lowCardinalityKeyValue(TaskExecutionObservation.TaskKeyValues.TASK_EXECUTION_ID.asString(),
"" + taskExecution.getExecutionId())
.lowCardinalityKeyValue(TaskExecutionObservation.TaskKeyValues.TASK_PARENT_EXECUTION_ID.asString(),
(getValueOrDefault(taskExecution.getParentExecutionId())))
.lowCardinalityKeyValue(TaskExecutionObservation.TaskKeyValues.TASK_EXTERNAL_EXECUTION_ID.asString(),
(getValueOrDefault(taskExecution.getExternalExecutionId())));
if (taskObservationCloudKeyValues != null) {
observation.lowCardinalityKeyValue(TaskExecutionObservation.TaskKeyValues.TASK_CF_ORG_NAME.asString(),
this.taskObservationCloudKeyValues.getOrganizationName());
observation.lowCardinalityKeyValue(TaskExecutionObservation.TaskKeyValues.TASK_CF_SPACE_ID.asString(),
this.taskObservationCloudKeyValues.getSpaceId());
observation.lowCardinalityKeyValue(TaskExecutionObservation.TaskKeyValues.TASK_CF_SPACE_NAME.asString(),
this.taskObservationCloudKeyValues.getSpaceName());
observation.lowCardinalityKeyValue(TaskExecutionObservation.TaskKeyValues.TASK_CF_APP_ID.asString(),
this.taskObservationCloudKeyValues.getApplicationId());
observation.lowCardinalityKeyValue(TaskExecutionObservation.TaskKeyValues.TASK_CF_APP_NAME.asString(),
this.taskObservationCloudKeyValues.getApplicationName());
observation.lowCardinalityKeyValue(TaskExecutionObservation.TaskKeyValues.TASK_CF_APP_VERSION.asString(),
this.taskObservationCloudKeyValues.getApplicationVersion());
observation.lowCardinalityKeyValue(TaskExecutionObservation.TaskKeyValues.TASK_CF_INSTANCE_INDEX.asString(),
this.taskObservationCloudKeyValues.getInstanceIndex());
}
observation.start();
this.scope = observation.openScope();
}
private String getValueOrDefault(Object value) {
return (value != null) ? value.toString() : UNKNOWN;
}
public void onTaskFailed(Throwable throwable) {
this.taskObservationContext.setStatus(STATUS_FAILURE);
this.scope.getCurrentObservation().error(throwable);
}
public void onTaskEnd(TaskExecution taskExecution) {
if (this.scope != null) {
this.taskObservationContext.getTaskExecution().setExitCode(taskExecution.getExitCode());
this.scope.close();
this.scope.getCurrentObservation().stop();
}
}
}
================================================
FILE: spring-cloud-task-core/src/main/java/org/springframework/cloud/task/listener/annotation/AfterTask.java
================================================
/*
* Copyright 2016-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 org.springframework.cloud.task.listener.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.aot.hint.annotation.Reflective;
import org.springframework.cloud.task.listener.TaskExecutionListener;
import org.springframework.cloud.task.repository.TaskExecution;
/**
*
* {@link TaskExecutionListener#onTaskEnd(TaskExecution)}.
*
*
*
* public class MyListener {
* @AfterTask
* public void doSomething(TaskExecution taskExecution) {
* }
* }
*
*
* @author Glenn Renfro
*/
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Reflective
public @interface AfterTask {
}
================================================
FILE: spring-cloud-task-core/src/main/java/org/springframework/cloud/task/listener/annotation/BeforeTask.java
================================================
/*
* Copyright 2016-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 org.springframework.cloud.task.listener.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.aot.hint.annotation.Reflective;
import org.springframework.cloud.task.listener.TaskExecutionListener;
import org.springframework.cloud.task.repository.TaskExecution;
/**
*
* {@link TaskExecutionListener#onTaskStartup(TaskExecution)}.
*
*
*
* public class MyListener {
* @BeforeTask
* public void doSomething(TaskExecution taskExecution) {
* }
* }
*
*
* @author Glenn Renfro
*/
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Reflective
public @interface BeforeTask {
}
================================================
FILE: spring-cloud-task-core/src/main/java/org/springframework/cloud/task/listener/annotation/FailedTask.java
================================================
/*
* Copyright 2016-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 org.springframework.cloud.task.listener.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.aot.hint.annotation.Reflective;
import org.springframework.cloud.task.listener.TaskExecutionListener;
import org.springframework.cloud.task.repository.TaskExecution;
/**
*
* {@link TaskExecutionListener#onTaskFailed(TaskExecution, Throwable)}.
*
*
*
* public class MyListener {
* @FailedTask
* public void doSomething(TaskExecution taskExecution, Throwable throwable) {
* }
* }
*
*
* @author Glenn Renfro
*/
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Reflective
public @interface FailedTask {
}
================================================
FILE: spring-cloud-task-core/src/main/java/org/springframework/cloud/task/listener/annotation/TaskListenerExecutor.java
================================================
/*
* Copyright 2016-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 org.springframework.cloud.task.listener.annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import org.springframework.cloud.task.listener.TaskExecutionException;
import org.springframework.cloud.task.listener.TaskExecutionListener;
import org.springframework.cloud.task.repository.TaskExecution;
/**
* Identifies all beans that contain a TaskExecutionListener annotation and stores the
* associated method so that it can be called by the {@link TaskExecutionListener} at the
* appropriate time.
*
* @author Glenn Renfro
* @author Isik Erhan
*/
public class TaskListenerExecutor implements TaskExecutionListener {
private Map> beforeTaskInstances;
private Map> afterTaskInstances;
private Map> failedTaskInstances;
public TaskListenerExecutor(Map> beforeTaskInstances,
Map> afterTaskInstances, Map> failedTaskInstances) {
this.beforeTaskInstances = beforeTaskInstances;
this.afterTaskInstances = afterTaskInstances;
this.failedTaskInstances = failedTaskInstances;
}
/**
* Executes all the methods that have been annotated with @BeforeTask.
* @param taskExecution associated with the event.
*/
@Override
public void onTaskStartup(TaskExecution taskExecution) {
executeTaskListener(taskExecution, this.beforeTaskInstances.keySet(), this.beforeTaskInstances);
}
/**
* Executes all the methods that have been annotated with @AfterTask.
* @param taskExecution associated with the event.
*/
@Override
public void onTaskEnd(TaskExecution taskExecution) {
executeTaskListener(taskExecution, this.afterTaskInstances.keySet(), this.afterTaskInstances);
}
/**
* Executes all the methods that have been annotated with @FailedTask.
* @param throwable that was not caught for the task execution.
* @param taskExecution associated with the event.
*/
@Override
public void onTaskFailed(TaskExecution taskExecution, Throwable throwable) {
executeTaskListenerWithThrowable(taskExecution, throwable, this.failedTaskInstances.keySet(),
this.failedTaskInstances);
}
private void executeTaskListener(TaskExecution taskExecution, Set methods,
Map> instances) {
for (Method method : methods) {
for (Object instance : instances.get(method)) {
try {
method.invoke(instance, taskExecution);
}
catch (IllegalAccessException e) {
throw new TaskExecutionException("@BeforeTask and @AfterTask annotated methods must be public.", e);
}
catch (InvocationTargetException e) {
throw new TaskExecutionException(
String.format("Failed to process @BeforeTask or @AfterTask" + " annotation because: %s",
e.getTargetException().getMessage()),
e);
}
catch (IllegalArgumentException e) {
throw new TaskExecutionException(
"taskExecution parameter " + "is required for @BeforeTask and @AfterTask annotated methods",
e);
}
}
}
}
private void executeTaskListenerWithThrowable(TaskExecution taskExecution, Throwable throwable, Set methods,
Map> instances) {
for (Method method : methods) {
for (Object instance : instances.get(method)) {
try {
method.invoke(instance, taskExecution, throwable);
}
catch (IllegalAccessException e) {
throw new TaskExecutionException("@FailedTask annotated methods must be public.", e);
}
catch (InvocationTargetException e) {
throw new TaskExecutionException(
String.format("Failed to process @FailedTask " + "annotation because: %s",
e.getTargetException().getMessage()),
e);
}
catch (IllegalArgumentException e) {
throw new TaskExecutionException("taskExecution and throwable parameters "
+ "are required for @FailedTask annotated methods", e);
}
}
}
}
}
================================================
FILE: spring-cloud-task-core/src/main/java/org/springframework/cloud/task/listener/annotation/package-info.java
================================================
/*
* Copyright 2015-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.
*/
/**
* Annotation-based listener support for Spring Cloud Task.
*/
package org.springframework.cloud.task.listener.annotation;
================================================
FILE: spring-cloud-task-core/src/main/java/org/springframework/cloud/task/listener/package-info.java
================================================
/*
* Copyright 2015-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.
*/
/**
* Task lifecycle listener support for Spring Cloud Task.
*/
package org.springframework.cloud.task.listener;
================================================
FILE: spring-cloud-task-core/src/main/java/org/springframework/cloud/task/package-info.java
================================================
/*
* Copyright 2015-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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.
*/
/**
* Base package for spring cloud task.
*/
package org.springframework.cloud.task;
================================================
FILE: spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/TaskExecution.java
================================================
/*
* Copyright 2015-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://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 org.springframework.cloud.task.repository;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import org.springframework.util.Assert;
/**
* Represents the state of the Task for each execution.
*
* @author Glenn Renfro
* @author Michael Minella
* @author Ilayaperumal Gopinathan
*/
public class TaskExecution {
/**
* The unique id associated with the task execution.
*/
private long executionId;
/**
* The parent task execution id.
*/
private Long parentExecutionId;
/**
* The recorded exit code for the task.
*/
private Integer exitCode;
/**
* User defined name for the task.
*/
private String taskName;
/**
* Time of when the task was started.
*/
private LocalDateTime startTime;
/**
* Timestamp of when the task was completed/terminated.
*/
private LocalDateTime endTime;
/**
* Message returned from the task or stacktrace.
*/
private String exitMessage;
/**
* Id assigned to the task by the platform.
*
* @since 1.1.0
*/
private String externalExecutionId;
/**
* Error information available upon the failure of a task.
*
* @since 1.1.0
*/
private String errorMessage;
/**
* The arguments that were used for this task execution.
*/
private List arguments;
public TaskExecution() {
this.arguments = new ArrayList<>();
}
public TaskExecution(long executionId, Integer exitCode, String taskName, LocalDateTime startTime,
LocalDateTime endTime, String exitMessage, List arguments, String errorMessage,
String externalExecutionId, Long parentExecutionId) {
Assert.notNull(arguments, "arguments must not be null");
this.executionId = executionId;
this.exitCode = exitCode;
this.taskName = taskName;
this.exitMessage = exitMessage;
this.arguments = new ArrayList<>(arguments);
this.startTime = startTime;
this.endTime = endTime;
this.errorMessage = errorMessage;
this.externalExecutionId = externalExecutionId;
this.parentExecutionId = parentExecutionId;
}
public TaskExecution(long executionId, Integer exitCode, String taskName, LocalDateTime startTime,
LocalDateTime endTime, String exitMessage, List arguments, String errorMessage,
String externalExecutionId) {
this(executionId, exitCode, taskName, startTime, endTime, exitMessage, arguments, errorMessage,
externalExecutionId, null);
}
public long getExecutionId() {
return this.executionId;
}
public Integer getExitCode() {
return this.exitCode;
}
public void setExitCode(Integer exitCode) {
this.exitCode = exitCode;
}
public String getTaskName() {
return this.taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
public LocalDateTime getStartTime() {
return this.startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return this.endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
public String getExitMessage() {
return this.exitMessage;
}
public void setExitMessage(String exitMessage) {
this.exitMessage = exitMessage;
}
public List