All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.deephaven.benchmark.run.PublishNotification Maven / Gradle / Ivy

The newest version!
/* Copyright (c) 2022-2024 Deephaven Data Labs and Patent Pending */
package io.deephaven.benchmark.run;

import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import io.deephaven.benchmark.api.Bench;
import io.deephaven.benchmark.connect.ResultTable;
import io.deephaven.benchmark.util.Filer;

/**
 * Generate benchmark tables for posting to Slack. Produces tables in CSV and SVG form. These tables are different from
 * other auto-generated tables in that they pull data exclusively from GCloud.
 */
public class PublishNotification {
    static final String rowIndent = " ".repeat(10);
    final String[] tables = {"nightly_worst_score", "nightly_best_score"};
    final URL queryFile;
    final URL svgTemplate;
    final Path outputDir;
    private String slackToken = "";
    private String slackChannel = "";

    /**
     * Create an instance to generate CSV and SVG tables
     * 
     * @param queryFile the query to run on Deephaven
     * @param svgTemplate the SVG template to apply table results to
     * @param outputDir the output directory to place the SVG and CSV files
     */
    public PublishNotification(URL queryFile, URL svgTemplate, Path outputDir) {
        this.queryFile = queryFile;
        this.svgTemplate = svgTemplate;
        this.outputDir = outputDir;
    }

    /**
     * Generate the tables and publish to Slack
     */
    public void publish() {
        var query = Filer.getURLText(queryFile);
        var svgTemp = new String[] {Filer.getURLText(svgTemplate)};
        Bench api = Bench.create("# Publish Notification");
        try {
            api.setName("# Publish");
            slackChannel = api.property("slack.channel", "");
            slackToken = api.property("slack.token", "");
            if (slackChannel.isBlank() || slackToken.isBlank()) {
                System.out.println("-- Slack properties are not defined. Skipping query notification --");
                return;
            }
            System.out.println("-- Running notification queries --");
            var aquery = api.query(query);
            aquery.fetchAfter("platform_details", table -> {
                svgTemp[0] = updatePlatformDetails(table, svgTemp[0]);
            });
            for (String tableName : tables) {
                aquery.fetchAfter(tableName + "_small", table -> {
                    generateCsv(table, outputDir, tableName + ".csv");
                });
                aquery.fetchAfter(tableName + "_large", table -> {
                    generateSvg(table, svgTemp[0], outputDir, tableName + ".svg");
                });
            }
            aquery.execute();
        } finally {
            api.close();
        }

        publishToSlack(outputDir);
    }

    void publishToSlack(Path outDir) {
        var message = "Nightly Benchmark Changes " +
                "\n";

        for (String table : tables) {
            message += "*" + table.replace("_", " ") + "*\n";
            message += "```" + Filer.getFileText(outDir.resolve(table + ".csv")) + "```\n";
        }

        var payload = """
        {"channel": "${channel}", "unfurl_links": "false", "unfurl_media": "false", "text": "${msg}"}
        """;
        payload = payload.replace("${channel}", slackChannel);
        payload = payload.replace("${msg}", message);
        try {
            System.out.println("-- Pushing notification to Slack --");
            URL url = new URI("https://slack.com/api/chat.postMessage").toURL();
            var c = (HttpURLConnection) url.openConnection();
            c.setRequestMethod("POST");
            c.setDoOutput(true);
            c.setRequestProperty("Content-Type", "application/json");
            c.setRequestProperty("Accept", "application/json");
            c.setRequestProperty("Authorization", "Bearer " + slackToken);
            byte[] out = payload.getBytes(StandardCharsets.UTF_8);
            OutputStream stream = c.getOutputStream();
            stream.write(out);
            System.out.println("-- Slack Response: " + c.getResponseCode() + " " + c.getResponseMessage() + "--");
            c.disconnect();
        } catch (Exception ex) {
            System.out.println("Failed to Post to channel: " + slackChannel);
        }
    }

    void generateCsv(ResultTable table, Path outDir, String fileName) {
        var s = table.toCsv("  ", "LR");
        Filer.putFileText(outDir.resolve(fileName), s);
    }

    String updatePlatformDetails(ResultTable platform, String svgTemplate) {
        var s = svgTemplate;
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        s = s.replace("${run_date}", dtf.format(LocalDateTime.now()));
        s = s.replace("${os_name}", "Ubuntu 22.04.1 LTS".toLowerCase().replace(" ", "-"));
        // s = s.replace("${benchmark_count}", "" + benchmarks.size());
        s = replaceDetail("${dh_threads}", s, platform, "deephaven-engine", "available.processors");
        s = replaceDetail("${dh_heap}", s, platform, "deephaven-engine", "java.max.memory");
        return s;
    }

    void generateSvg(ResultTable table, String svgTemplate, Path outDir, String fileName) {
        var s = svgTemplate;
        var columnNames = table.getColumnNames();
        s = s.replace("${HEADER}", getRow("th", columnNames.toArray()));
        s = s.replace("${ROWS}", getRows("td", table, columnNames));
        Filer.putFileText(outDir.resolve(fileName), s);
    }

    private String replaceDetail(String var, String temp, ResultTable table, String origin, String name) {
        ResultTable t = table.findRows("origin", origin).findRows("name", name);
        return (t.getRowCount() < 1) ? temp : temp.replace(var, t.getValue(0, "value").toString());
    }

    private String getRows(String colMarkupElem, ResultTable table, List columnNames) {
        var str = "";
        for (int i = 0, n = table.getRowCount(); i < n; i++) {
            if (i > 0)
                str += "\n" + rowIndent;
            str += getRow(colMarkupElem, table.getRow(i, columnNames).toArray());
        }
        return str;
    }

    private String getRow(String colMarkupElem, Object... values) {
        var str = "";
        for (Object value : values) {
            str += "<" + colMarkupElem + '>' + value + "';
        }
        return str += "";
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy