LoginSignup
5
3

More than 5 years have passed since last update.

CSV形式のデータをグラフに表示するJenkins Plug-inの作成 (2)

Posted at

はじめに

前回はJenkins Pluginを作成し、CSVファイルのデータをテキストで表示するサンプルを作成しました。今回は、CSVファイルのデータをグラフ化するプラグインを作成したいと思います。前回の記事の続きになっていますので、前回の記事をお読みでない方は、前回の記事もご参照頂ければと思います。

JFreeChartを用いたグラフ化

グラフ化の方法はいろいろあると思いますが、plot pluginのソースコードを調査したところJFreeChartを使っていることが分かりました。このサンプルでも同様にJFreeChartを使用したいと思います。

JFreeChartを用いたグラフ化は単純には以下のような流れになります

  1. DefaultCategoryDatasetにデータを入力
  2. ChartFactoryクラスを用いてdatasetからJFreeChartクラスを作成
  3. JFreeChartクラスからPNGを作成

CSVファイルからDatasetの作成

以下のようなCSVデータをパースします

echo "week, active, new" > kpi.csv
echo "w1,1000,100" >> kpi.csv                                    
echo "w2,1200,200" >>  kpi.csv                                    
echo "w3,1400,200" >> kpi.csv                                    
echo "w4,1500,100" >> kpi.csv
echo "w5,1600,100" >> kpi.csv

CSVからDatasetを作成するクラスです

public class CsvDataset {
    public static CsvDataset parse(FilePath path) {
        try {
            if (!path.exists()) {
                return null;
            }
        } catch (IOException e2) {
            return null;
        } catch (InterruptedException e2) {
            return null;
        }

        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(path.read(), "UTF-8"));
        } catch (UnsupportedEncodingException e1) {
            return null;
        } catch (IOException e1) {
            return null;
        } catch (InterruptedException e1) {
            return null;
        }

        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        String[] columns = null;
        try {
            String line = null;
            while ((line = reader.readLine()) != null) {
                if (columns == null) {
                    columns = line.split(",");
                } else {
                    addValues(dataset, columns, line);
                }
            }
        } catch (IOException e) {
            return null;
        }

        return new CsvDataset(dataset, columns[0]);
    }

    private static void addValues(DefaultCategoryDataset dataset, String[] columns, String line) {
        String[] values = line.split(",");
        if (columns.length != values.length) {
            return;
        }
        String rowKey = values[0];
        for (int i = 1; i < columns.length; i++) {
            Number value = retrieveValue(values[i]);
            if (value != null) {
                dataset.addValue(value, columns[i], rowKey);
            }
        }
    }

    private static Number retrieveValue(String valueStr) {
        Number value = null;
        try {
            value = Integer.valueOf(valueStr);
        } catch (NumberFormatException ie) {
            try {
                value = Double.valueOf(valueStr);
            } catch (NumberFormatException de) {
            }
        }
        return value;
    }

    private final DefaultCategoryDataset mDataset;

    private final String mCategoryLabel;

    private CsvDataset(DefaultCategoryDataset dataset, String categoryLabel) {
        mDataset = dataset;
        mCategoryLabel = categoryLabel;
    }

    public CategoryDataset getCategoryDataset() {
        return mDataset;
    }

    public String getCategoryLabel() {
        return mCategoryLabel;
    }
}

CsvPublisherの拡張

グラフには、タイトルなどの追加情報が必要ですので、以下のようにタイトルと縦軸のラベルのパラメーターを追加します。

スクリーンショット 2015-12-24 23.53.42.png

config.jelly

<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
  <!--
    This jelly script is used for per-project configuration.

    See global.jelly for a general discussion about jelly script.
  -->

  <f:entry title="File Name" field="fileName">
    <f:textbox />
  </f:entry>
  <f:entry title="Title" field="title">
    <f:textbox />
  </f:entry>
  <f:entry title="Value Label" field="valueLabel">
    <f:textbox />
  </f:entry>
</j:jelly>

CsvPublisher.java

public class CsvPlotPublisher extends Recorder implements SimpleBuildStep {
    private final String mFileName;

    private final String mTitle;

    private final String mValueLabel;

    private FilePath mFilePath;

    @DataBoundConstructor
    public CsvPlotPublisher(String fileName, String title, String valueLabel) {
        mFileName = fileName;
        mTitle = title;
        mValueLabel = valueLabel;
    }

グラフの表示

index.jellyからのグラフの表示ですが、JavaのコードからPNGのデータを受け取りそれを表示する形になります。ここではgetPlotでデータを取得していますが、ネーミングルールで、JavaではdoGetPlotというメソッドで呼び出す形になります。doGetPlotメソッド内でグラフを作成し、PNGを返してやればグラフの描画がされます。

index.jelly

<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:c="chart">
  <l:layout title="${it.project.displayName}">
    <l:main-panel>
      <img src="getPlot" width="750" height="450" />
    </l:main-panel>
  </l:layout>    
</j:jelly>

CsvPlotAction.java

    public void doGetPlot(StaplerRequest req, StaplerResponse rsp) {
        FilePath filePath = mPublisher.getFilePath();
        CsvDataset dataset = CsvDataset.parse(filePath);
        final JFreeChart chart = ChartFactory.createLineChart(mPublisher.getTitle(), 
                dataset.getCategoryLabel(), mPublisher.getValueLabel(), 
                dataset.getCategoryDataset(), PlotOrientation.VERTICAL, true, false, false);
        chart.setBackgroundPaint(ChartColor.WHITE);
        try {
            new Graph(-1, 750, 450) {
                protected JFreeChart createGraph() {
                    return chart;
                }
            }.doPng(req,rsp);
        } catch (IOException e) {
        }
    }

前回ではテキストで表示されていたCSV Plotメニューを選択するとグラフが出ました

スクリーンショット 2015-12-24 23.54.12.png

おわりに

plot plug-inを参考にして、ミニマムなCSVファイルからグラフ化するプラグインを作成しました。今後はこれを拡張して、様々な業務に役立てていきたいと思います。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3