Skip to content

Commit

Permalink
add support for groovy and gmd
Browse files Browse the repository at this point in the history
  • Loading branch information
perNyfelt committed Feb 15, 2023
1 parent b183c14 commit 5008b68
Show file tree
Hide file tree
Showing 25 changed files with 2,777 additions and 52 deletions.
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
# Munin
This is a report server for reports created in R based on [Renjin](https://www.renjin.org/) and [Spring Boot](https://spring.io/projects/spring-boot).
This is a report server for reports created in either R based on [Renjin](https://www.renjin.org/) or Groovy
. It is an application on [Spring Boot](https://spring.io/projects/spring-boot).
The name comes from the one of Odin's ravens who he sent out every day to scout the world and bring him back reports.

![example report](docs/viewSampleReport.png)
# Overview
Munin is a reporting server that can run and display reports created in Renjin R on the web.
Munin is a reporting server that can run and display reports, created in Renjin R or Groovy, on the web.

Currently, it supports R reports where the R code returns html, or the mdr format (markdown with support for r code, similar to rmd - more on that further down).
Currently, it supports:
- R reports where the R code returns html
- mdr Reports (markdown with support for r code, similar to rmd - more on that further down).
- Groovy reports where the Groovy code returns html
- gmd Reports (markdown with support for groovy code - more on that further down)

Creating html from R code can be done by using the htmlcreator package for Renjin, e.g:
```r
Expand Down Expand Up @@ -189,6 +194,10 @@ Rmd requires knitr which depends on the Markdown package. The Markdown packages
the Renjin GCC bridge cannot make sense of. Hence, knitr and thus the rmd file format does not (currently)
work in Renjin. As soon as that is fixed, I plan to support rmd files in Munin as well.

# Groovy reports

# GMD reports

# Installing
There are a few different ways to install Munin.

Expand Down
24 changes: 18 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
<groupId>se.alipsa</groupId>
<version>1.2.2-SNAPSHOT</version>

<name>Munin - a Renjin based web reporting server</name>
<description>A reporting server based on Renjin and Spring Boot.</description>
<name>Munin - a web reporting server for R and Groovy</name>
<description>A reporting server for reports created in R or Groovy based on Spring Boot.</description>
<url>https://github.com/perNyfelt/munin</url>
<licenses>
<license>
Expand Down Expand Up @@ -51,8 +51,8 @@
<junit-jupiter.version>5.9.2</junit-jupiter.version>
<junit-platform.version>1.9.2</junit-platform.version>
<liquibase-core.version>4.19.0</liquibase-core.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<mdr.version>1.5.2</mdr.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
Expand Down Expand Up @@ -123,6 +123,17 @@
<artifactId>mdr</artifactId>
<version>${mdr.version}</version>
</dependency>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>4.0.9</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>se.alipsa.groovy</groupId>
<artifactId>gmd</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
Expand Down Expand Up @@ -242,6 +253,7 @@
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
Expand Down Expand Up @@ -341,9 +353,9 @@
<message>Please use maven version 3.5.2 or higher</message>
</requireMavenVersion>
<requireJavaVersion>
<version>1.8.0</version>
<version>17</version>
<level>WARN</level>
<message>Please use Java 8</message>
<message>Please use Java 17</message>
</requireJavaVersion>
</rules>
</configuration>
Expand Down
2 changes: 1 addition & 1 deletion src/bin/munin.service
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Example config file for a systemd service
[Unit]
Description=Munin, a reporting server based on Spring Boot and Renjin
Description=Munin, a reporting server based on Spring Boot for Renjin R and Groovy
After=network.target syslog.target

[Service]
Expand Down
25 changes: 8 additions & 17 deletions src/main/java/se/alipsa/munin/controller/ReportController.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@
import se.alipsa.munin.repo.ReportRepo;
import se.alipsa.munin.repo.ReportScheduleRepo;
import se.alipsa.munin.service.ReportDefinitionException;
import se.alipsa.munin.service.ReportEngine;
import se.alipsa.munin.service.RenjinReportEngine;
import se.alipsa.munin.service.ReportSchedulerService;
import se.alipsa.munin.service.ReportService;

import javax.script.ScriptException;
import java.util.*;
Expand All @@ -41,7 +42,8 @@ public class ReportController {
private static final Logger LOG = LoggerFactory.getLogger(ReportController.class);
private final ReportRepo reportRepo;
private final ReportScheduleRepo reportScheduleRepo;
private final ReportEngine reportEngine;

private final ReportService reportService;
private final ReportSchedulerService reportSchedulerService;
private final ReportScheduleWebFactory reportScheduleWebFactory;

Expand All @@ -50,12 +52,12 @@ public class ReportController {

@SuppressFBWarnings("EI_EXPOSE_REP2")
@Autowired
public ReportController(ReportRepo reportRepo, ReportScheduleRepo reportScheduleRepo, ReportEngine reportEngine,
public ReportController(ReportRepo reportRepo, ReportScheduleRepo reportScheduleRepo, ReportService reportService,
ReportSchedulerService reportSchedulerService, ReportScheduleWebFactory reportScheduleWebFactory,
@Qualifier("springCronParser") CronParser cronParser) {
this.reportRepo = reportRepo;
this.reportScheduleRepo = reportScheduleRepo;
this.reportEngine = reportEngine;
this.reportService = reportService;
this.reportSchedulerService = reportSchedulerService;
this.reportScheduleWebFactory = reportScheduleWebFactory;
this.cronParser = cronParser;
Expand All @@ -78,12 +80,7 @@ public String viewReport(@PathVariable String name, Model model) throws ReportNo
model.addAttribute("reportGroup", report.getReportGroup());
model.addAttribute("reportDescription", report.getDescription());
if (report.getInputContent() == null || report.getInputContent().trim().isEmpty()){
String reportContent;
if (ReportType.MDR.equals(report.getReportType())) {
reportContent = reportEngine.runMdrReport(report.getDefinition());
} else {
reportContent = reportEngine.runReport(report.getDefinition());
}
String reportContent = reportService.runReport(report);
model.addAttribute(report.getInputContent());
model.addAttribute("reportContent", reportContent);
return "viewReport";
Expand All @@ -108,13 +105,7 @@ public ModelAndView viewReport(@PathVariable String name, @RequestParam MultiVal
params.put(k, v);
}
});
String reportContent;

if (ReportType.MDR.equals(report.getReportType())) {
reportContent = reportEngine.runMdrReport(report.getDefinition(), params);
} else {
reportContent = reportEngine.runReport(report.getDefinition(), params);
}
String reportContent = reportService.runReport(report, params);
mav.addObject(report.getInputContent());
mav.addObject("reportContent", reportContent);
mav.setViewName("viewReport");
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/se/alipsa/munin/model/ReportType.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package se.alipsa.munin.model;

public enum ReportType {
UNMANAGED, MDR
R, MDR, GROOVY, GMD
}
42 changes: 42 additions & 0 deletions src/main/java/se/alipsa/munin/service/GroovyReportEngine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package se.alipsa.munin.service;

import groovy.lang.GroovyClassLoader;
import org.codehaus.groovy.jsr223.GroovyScriptEngineImpl;
import org.springframework.stereotype.Service;
import se.alipsa.groovy.gmd.Gmd;

import java.util.HashMap;
import java.util.Map;
import javax.script.ScriptContext;
import javax.script.ScriptException;

@Service
public class GroovyReportEngine {

GroovyScriptEngineImpl engine;

public GroovyReportEngine() {
GroovyClassLoader classLoader = new GroovyClassLoader();
engine = new GroovyScriptEngineImpl(classLoader);
}

public String runGroovyReport(String definition, Map<String, Object>... params) throws ScriptException {
try {
if (params.length > 0) {
engine.getBindings(ScriptContext.ENGINE_SCOPE).putAll(params[0]);
}
return String.valueOf(engine.eval(definition));
} finally {
engine.getBindings(ScriptContext.ENGINE_SCOPE).clear();
}
}

public String runGmdReport(String definition, Map<String, Object>... params) {
var gmd = new Gmd();
if (params.length == 0) {
return gmd.gmdToHtml(definition);
} else {
return gmd.gmdToHtml(definition, params[0]);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@
import java.util.Map;

@Service
public class ReportEngine {
public class RenjinReportEngine {


private final RenjinSessionEnginePool renjinSessionEnginePool;
private final EnvironmentUtil environmentUtil;

private static final Logger LOG = LoggerFactory.getLogger(ReportEngine.class);
private static final Logger LOG = LoggerFactory.getLogger(RenjinReportEngine.class);

@SuppressFBWarnings("EI_EXPOSE_REP2")
@Autowired
public ReportEngine(RenjinSessionEnginePool renjinSessionEnginePool, EnvironmentUtil environmentUtil) {
public RenjinReportEngine(RenjinSessionEnginePool renjinSessionEnginePool, EnvironmentUtil environmentUtil) {
this.renjinSessionEnginePool = renjinSessionEnginePool;
this.environmentUtil = environmentUtil;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ public class ReportSchedulerService implements
private final TaskScheduler executor;
private final ReportRepo reportRepo;
private final ReportScheduleRepo reportScheduleRepo;
private final ReportEngine reportEngine;
private final RenjinReportEngine reportEngine;
private final EmailService emailService;
private final Map<Long, ScheduledFuture<?>> currentSchedules = new HashMap<>();

private final static Logger LOG = LoggerFactory.getLogger(ReportSchedulerService.class);

@Autowired
public ReportSchedulerService(TaskScheduler executor, ReportRepo reportRepo, ReportScheduleRepo reportScheduleRepo, ReportEngine reportEngine,
public ReportSchedulerService(TaskScheduler executor, ReportRepo reportRepo, ReportScheduleRepo reportScheduleRepo, RenjinReportEngine reportEngine,
EmailService emailService) {
this.executor = executor;
this.reportRepo = reportRepo;
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/se/alipsa/munin/service/ReportService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package se.alipsa.munin.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import se.alipsa.munin.model.Report;

import java.util.Map;
import javax.script.ScriptException;

@Service
public class ReportService {

private final RenjinReportEngine renjinReportEngine;
private final GroovyReportEngine groovyReportEngine;

@Autowired
public ReportService(RenjinReportEngine renjinReportEngine, GroovyReportEngine groovyReportEngine) {
this.renjinReportEngine = renjinReportEngine;
this.groovyReportEngine = groovyReportEngine;
}
public String runReport(Report report, Map<String, Object>... params) throws ScriptException, ReportDefinitionException {
return switch (report.getReportType()) {
case R -> renjinReportEngine.runReport(report.getDefinition(), params);
case MDR -> renjinReportEngine.runMdrReport(report.getDefinition(), params);
case GROOVY -> groovyReportEngine.runGroovyReport(report.getDefinition(), params);
case GMD -> groovyReportEngine.runGmdReport(report.getDefinition(), params);
};
}
}
Loading

0 comments on commit 5008b68

Please sign in to comment.