Skip to content
Closed
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d96ba59
Created `report_result` table in the database.
milanmajchrak Jun 5, 2025
2044d2a
Created Java mapping for the ReportResult object with the CRUD operat…
milanmajchrak Jun 5, 2025
ea0358b
JSONified the InfoCheck and the result is stored to the ReportResult …
milanmajchrak Jun 5, 2025
356d3e7
Fetch the ReportResultService from the ContentServiceFactory
milanmajchrak Jun 5, 2025
6f294e3
Marked the report_result_id as PRIMARY KEY in the sql file.
milanmajchrak Jun 6, 2025
46256f3
Use CURRENT_TIMESTAMP as a default value for the last_modified
milanmajchrak Jun 6, 2025
52b85fe
h2 should have the defaut value for the `report_result_id`
milanmajchrak Jun 6, 2025
e65a9ac
Added doc to the report result service
milanmajchrak Jun 6, 2025
ada63d5
Updated doc in the report result service
milanmajchrak Jun 6, 2025
28a15ec
Make sure the current date is used in the timestamp when updating the…
milanmajchrak Jun 6, 2025
b7d0f83
Removed redundant `getID` method from the ReportResult
milanmajchrak Jun 6, 2025
f461963
Do not add the `URL: ` value to the url property in the InfoCheck
milanmajchrak Jun 6, 2025
74939b1
Format the date for the InfoCheck date time stamp
milanmajchrak Jun 6, 2025
e977a9c
Added HealthReport functionality to the Try Finally block to be sure …
milanmajchrak Jun 6, 2025
48c6fd3
Created sequence in the h2 database for the report result object.
milanmajchrak Jun 6, 2025
e900051
Fixed documentation in the psql for the report result.
milanmajchrak Jun 6, 2025
50c781a
Do not append string with `Url: ` two times..
milanmajchrak Jun 6, 2025
9d5a6ce
Fixed checkstyle
milanmajchrak Jun 6, 2025
d05bf5d
Fixed h2 sql definition - missing comma
milanmajchrak Jun 6, 2025
4454544
Added raw process for creating diff between two last result reports.
milanmajchrak Jun 6, 2025
fc2c62f
Working somehow, refactoring needed.
milanmajchrak Jun 10, 2025
b5e2872
Added Integration tests and fixed bugs.
milanmajchrak Jun 10, 2025
16c8d34
Refactored the code and fixed checkstyle issues
milanmajchrak Jun 11, 2025
cbbfaea
Use consistent DateFormat
milanmajchrak Jun 11, 2025
ac24df9
Updated description for the srcipt definition
milanmajchrak Jun 12, 2025
f1e6a8e
The test failed because not all scripts were returned because of pagi…
milanmajchrak Jun 12, 2025
4e42a99
UFAL/JSONificate Item Summary health reports (#986)
jr-rk Jul 9, 2025
fa0dfc7
UFAL/JSONificate User Summary health reports (#987)
jr-rk Jul 9, 2025
346e87f
UFAL/JSONificate License Summary health reports (#988)
jr-rk Jul 9, 2025
3a63fce
Use last two reports from DB when 'from' and 'to' are empty, add test
Paurikova2 Aug 6, 2025
ba10d17
Send an email about the report differences
Paurikova2 Aug 6, 2025
0f980fb
refactoring based on copilot and coderabbitai
Paurikova2 Aug 6, 2025
ba6eb2e
added limit for dates list
Paurikova2 Aug 6, 2025
551a270
review copilot
Paurikova2 Aug 6, 2025
bf3583e
fix incorrect limit specification
Paurikova2 Aug 12, 2025
380640f
fix log msgs
Paurikova2 Aug 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion dspace-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,12 @@
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>com.flipkart.zjsonpatch</groupId>
<artifactId>zjsonpatch</artifactId>
<version>0.4.6</version>
</dependency>

</dependencies>

<dependencyManagement>
Expand Down
149 changes: 111 additions & 38 deletions dspace-api/src/main/java/org/dspace/app/healthreport/HealthReport.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@
import java.util.Map;
import javax.mail.MessagingException;

import org.apache.commons.cli.Option;
import org.apache.commons.cli.ParseException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.content.ReportResult;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.ReportResultService;
import org.dspace.core.Context;
import org.dspace.core.Email;
import org.dspace.core.I18nUtil;
Expand All @@ -34,6 +38,8 @@
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.utils.DSpace;
import org.json.JSONArray;
import org.json.JSONObject;

/**
* This class is used to generate a health report of the DSpace instance.
Expand All @@ -44,6 +50,7 @@ public class HealthReport extends DSpaceRunnable<HealthReportScriptConfiguration
private static final Logger log = LogManager.getLogger(HealthReport.class);

private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
private ReportResultService reportResultService = ContentServiceFactory.getInstance().getReportResultService();
private EPersonService ePersonService;

/**
Expand Down Expand Up @@ -136,56 +143,82 @@ public void internalRun() throws Exception {
return;
}

ReportInfo ri = new ReportInfo(this.forLastNDays);
try (Context context = new Context()) {
context.setCurrentUser(ePersonService.find(context, this.getEpersonIdentifier()));

StringBuilder sbReport = new StringBuilder();
sbReport.append("\n\nHEALTH REPORT:\n");
ReportInfo ri = new ReportInfo(this.forLastNDays);

int position = -1;
for (Map.Entry<String, Check> check_entry : Report.checks().entrySet()) {
++position;
if (specificCheck != -1 && specificCheck != position) {
continue;
}
StringBuilder sbReport = new StringBuilder();
sbReport.append("\n\nHEALTH REPORT:\n");

String name = check_entry.getKey();
Check check = check_entry.getValue();
int position = -1;
JSONObject root = new JSONObject();
// Create the array
JSONArray checksArray = new JSONArray();
for (Map.Entry<String, Check> check_entry : Report.checks().entrySet()) {
++position;
if (specificCheck != -1 && specificCheck != position) {
continue;
}

log.info("#{}. Processing [{}] at [{}]", position, name, new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
String name = check_entry.getKey();
Check check = check_entry.getValue();

sbReport.append("\n######################\n\n").append(name).append(":\n");
check.report(ri);
sbReport.append(check.getReport());
}
log.info("#{}. Processing [{}] at [{}]", position, name, new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));

// save output to file
if (fileName != null) {
Context context = new Context();
context.setCurrentUser(ePersonService.find(context, this.getEpersonIdentifier()));
sbReport.append("\n######################\n\n").append(name).append(":\n");
check.report(ri);
sbReport.append(check.getReport());

InputStream inputStream = toInputStream(sbReport.toString(), StandardCharsets.UTF_8);
handler.writeFilestream(context, fileName, inputStream, "export");
// JSON:
// Check name: {Report}
JSONObject report = check.getReportJson(); // assume check is already defined

context.restoreAuthSystemState();
context.complete();
}
JSONObject checkJson = new JSONObject();
checkJson.put("name", name);
checkJson.put("report", report);
// Add items to array
checksArray.put(checkJson);
}

// send email to email address from argument
if (emails != null && emails.length > 0) {
try {
Email e = Email.getEmail(I18nUtil.getEmailFilename(Locale.getDefault(), "healthcheck"));
for (String recipient : emails) {
e.addRecipient(recipient);
// Add array to root object under a key "checks"
root.put("checks", checksArray);

// Add health report summary to the ReportResult object
ReportResult reportResult = reportResultService.create(context);
reportResult.setArgs(printCommandlineOptions());
reportResult.setExecutor(context.getCurrentUser());
reportResult.setType("healthcheck");
reportResult.setValue(root.toString());
reportResultService.update(context, reportResult);
context.commit();

// save output to file
if (fileName != null) {
InputStream inputStream = toInputStream(sbReport.toString(), StandardCharsets.UTF_8);
handler.writeFilestream(context, fileName, inputStream, "export");

context.restoreAuthSystemState();

}

// send email to email address from argument
if (emails != null && emails.length > 0) {
try {
Email e = Email.getEmail(I18nUtil.getEmailFilename(Locale.getDefault(), "healthcheck"));
for (String recipient : emails) {
e.addRecipient(recipient);
}
e.addArgument(sbReport.toString());
e.send();
} catch (IOException | MessagingException e) {
log.error("Error sending email:", e);
}
e.addArgument(sbReport.toString());
e.send();
} catch (IOException | MessagingException e) {
log.error("Error sending email:", e);
}
}

handler.logInfo(sbReport.toString());
handler.logInfo(sbReport.toString());
}
}

@Override
Expand All @@ -201,6 +234,25 @@ public void printHelp() {
);
}

/**
* Print command line options in a readable format.
* This method is used to print the options used for the report.
*/
private String printCommandlineOptions() {
// Return key-value pairs of options
StringBuilder options = new StringBuilder();
for (Option option : commandLine.getOptions()) {
String key = option.getOpt();
String value = commandLine.getOptionValue(key);
if (value != null) {
options.append(String.format(" -%s: %s\n", key, value));
} else {
options.append(String.format(" -%s\n", key));
}
}
return options.toString();
}

Comment thread
milanmajchrak marked this conversation as resolved.
/**
* Convert checks names to string.
*/
Expand All @@ -219,4 +271,25 @@ private String checksNamesToString() {
public static int getNumberOfChecks() {
return checks.size();
}

/**
* Get the name of a specific check by its index.
* This is used for the `-c` option.
*
* @param specificCheck the index of the check
* @return the name of the check, or null if the index is invalid
*/
public static String getCheckName(int specificCheck) {
if (specificCheck < 0 || specificCheck >= getNumberOfChecks()) {
return null;
}
int pos = 0;
for (String name : checks.keySet()) {
if (pos == specificCheck) {
return name;
}
pos++;
}
return null; // should not happen
}
}
Loading