Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Binary file added .DS_Store
Binary file not shown.
17 changes: 17 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.2</version>
<relativePath></relativePath>
</parent>
<groupId>org.onedatashare</groupId>
<artifactId>ods-metadata</artifactId>
Expand Down Expand Up @@ -95,6 +96,22 @@
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>8.0.3</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import com.google.common.base.Preconditions;
import lombok.extern.slf4j.Slf4j;
import org.onedatashare.odsmetadata.mapper.BatchJobMapper;
import org.onedatashare.odsmetadata.model.*;
import org.onedatashare.odsmetadata.services.InfluxIOService;
import org.onedatashare.odsmetadata.services.JobService;
import org.onedatashare.odsmetadata.services.ReportService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
Expand Down Expand Up @@ -33,9 +35,15 @@ public class BatchJobController {

InfluxIOService influxIOService;

public BatchJobController(JobService jobService, InfluxIOService influxIOService) {
ReportService reportService;

private BatchJobMapper mapper;

public BatchJobController(JobService jobService, InfluxIOService influxIOService,
ReportService reportService) {
this.jobService = jobService;
this.influxIOService = influxIOService;
this.reportService = reportService;
}

private static final String REGEX_PATTERN = "^(?=.{1,64}@)[A-Za-z0-9_-]+(\\.[A-Za-z0-9_-]+)*@"
Expand Down Expand Up @@ -259,4 +267,17 @@ public TransferSummary jobMonitor(@RequestParam String userEmail, @RequestParam
summary.setTransferStatus(jobData.getStatus());
return summary;
}

@GetMapping("/stats/report")
public String createPDF(@RequestParam String userEmail, @RequestParam Long jobId){
String result = "Report generation failed";
try {
if (String.valueOf(jobId).matches(REGEX) && validateUserEmail(userEmail)) {
result = reportService.createPDF(userEmail, jobId);
}
} catch (Exception E){
return E.toString();
}
return result;
}
}
240 changes: 240 additions & 0 deletions src/main/java/org/onedatashare/odsmetadata/services/ChartService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
package org.onedatashare.odsmetadata.services;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.onedatashare.odsmetadata.model.InfluxData;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.DoubleSummaryStatistics;
import java.util.List;
import java.util.function.ToDoubleFunction;

@Service
public class ChartService {

public byte[] createThroughputCharts(List<InfluxData> dataList) throws IOException {
JFreeChart readChart = createSummaryChart(dataList,
"Read Throughput", InfluxData::getReadThroughput);
JFreeChart writeChart = createSummaryChart(dataList,
"Write Throughput", InfluxData::getWriteThroughput);

int chartWidth = 450;
int chartHeight = 300;
BufferedImage combinedImage = combineChartsIntoGrid(new JFreeChart[]{readChart, writeChart}, 1, 2, chartWidth, chartHeight);
combinedImage = resize(combinedImage, 500, 250);

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(combinedImage, "png", outputStream);
return outputStream.toByteArray();
}

public byte[] createThroughputTimeCharts(List<InfluxData> dataList) throws IOException {
JFreeChart readThroughputChart = getThroughputChart(dataList, "Read Throughput Over Time", InfluxData::getReadThroughput);
JFreeChart writeThroughputChart = getThroughputChart(dataList, "Write Throughput Over Time", InfluxData::getWriteThroughput);

int chartWidth = 500;
int chartHeight = 300;
BufferedImage combinedImage = combineChartsIntoGrid(new JFreeChart[]{readThroughputChart, writeThroughputChart}, 1, 2, chartWidth, chartHeight);
combinedImage = resize(combinedImage, 500, 180);

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(combinedImage, "png", outputStream);
return outputStream.toByteArray();
}

public byte[] createMemoryCharts(List<InfluxData> dataList) throws IOException {
JFreeChart memoryChart = getMemoryChart(dataList,
"Memory Usage", InfluxData::getMemory);
JFreeChart freeMemoryChart = getMemoryChart(dataList,
"Free Memory", InfluxData::getFreeMemory);
JFreeChart maxMemoryChart = getMemoryChart(dataList,
"Max Memory", InfluxData::getMaxMemory);
JFreeChart allocatedMemoryChart = getMemoryChart(dataList,
"Allocated Memory", InfluxData::getAllocatedMemory);

int chartWidth = 500; // Adjust as needed
int chartHeight = 280; // Adjust as needed
BufferedImage combinedImage = combineChartsIntoGrid(new JFreeChart[]{memoryChart,
freeMemoryChart, maxMemoryChart, allocatedMemoryChart},
2, 2, chartWidth, chartHeight);
combinedImage = resize(combinedImage, 500, 430);

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(combinedImage, "png", outputStream);
return outputStream.toByteArray();
}

public byte[] createParameterChangesChart(List<InfluxData> dataList) throws IOException {
CategoryDataset dataset = createParameterChangesDataset(dataList);
JFreeChart chart = ChartFactory.createLineChart(
"Parameter Changes Over Time",
"Time",
"Value",
dataset,
PlotOrientation.VERTICAL,
true,
true,
false
);
int chartWidth = 500; // Adjust as needed
int chartHeight = 340; // Adjust as needed
BufferedImage chartImage = chart.createBufferedImage(chartWidth, chartHeight);
// Convert the chart image to byte array
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(chartImage, "png", outputStream);
return outputStream.toByteArray();
}

public byte[] createLatencyAndRTTCharts(List<InfluxData> dataList) throws IOException {
JFreeChart sourceRttChart = createSummaryChart(dataList,
"Source RTT", InfluxData::getSourceRtt);
JFreeChart sourceLatencyChart = createSummaryChart(dataList,
"Source Latency", InfluxData::getSourceLatency);
JFreeChart destinationRttChart = createSummaryChart(dataList,
"Destination RTT", InfluxData::getDestinationRtt);
JFreeChart destinationLatencyChart = createSummaryChart(dataList,
"Destination Latency", InfluxData::getDestLatency);

int chartWidth = 500; // Adjust as needed
int chartHeight = 280; // Adjust as needed
BufferedImage combinedImage = combineChartsIntoGrid(new JFreeChart[]{sourceRttChart,
sourceLatencyChart, destinationRttChart, destinationLatencyChart},
2, 2, chartWidth, chartHeight);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(combinedImage, "png", outputStream);
return outputStream.toByteArray();
}

private JFreeChart getThroughputChart(List<InfluxData> dataList, String title, ToDoubleFunction<InfluxData> valueFunction) {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
Integer time = 0;
for (InfluxData data : dataList) {
dataset.addValue(valueFunction.applyAsDouble(data), "Throughput", time);
time += 15;
}

JFreeChart chart = ChartFactory.createLineChart(
title,
"Time",
"Throughput",
dataset,
PlotOrientation.VERTICAL,
true,
true,
false
);
CategoryPlot plot = (CategoryPlot) chart.getPlot();
LineAndShapeRenderer renderer = new LineAndShapeRenderer();
plot.setRenderer(renderer);
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setNumberFormatOverride(new DecimalFormat("0.00"));
return chart;
}

private JFreeChart createSummaryChart(List<InfluxData> dataList, String title,
ToDoubleFunction<InfluxData> valueFunction) {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
DoubleSummaryStatistics stats = dataList.stream().mapToDouble(valueFunction)
.summaryStatistics();
dataset.addValue(stats.getMin(), "Min", title);
dataset.addValue(stats.getAverage(), "Avg", title);
dataset.addValue(stats.getMax(), "Max", title);

JFreeChart chart = ChartFactory.createBarChart(
title,
"Metric",
"Value",
dataset,
PlotOrientation.VERTICAL,
true,
true,
false
);
return chart;
}

private JFreeChart getMemoryChart(List<InfluxData> dataList, String title,
ToDoubleFunction<InfluxData> valueFunction) {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
Integer time = 0;
for (InfluxData data : dataList) {
// Convert memory values to megabytes (MB)
double memoryInMB = valueFunction.applyAsDouble(data) / 1e6;
dataset.addValue(memoryInMB, title, time);
time += 15;
}

JFreeChart chart = ChartFactory.createLineChart(
title,
"Time",
"Memory (MB)",
dataset,
PlotOrientation.VERTICAL,
false,
true,
false
);
// Customize chart appearance
chart.getTitle().setFont(new Font("Arial", Font.BOLD, 14));
chart.setBorderVisible(false);
chart.setBackgroundPaint(Color.WHITE);
// Customize the range axis (y-axis) to show meaningful scale
NumberAxis rangeAxis = (NumberAxis) chart.getCategoryPlot().getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setTickUnit(new NumberTickUnit(200));
rangeAxis.setNumberFormatOverride(new DecimalFormat("#,##0"));

return chart;
}

private BufferedImage combineChartsIntoGrid(JFreeChart[] charts, int rows, int cols,
int chartWidth, int chartHeight) {
int combinedWidth = chartWidth * cols;
int combinedHeight = chartHeight * rows;
BufferedImage combined = new BufferedImage(combinedWidth, combinedHeight,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = combined.createGraphics();
for (int i = 0; i < charts.length; i++) {
int row = i / cols;
int col = i % cols;
BufferedImage chartImage = charts[i].createBufferedImage(chartWidth, chartHeight);
g2.drawImage(chartImage, col * chartWidth, row * chartHeight, null);
}
g2.dispose();
return combined;
}
private CategoryDataset createParameterChangesDataset(List<InfluxData> dataList) {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
Integer time = 0;
for (InfluxData data : dataList) {
dataset.addValue(data.getConcurrency(), "Concurrency", time);
dataset.addValue(data.getParallelism(), "Parallelism", time);
dataset.addValue(data.getPipelining(), "Pipelining", time);
time += 15;
}
return dataset;
}

private BufferedImage resize(BufferedImage img, int newW, int newH) {
Image tmp = img.getScaledInstance(newW, newH, Image.SCALE_SMOOTH);
BufferedImage newImage = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = newImage.createGraphics();
g2d.drawImage(tmp, 0, 0, null);
g2d.dispose();
return newImage;
}

}
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
package org.onedatashare.odsmetadata.services;

import com.influxdb.annotations.Column;
import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.QueryApi;
import com.influxdb.query.dsl.Flux;
import com.influxdb.query.dsl.functions.restriction.Restrictions;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.Style;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.UnitValue;
import jakarta.annotation.PostConstruct;
import org.onedatashare.odsmetadata.model.InfluxData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.io.FileOutputStream;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class InfluxIOService {
Expand Down
Loading