Skip to content

Commit

Permalink
feat(app): import and show errors
Browse files Browse the repository at this point in the history
* import error records from Hazelcast
* show errors of a workflow instance in the detail view
* show a list of errors in the main view
  • Loading branch information
saig0 committed Mar 22, 2021
1 parent 7d5b11a commit 11ecafe
Show file tree
Hide file tree
Showing 10 changed files with 341 additions and 15 deletions.
94 changes: 94 additions & 0 deletions src/main/java/io/zeebe/monitor/entity/ErrorEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright © 2017 camunda services GmbH ([email protected])
*
* 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
*
* 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.zeebe.monitor.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;

@Entity(name = "ERROR")
public class ErrorEntity {

@Id
@Column(name = "POSITION_")
private long position;

@Column(name = "ERROR_EVENT_POSITION_")
private long errorEventPosition;

@Column(name = "WORKFLOW_INSTANCE_KEY_")
private long workflowInstanceKey;

@Column(name = "EXCEPTION_MESSAGE_")
@Lob
private String exceptionMessage;

@Column(name = "STACKTRACE_")
@Lob
private String stacktrace;

@Column(name = "TIMESTAMP_")
private long timestamp;

public long getPosition() {
return position;
}

public void setPosition(long position) {
this.position = position;
}

public long getErrorEventPosition() {
return errorEventPosition;
}

public void setErrorEventPosition(long errorEventPosition) {
this.errorEventPosition = errorEventPosition;
}

public long getWorkflowInstanceKey() {
return workflowInstanceKey;
}

public void setWorkflowInstanceKey(long workflowInstanceKey) {
this.workflowInstanceKey = workflowInstanceKey;
}

public String getExceptionMessage() {
return exceptionMessage;
}

public void setExceptionMessage(String exceptionMessage) {
this.exceptionMessage = exceptionMessage;
}

public String getStacktrace() {
return stacktrace;
}

public void setStacktrace(String stacktrace) {
this.stacktrace = stacktrace;
}

public long getTimestamp() {
return timestamp;
}

public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}
30 changes: 30 additions & 0 deletions src/main/java/io/zeebe/monitor/repository/ErrorRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright © 2017 camunda services GmbH ([email protected])
*
* 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
*
* 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.zeebe.monitor.repository;

import io.zeebe.monitor.entity.ErrorEntity;
import io.zeebe.monitor.entity.IncidentEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;

import java.util.List;

public interface ErrorRepository extends PagingAndSortingRepository<ErrorEntity, Long> {

List<ErrorEntity> findByWorkflowInstanceKey(long workflowInstanceKey);

}
59 changes: 59 additions & 0 deletions src/main/java/io/zeebe/monitor/rest/ErrorDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.zeebe.monitor.rest;

