001/*
002 * Copyright 2025 devteam@scivics-lab.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing,
011 * software distributed under the License is distributed on an
012 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied.  See the License for the
014 * specific language governing permissions and limitations
015 * under the License.
016 */
017
018package com.scivicslab.actoriac.log;
019
020import java.time.Duration;
021import java.time.LocalDateTime;
022import java.util.List;
023
024/**
025 * Summary of a workflow execution session.
026 *
027 * @author devteam@scivics-lab.com
028 */
029public class SessionSummary {
030    private final long sessionId;
031    private final String workflowName;
032    private final String overlayName;
033    private final String inventoryName;
034    private final LocalDateTime startedAt;
035    private final LocalDateTime endedAt;
036    private final int nodeCount;
037    private final SessionStatus status;
038    private final int successCount;
039    private final int failedCount;
040    private final List<String> failedNodes;
041    private final int totalLogEntries;
042    private final int errorCount;
043
044    public SessionSummary(long sessionId, String workflowName, String overlayName,
045                          String inventoryName, LocalDateTime startedAt,
046                          LocalDateTime endedAt, int nodeCount, SessionStatus status,
047                          int successCount, int failedCount, List<String> failedNodes,
048                          int totalLogEntries, int errorCount) {
049        this.sessionId = sessionId;
050        this.workflowName = workflowName;
051        this.overlayName = overlayName;
052        this.inventoryName = inventoryName;
053        this.startedAt = startedAt;
054        this.endedAt = endedAt;
055        this.nodeCount = nodeCount;
056        this.status = status;
057        this.successCount = successCount;
058        this.failedCount = failedCount;
059        this.failedNodes = failedNodes;
060        this.totalLogEntries = totalLogEntries;
061        this.errorCount = errorCount;
062    }
063
064    public long getSessionId() { return sessionId; }
065    public String getWorkflowName() { return workflowName; }
066    public String getOverlayName() { return overlayName; }
067    public String getInventoryName() { return inventoryName; }
068    public LocalDateTime getStartedAt() { return startedAt; }
069    public LocalDateTime getEndedAt() { return endedAt; }
070    public int getNodeCount() { return nodeCount; }
071    public SessionStatus getStatus() { return status; }
072    public int getSuccessCount() { return successCount; }
073    public int getFailedCount() { return failedCount; }
074    public List<String> getFailedNodes() { return failedNodes; }
075    public int getTotalLogEntries() { return totalLogEntries; }
076    public int getErrorCount() { return errorCount; }
077
078    public Duration getDuration() {
079        if (startedAt == null || endedAt == null) {
080            return Duration.ZERO;
081        }
082        return Duration.between(startedAt, endedAt);
083    }
084
085    @Override
086    public String toString() {
087        StringBuilder sb = new StringBuilder();
088        sb.append("Session #").append(sessionId).append(": ").append(workflowName).append("\n");
089        if (overlayName != null) {
090            sb.append("  Overlay:  ").append(overlayName).append("\n");
091        }
092        if (inventoryName != null) {
093            sb.append("  Inventory: ").append(inventoryName).append("\n");
094        }
095        sb.append("  Started:  ").append(startedAt != null ? startedAt.toString().replace("T", " ") : "N/A").append("\n");
096        sb.append("  Ended:    ").append(endedAt != null ? endedAt.toString().replace("T", " ") : "N/A").append("\n");
097
098        Duration d = getDuration();
099        if (!d.isZero()) {
100            long minutes = d.toMinutes();
101            long seconds = d.toSecondsPart();
102            sb.append("  Duration: ").append(minutes).append("m ").append(seconds).append("s\n");
103        }
104
105        sb.append("  Nodes:    ").append(nodeCount).append("\n");
106        sb.append("  Status:   ").append(status).append("\n");
107        sb.append("\n");
108        sb.append("  Results:\n");
109        sb.append("    SUCCESS: ").append(successCount).append(" nodes\n");
110        sb.append("    FAILED:  ").append(failedCount).append(" nodes");
111        if (failedNodes != null && !failedNodes.isEmpty()) {
112            sb.append(" (").append(String.join(", ", failedNodes)).append(")");
113        }
114        sb.append("\n");
115        sb.append("\n");
116        sb.append("  Log entries: ").append(totalLogEntries).append(" (").append(errorCount).append(" errors)");
117        return sb.toString();
118    }
119}