Redmineのログ可視化ページがお蔵入りした話

# はじめに

私が以前に所属していたチームでは月末に振り返りを行い案を出して改善活動をしていました。
この振り返り作業のために、開発チームメンバのRedmineのログを可視化したけど残念ながら活用されなかった思い出を書いていきます。
ですので、本記事では成功事例というより、業務の合間にせっかく作ったのに使われずにお蔵入りしてしまった、という失敗事例の内容となります。

#当時の問題

月末に実施していた振返りでは、一ヶ月の間に実行したタスクと予定と実績工数などの確認をしてどの作業に時間がかかったかを見つけて問題点を挙げて改善案を検討していました。
この振返りの材料となるデータ（予定工数、実績工数等）を、プロジェクト管理ツールとして使っていたRedmineのログから取得、集計して作成していました。

### Redmineとは？
集計作業内容の説明にあたって、少しだけRedmineの説明をさせて頂きます。
【概要】
　OSSのプロジェクト管理ツールです。
　Redmineではタスクを「チケット」として作成して進捗、スケジュール管理を行えます。
　詳細は公式ページをご確認ください。⇒ [Redmine](https://redmine.jp/overview/)
【機能】
本記事を読むにあたって最低限の用語説明を記載します。
詳細は公式サイトの用語解説を見るのが良いです。⇒ [用語解説](https://redmine.jp/glossary/)
**〇チケット**
　Redmineでのタスク管理におけるタスクの単位です。
　タスクの内容・優先度・担当者・期日・進捗状況などを記録することができます。
　以下の画面でチケット作成ができ、作成したチケット一覧を確認できます。
　また、作成したチケットはCSV形式で出力も可能です。
　**チケット作成画面**
　　<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536019/39fcc56b-e81c-4415-ad97-063dd1db1c94.png">
　**チケット一覧**
　　<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536019/23419fb9-6165-8689-82ea-d0e289b87de2.png">
　　チケット一覧画面でフィルタ設定することによって特定のチケットを確認できます。
　　例：自分が担当のチケット、進行中のチケット、etc../

**〇プロジェクト**
　Redmineで情報管理を行う最も大きな単位です。
　案件ごとにプロジェクトを作成し、プロジェクト内でチケット発行してスケジュール等を決めていきます
　管理者であれば好きにプロジェクトを作成でき、プロジェクトを入れ子にすることもできます。

### 集計作業

振返り会を実施するにあたり、Redmineで対象プロジェクトのチケット一覧画面から当月の担当チケットをフィルタリングして抽出、CSVデータを出力してExcelで集計！！していました。

集計作業の流れは以下の通りです。

- Redmineからログ(.csv)を取得
    - チケット一覧、作業時間履歴画面から下図の緑枠部でフィルタリング設定して担当タスクを抽出
    - 赤枠部で抽出したデータをCSV出力
    - CSVにはチケットに設定可能な項目が出力されます

　　　<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536019/ac7216c7-1766-1d14-516c-1025d0a43699.png">

- 作業タスクの予実差を集計
    - 月間の全チケットの予定、実績時間の合計、予実差を計算。
    - 各チケット毎の予定、実績時間の合計、予実差を計算
    - 予実差、予実比が大きいタスクを抽出
- レビュー結果を集計
    - カテゴリ「レビュー」のチケット数をカウント
    - 各タスク毎のレビュー指摘件数を集計
    - レビュー種別毎の件数を集計
- 不具合件数を集計
    - 「バグ」カテゴリをカウント
    - バグの種別（登録時に設定）毎の件数を集計
 
書き出してみると結構ありますね。。辛い記憶がよみがえります。。

この作業はとても苦痛でした。。
それでも振返りの材料集めのため実施していましたが、この作業自体が結構大変だったため以下のような問題が発生するようになりました。

- 単純に集計作業に時間がかかる。
- 集計項目・内容が各担当者に属人化していた
- 集計に時間がかかってじっくり振返り出来ない
- 分析に注力出来ないから改善案も表面的なものになり問題も再発

そのため、何とか上記作業を楽にしようと集計作業の自動化に取り組みました。

# 目指したこと

手作業でのCSVデータ集計をやめることを目指しました。
個人的な要望は以下の3点でした。
- データ取得から集計までを自動化して簡単に集計結果を得たいこと
- 集計よりも振返り、分析に時間を使いたい
- 集計結果から何かインサイトを得て機械学習したい
  
モチベーションとしては3点目の「機械学習したい！」が一番高かったですが、そこまで到達しなかったです。。

# 環境、利用ツール・ライブラリ

ログデータの収集、集計、可視化のためには以下のツール・ライブラリを使用しました。

- OS：Windows 10
- 開発言語：Python 3.6
- ライブラリ
    - python-redmine
    - flask
    - pandas
    - pyinstaller
- ツール
    - Jenkins
    - docker for windows
    - jupyter notebook

# お蔵入りまでの足跡

最終的にお蔵入りになりる作成した可視化ページですが、そこに至るまでの足跡を書いていきます

## 1. jupyter notebookで集計

集計作業を自動化するためには大きく、「データ取得」、「集計」、「可視化」の3工程に分かれます。
まずは、集計にフォーカスして作業を始めました。
ログデータ(.CSV)はそれまでと同様にRedmineを操作して全データを取得します。
実装にはpythonを使ってjupyter notebookで実験的に集計しました。

文字コードに躓きつつ、チケット毎の作業予定・実績時間、作業別の時間割合を出してみました。
出力例を紹介します

- 作業予定・実績時間
  
　作業予定時間と作業実績時間の差を集計しています。
　各チケット毎の値をとり、予定時間 ＜ 実績時間 となったチケットをピックアップしてグラフ化しました。
　縦軸を左図は予定・実績時間の差で、右図は予定・実績時間を予定時間に対する比率にして作成しています。
　これで予定より時間がかかったのか、予定超過の作業時間は予定に対してどれだけあったかがわかるかと思います。

![yojitu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536019/79db2db6-361f-1377-1761-c12a5f6fb20e.png)

- 作業時間割合

一ヶ月間のタスク別の作業時間割合をバーグラフにしました。
これをプロジェクト別など、別の切り口でも用意しました。
※凡例部分は個人やタスクの内容が特定されるので隠しています。

![worktime.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536019/10f8fee1-b4ac-428a-e379-6d2536502236.png)


この辺で、チームリーダに集計結果を紹介すると良い反応がもらえたので他メンバにも共有しました。

メンバからは歓喜の声が聴けるんじゃないかと期待していたんですが、共有した後に返ってきたのは「.ipynbファイルってなんですか？」、「どうやって動かすんですか？」ってリアクションでした。
普段の開発はC++やC#がメインだったのでpythonは馴染みが薄かったのです。。
説明用に資料作るのもめんどくさかったので、全員が実行できる形式で配布することにしました。

## 2. exe化

開発環境はみんなWindowsな状態なので、.exe化して配布することにしました。
exe化には「pyinstaller」を使いました。
ese化するとなるとjupyter notebookのようにグラフ表示できないのでpythonスクリプト化して集計結果のグラフは画像出力するようにしました。
下図のようなイメージです。
![exe.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536019/81216a1f-54c7-b5c0-d3d8-b772f6e25427.jpeg)

データ取得まではこれまで通り手作業をして、所定の場所にデータを置いて集計スクリプト実行となります。

.exeとしてパッケージして配布しようと思ったときに、いくつか悩んだことがありました。

- 集計内容を個人単位で選べるようにする？
    - exe化すると各個人でちょっと変えて実行とかしなくなるため  
      ⇒ 時間なかったので全員分の集計結果をすべて出力するようにしました
- .exeファイルをダブルクリックだけで終わるようにしたい  
   ⇒ 引数付けたり、GUIとか用意とかしない。データ置いて実行したら集計結果が出てくるようにしました
- リファクタする
    - .exe化するにあたりpythonスクリプト化する必要があった
    - jupyter notebookで実験的に実装していた  
      ⇒ 実験コードのままだと辛かったので、機能を整理して大雑把にクラス設計して再実装しました。

業務外の時間（始業前やお昼休憩）を使って作業していたので、中々作業進まず上記対応には結構時間かかりました。。

そして、何とか上記対応を反映して.exeファイルをソースコードと共にチームメンバに共有しました。
今度は.exe実行だけだったので試してもらえたのですが、「自分の集計結果だけ出したい」、「データは毎回取得ですか？」といったリアクションでこの時点でもあまり利用してもらえませんでした。残念。

また、出力結果が全員分出るなら各個人で実行する必要もないので共有PCで定期的にデータ取得・集計実行するようにしました。
以下のような構図です。

![exe2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536019/65e1d341-5657-3f4a-d9e6-32da10a60812.jpeg)

代表者（私）だけが更新作業をすることになりますが、チームメンバはデータ取得だけになります。
集計作業の負担が下がり集計頻度を増やし始めるとデータ取得の手間が増えたので、次にデータ取得の自動化に着手しました。

## 3. データ取得の自動化

データ取得には[python-redmine](https://python-redmine.com/)（RedmineのAPI機能をサポートするpythonライブラリ）を利用しました。
このライブラリの使い方についての解説は以下の記事が参考になります。
[Python Redmineを使用してRedmineを操作する](https://qiita.com/mima_ita/items/1a939db423d8ee295c85)

このライブラリを駆使して、これまでRedmineを操作して実行していたデータ取得作業をpythonで自動化しました。
Redmineをスクリプトから操作できて便利！でしたが、カラム名を調整したり未入力項目などの欠損処理が必要だったりと実装には苦戦。。。
最終的にはデータ取得用スクリプトと集計用スクリプトに改修を加えて2つの機能を連携させました。
また、この段階ではスクリプトを実行するのは私だけになっていたので.exe化をやめました。

以下のような構図になります。
![redmine.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536019/7b0625f1-5cef-8c5f-9c17-64e8746c48e4.jpeg)

Redmineを操作してデータ取得する作業がなくなり集計結果出力までが自動化され、チームメンバは集計結果を取得するだけになりました。

ですが、残念ながらこの時点でもまだ集計結果はあまり利用されませんでした。
その理由として考えたのが以下の3点です。

- 集計結果画像は同じ場所に出力していたので目的のファイルを探すのがめんどくさい
- 確認出来る集計結果の種類が少ない
- 欲しいときにタイムリーな結果がない

このまま、集計のバリエーションを増やすと集計結果出力場所が煩雑になりますし、もっと手軽に集計結果を見れる必要があると思い可視化に取り組みました。
その後にデータ更新を検討することにしました。

## 4. 集計結果の可視化

どうやったら利用しやすくなるだろうかと考え、Webページとしてグループ内で公開することにしました。
理由としては、以下の通りです。

- 環境設定を不要にしてどのPCでも確認できるようにしたい
    - デスクトップPC＋ノートPCで作業しているメンバもいたため
- ファイル取得なしで、アクセスしたらすぐ見れるようにしたい
- 複数の集計結果を1ページで色々確認出来る

この時点の実装上の問題としては、私自身がWeb開発の経験がなかったことです。。
それでも利用しやすい環境を目標に開発の仕方から調べました。
使用したのは以下のものになります。

- Webサーバ：flask
- Webページ：html、css
- サーバ：グループ内で使っていた共有PCを利用
- 実行環境：Docker for windows

pythonだけじゃなく、flaskやpython-redmineも使うようになり環境構築が大変になったのでここからDockerも導入して実行環境も整備するようにしています。
ちなみにコンテナを使うのも初めてでした。

Dockerとflaskの使い方、Web全般について調べながら実装して以下のような構図となりました。

![redmine3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536019/b0bd1686-55a1-ef45-2579-c7b22cdace7c.jpeg)

作成したページも名前が出てくる箇所は隠して一部ですが掲載しておきます。
質素な見た目ですがこんな画面を作成しました。

![redmine5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536019/6dcd5032-dd8f-9461-b9d1-d8535fea5a87.jpeg)

ここまでくると少しづつ見てもらえるようになり、
「これ見たい」、「あれ見たい」といった集計の要望が一部メンバから上がるようになりました。
要望に応えようと、私は集計処理を実装して更新していきます。。
集計項目が増えていったのはいいのですが、この辺りでソース修正後の環境更新作業の手間が我慢できなくなりました。

簡単にその手順を書くと、こんな感じです。

- ローカルPCでソースコードを修正する
- Githubへプッシュ
- 共有PCへ移動してソースコード取得
- コンテナをとめてWebサービス停止
- コンテナ再稼働

5 ～ 10分くらいの作業だったと思うのですが更新頻度が多くなると辛くなりました。
ですので、このオペレーションの自動化に取り組み始めます。

## 5. オペレーションの自動化

環境更新作業を自動化するにあたってどんなツールがあるかしばらく探しました。
バッチファイル作って定期実行でも良いですが、
　・バッチファイル苦手だから作りたくない、
　・GUIで設定を制御できるようにしたい、
　・無償のツールでやる
などなど個人的な要望があり、過去に経験があるJenkinsを使うことにしました。

jenkinsはDockerを使って導入してデータ取得～Webサーバ再起動までの作業を定期的に実行するように対応しました。

Dockerコンテナ上で動作するJenkinsから別のDockerコンテナを操作することになったので色々めんどくさかったのですが、参考記事をあさってDinDかDooDにするかなどを検討して何とか作り上げたのが以下の構成です。

![Extra - Archetecture3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536019/d864cc1d-3524-5e11-a13b-32b0046b94fa.jpeg)

これでついに、データ取得からWebページ公開までの作業が自動化されて私は集計処理やWebページの改善に集中できるようになりました。うれしい！！
ただこの構成だとデータ更新が発生するのが定期実行のタイミングだけという課題があります。

もっと賢いツールの選択ややり方などあるのでしょうが、notebookを配布していた状態と比較するととても作業がやりやすくなりました。

## 6. そしてお蔵入りへ

ここまで取り組んできましたが、残念ながらお蔵入りの時が近づいてきます。
作業環境が整備されたため、業務の合間はずっと集計作業やWebページ修正をしていました。

集計対象もすべてのプロジェクトに拡張して、各メンバがどのプロジェクトのどの作業に時間を使っているかを可視化していきました。
集計項目についても、普段の会話からどんなものが必要そうかを考えて追加していきました。
その他にもSPA導入など、やってみたいことはたくさんあったんですが、一人では手が回らず。。
当時は自分で考えて作っていくことが楽しく、色々と修正と拡張を繰り返してました。

ですが、ここまで様々に仕組みを作成してきましたがどうやって使うかの議論がなされていなかったということもあり、Webページを見てくれるメンバは残念ながら増えていきませんでした。

また、〇〇報告資料のフォーマットで集計して出力できるか？といった当初の要望とは違うことや△△のプロジェクトは非表示にしてほしいなど可視化をしだして初めて聞く意見もありました。
各意見に向き合ってどうすればいいか話し合っていけばよかったのですがそんな行動はしていませんでした。。

そして、なかなか使ってもらえない状況や、自分の想いと要望とのギャップに整理がつけられず作成・改善することをやめてしまいました。

最終的に、Redmineログ可視化へのモチベーションがなくなり、更新が止まりお蔵入りすることになりました。

# おわりに

結果的には、利用者の要望を取り入れなかった独りよがりのものを生み出してしまったのだと思います。

コンテンツを増やしていけばみんな見てくれる、技術的な要素を増やしていけばみんな興味持ってくれる、という思い込みをベースにして作業していたので利用者の要望とずれたものになってしまったし、思い込みが間違っていると分かったときに整理がつけれず手が止まってしまいました。

当時の自分に足りなかったのは、自分が生み出したものを使ってくれるメンバとの対話だったのかと思います。
それ故に、チーム内で必要とされるものが作れなかったと思います。

今後はこんな悲しいことはしたくないと思い、本記事をまとめさせていただきました。
ここまで読んで頂きありがとうございました。

# 参考資料

- [Redmine](https://redmine.jp/)
- [Python-Redmine](https://python-redmine.com/)
- [Python Redmineを使用してRedmineを操作する](https://qiita.com/mima_ita/items/1a939db423d8ee295c85)
- [Dockerコンテナ内からDockerを使うことについて](https://esakat.github.io/esakat-blog/posts/docker-in-docker/)