public final class ErrorDto {

private long position;
private long errorEventPosition;
private Long workflowInstanceKey;
private String exceptionMessage;
private String stacktrace;
private String timestamp;

public long getPosition() {
return position;
}

public void setPosition(long position) {
this.position = position;
}

public long getErrorEventPosition() {
return errorEventPosition;
}

public void setErrorEventPosition(long errorEventPosition) {
this.errorEventPosition = errorEventPosition;
}

public Long getWorkflowInstanceKey() {
return workflowInstanceKey;
}

public void setWorkflowInstanceKey(Long workflowInstanceKey) {
this.workflowInstanceKey = workflowInstanceKey;
}

public String getExceptionMessage() {
return exceptionMessage;
}

public void setExceptionMessage(String exceptionMessage) {
this.exceptionMessage = exceptionMessage;
}

public String getStacktrace() {
return stacktrace;
}

public void setStacktrace(String stacktrace) {
this.stacktrace = stacktrace;
}

public String getTimestamp() {
return timestamp;
}

public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
}
64 changes: 49 additions & 15 deletions src/main/java/io/zeebe/monitor/rest/ViewController.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import io.zeebe.model.bpmn.instance.zeebe.ZeebeTaskDefinition;
import io.zeebe.monitor.entity.ElementInstanceEntity;
import io.zeebe.monitor.entity.ElementInstanceStatistics;
import io.zeebe.monitor.entity.ErrorEntity;
import io.zeebe.monitor.entity.IncidentEntity;
import io.zeebe.monitor.entity.JobEntity;
import io.zeebe.monitor.entity.MessageEntity;
Expand All @@ -20,6 +21,7 @@
import io.zeebe.monitor.entity.WorkflowEntity;
import io.zeebe.monitor.entity.WorkflowInstanceEntity;
import io.zeebe.monitor.repository.ElementInstanceRepository;
import io.zeebe.monitor.repository.ErrorRepository;
import io.zeebe.monitor.repository.IncidentRepository;
import io.zeebe.monitor.repository.JobRepository;
import io.zeebe.monitor.repository.MessageRepository;
Expand Down Expand Up @@ -63,29 +65,20 @@ public class ViewController {
Arrays.asList(BpmnElementType.MULTI_INSTANCE_BODY.name());

private static final List<String> JOB_COMPLETED_INTENTS = Arrays.asList("completed", "canceled");

private final String base_path;
@Autowired private WorkflowRepository workflowRepository;

@Autowired private WorkflowInstanceRepository workflowInstanceRepository;

@Autowired private ElementInstanceRepository activityInstanceRepository;

@Autowired private IncidentRepository incidentRepository;

@Autowired private JobRepository jobRepository;

@Autowired private MessageRepository messageRepository;

@Autowired private MessageSubscriptionRepository messageSubscriptionRepository;

@Autowired private TimerRepository timerRepository;

@Autowired private VariableRepository variableRepository;

private final String base_path;
@Autowired private ErrorRepository errorRepository;

public ViewController(@Value("${server.servlet.context-path}") final String base_path) {
this.base_path = base_path.endsWith("/") ? base_path : base_path + "/";
this.base_path = base_path.endsWith("/") ? base_path : base_path + "/";
}

@GetMapping("/")
Expand Down Expand Up @@ -578,6 +571,12 @@ private WorkflowInstanceDto toInstanceDto(WorkflowInstanceEntity instance) {
.collect(Collectors.toList());
dto.setCalledWorkflowInstances(calledWorkflowInstances);

final var errors =
errorRepository.findByWorkflowInstanceKey(instance.getKey()).stream()
.map(this::toDto)
.collect(Collectors.toList());
dto.setErrors(errors);

return dto;
}

Expand Down Expand Up @@ -752,6 +751,26 @@ public String messageList(Map<String, Object> model, Pageable pageable) {
return "message-list-view";
}

@GetMapping("/views/errors")
public String errorList(Map<String, Object> model, Pageable pageable) {

final long count = errorRepository.count();

final List<ErrorDto> dtos = new ArrayList<>();
for (ErrorEntity entity : errorRepository.findAll(pageable)) {
final var dto = toDto(entity);
dtos.add(dto);
}

model.put("errors", dtos);
model.put("count", count);

addContextPathToModel(model);
addPaginationToModel(model, pageable, count);

return "error-list-view";
}

private MessageDto toDto(MessageEntity message) {
final MessageDto dto = new MessageDto();

Expand Down Expand Up @@ -801,6 +820,21 @@ private TimerDto toDto(TimerEntity timer) {
return dto;
}

private ErrorDto toDto(ErrorEntity entity) {
final var dto = new ErrorDto();
dto.setPosition(entity.getPosition());
dto.setErrorEventPosition(entity.getErrorEventPosition());
dto.setExceptionMessage(entity.getExceptionMessage());
dto.setStacktrace(entity.getStacktrace());
dto.setTimestamp(Instant.ofEpochMilli(entity.getTimestamp()).toString());

if (entity.getWorkflowInstanceKey() > 0) {
dto.setWorkflowInstanceKey(entity.getWorkflowInstanceKey());
}

return dto;
}

private void addPaginationToModel(
Map<String, Object> model, Pageable pageable, final long count) {

Expand All @@ -814,9 +848,9 @@ private void addPaginationToModel(
}
}

private void addContextPathToModel(Map<String, Object> model) {
model.put("context-path", base_path);
}
private void addContextPathToModel(Map<String, Object> model) {
model.put("context-path", base_path);
}

private static class VariableTuple {
private final long scopeKey;
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/io/zeebe/monitor/rest/WorkflowInstanceDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class WorkflowInstanceDto {
private List<MessageSubscriptionDto> messageSubscriptions = new ArrayList<>();
private List<TimerDto> timers = new ArrayList<>();
private List<CalledWorkflowInstanceDto> calledWorkflowInstances = new ArrayList<>();
private List<ErrorDto> errors = new ArrayList<>();

private List<BpmnElementInfo> bpmnElementInfos = new ArrayList<>();

Expand Down Expand Up @@ -250,4 +251,12 @@ public List<BpmnElementInfo> getBpmnElementInfos() {
public void setBpmnElementInfos(List<BpmnElementInfo> bpmnElementInfos) {
this.bpmnElementInfos = bpmnElementInfos;
}

public List<ErrorDto> getErrors() {
return errors;
}

public void setErrors(List<ErrorDto> errors) {
this.errors = errors;
}
}
27 changes: 27 additions & 0 deletions src/main/java/io/zeebe/monitor/zeebe/ZeebeImportService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.zeebe.exporter.proto.Schema;
import io.zeebe.hazelcast.connect.java.ZeebeHazelcast;
import io.zeebe.monitor.entity.ElementInstanceEntity;
import io.zeebe.monitor.entity.ErrorEntity;
import io.zeebe.monitor.entity.HazelcastConfig;
import io.zeebe.monitor.entity.IncidentEntity;
import io.zeebe.monitor.entity.JobEntity;
Expand All @@ -14,6 +15,7 @@
import io.zeebe.monitor.entity.WorkflowEntity;
import io.zeebe.monitor.entity.WorkflowInstanceEntity;
import io.zeebe.monitor.repository.ElementInstanceRepository;
import io.zeebe.monitor.repository.ErrorRepository;
import io.zeebe.monitor.repository.HazelcastConfigRepository;
import io.zeebe.monitor.repository.IncidentRepository;
import io.zeebe.monitor.repository.JobRepository;
Expand Down Expand Up @@ -52,6 +54,7 @@ public class ZeebeImportService {
@Autowired private MessageRepository messageRepository;
@Autowired private MessageSubscriptionRepository messageSubscriptionRepository;
@Autowired private TimerRepository timerRepository;
@Autowired private ErrorRepository errorRepository;

@Autowired private ZeebeNotificationService notificationService;

Expand Down Expand Up @@ -93,6 +96,7 @@ record -> withKey(record, Schema.TimerRecord::getMetadata, this::importTimer))
record -> withKey(record, Schema.MessageRecord::getMetadata, this::importMessage))
.addMessageSubscriptionListener(this::importMessageSubscription)
.addMessageStartEventSubscriptionListener(this::importMessageStartEventSubscription)
.addErrorListener(this::importError)
.postProcessListener(
sequence -> {
hazelcastConfig.setSequence(sequence);
Expand Down Expand Up @@ -414,6 +418,29 @@ private void importVariable(final Schema.VariableRecord record) {
}
}

private void importError(final Schema.ErrorRecord record) {

final var metadata = record.getMetadata();
final var position = metadata.getPosition();

final var entity =
errorRepository
.findById(position)
.orElseGet(
() -> {
final var newEntity = new ErrorEntity();
newEntity.setPosition(position);
newEntity.setErrorEventPosition(record.getErrorEventPosition());
newEntity.setWorkflowInstanceKey(record.getWorkflowInstanceKey());
newEntity.setExceptionMessage(record.getExceptionMessage());
newEntity.setStacktrace(record.getStacktrace());
newEntity.setTimestamp(metadata.getTimestamp());
return newEntity;
});

errorRepository.save(entity);
}

private String generateId() {
return UUID.randomUUID().toString();
}
Expand Down
Loading

0 comments on commit 11ecafe

Please sign in to comment.