2013/06/23

OSSの開発活動を可視化するWebサービスをつくりました

Linux Foundation の報告書 "Linux Kernel Development: How Fast it is Going, Who is Doing It, What They are Doing, and Who is Sponsoring It" には Linux Kernle 開発の統計情報が数多く含まれており、開発の規模やスピード感が読み取れます。こういった統計情報は Linux Kernel のみならず、他の多くの OSS 開発プロジェクトにおいても有用です。今回作成した Web サービス "OSS Development Statistics" は git レポジトリのログから、月ごとのコミット数やディベロッパ数、コミット数ランキング、ホットな開発キーワードを表示します。

現在登録してあるプロジェクトは、自分が独断で選んだ以下のものです。要望があれば他にも追加いたします。@Etsukataまでお気軽にどうぞ。git レポジトリであれば簡単に追加できます。
  • libvirt 
  • linux 
  • mongo 
  • node 
  • openstack_nova
  • openstack_quantum 
  • openstack_swift 
  • qemu 
  • riak
現在、一日に一回 git pull してデータベースを更新しています。

サービスの作成にあたっては、MEAN Stack を使用しました。
MEAN Stack とは M : Mongodb, E : Express, A : Angular JS, N : Node.js を指し示します。クライアントサイド、サーバサイドともにJavaScriptで記述できる生産性の高いフレームワーク群です。MEAN Stackについては、mongodb blog に寄稿されている記事: The MEAN Stack: MongoDB, ExpressJS, AngularJS and Node.js が参考になります。

類似のことをするソフトウェアとしては、LWN.net の Jonathan Corbet 氏が主に開発している git-dm があります。Corbet 氏は 新しい Linux Kernel がリリースされる度に開発の統計情報をまとめた記事を投稿しますが、git-dmはその記事を書くために用いられているようです。
Linux Kernel 3.9 リリース時の記事:

今回本サービスを使ってみて、OpenStack-Nova の開発規模が QEMU を上回っていることに驚きました。OpenStack 全体では Linux Kernel の開発規模に迫りつつあるかもしれません。
今後は OSS プロジェクト相互の開発者の乗り入れ状況や、プロジェクト同士の開発規模、開発加速度の比較をしたいと考えています。

参考情報

2013/06/15

Mongodb の Aggregation Framework で月ごとに集計をとる

はじめに

mongodb ので Date Object を含むデータを集計する際に、月ごとで集計をとる方法について説明します。ここでは mongodb version 2.2 で導入された aggregation framework を用います。aggregation framework は非常に柔軟なフレームワークで、SQL に迫るほど強力な集計機能を備えています。map-reduce ほど表現力が豊かではありませんが、ほとんどの集計処理をより手軽に行えます。

早速 aggregation framework を用いて、月ごとに集計をとって見ましょう。

サンプル

まず、mongodb を起動し、mongo shell からサンプルデータを入力しておきます。
> db.revenue.insert({ revenue : 10 , date : ISODate("2013-06-20") })
> db.revenue.insert({ revenue : 5 , date : ISODate("2013-06-30") })
> db.revenue.insert({ revenue : 4 , date : ISODate("2013-05-30") })
> db.revenue.insert({ revenue : 6 , date : ISODate("2013-05-20") })
> db.revenue.insert({ revenue : 3 , date : ISODate("2013-05-10") })
> db.revenue.insert({ revenue : 1 , date : ISODate("2013-04-10") })
> db.revenue.insert({ revenue : 5 , date : ISODate("2013-04-20") })
> db.revenue.insert({ revenue : 2 , date : ISODate("2013-04-30") })
> db.revenue.find()
{ "_id" : ObjectId("51bbbf89d6ac2be7cae104b8"), "revenue" : 20, "date" : ISODate("2013-06-10T00:00:00Z") }
{ "_id" : ObjectId("51bbbfb5d6ac2be7cae104b9"), "revenue" : 10, "date" : ISODate("2013-06-20T00:00:00Z") }
{ "_id" : ObjectId("51bbbfc3d6ac2be7cae104ba"), "revenue" : 5, "date" : ISODate("2013-06-30T00:00:00Z") }
{ "_id" : ObjectId("51bbbfd9d6ac2be7cae104bb"), "revenue" : 4, "date" : ISODate("2013-05-30T00:00:00Z") }
{ "_id" : ObjectId("51bbbfe6d6ac2be7cae104bc"), "revenue" : 6, "date" : ISODate("2013-05-20T00:00:00Z") }
{ "_id" : ObjectId("51bbbfedd6ac2be7cae104bd"), "revenue" : 3, "date" : ISODate("2013-05-10T00:00:00Z") }
{ "_id" : ObjectId("51bbbff7d6ac2be7cae104be"), "revenue" : 1, "date" : ISODate("2013-04-10T00:00:00Z") }
{ "_id" : ObjectId("51bbc000d6ac2be7cae104bf"), "revenue" : 5, "date" : ISODate("2013-04-20T00:00:00Z") }
{ "_id" : ObjectId("51bbc008d6ac2be7cae104c0"), "revenue" : 2, "date" : ISODate("2013-04-30T00:00:00Z") }

これらのデータについて、月ごとの revenue を集計してみましょう。
今回使用する aggreagation framework のオペレータは 以下です。
$project : document を集計しやすくするために整形する(SQL での SELECT に相当)
$month : Date Object から月を示す数値を返す
$year : Date Object から年を示す数値を返す
$group : document を集計するためにグルーピングを行う(SQL での GROUP BY に相当
$sum : 数値を合計する

オペレータ一覧は下記ページにあります。
Aggregation Framework Reference

クエリは以下のようになります。
> db.revenue.aggregate(
  { $project : {
    ym : { 
      year : { $year : "$date" }, 
      month : { $month : "$date" }
    },
    revenue : 1}
  }, 
  { $group : {
    _id : "$ym" , 
    revenue_per_month : { $sum : "$revenue" }
    }
  })

{
 "result" : [
  {
   "_id" : {
    "year" : 2013,
    "month" : 5
   },
   "revenue_per_month" : 13
  },
  {
   "_id" : {
    "year" : 2013,
    "month" : 4
   },
   "revenue_per_month" : 8
  },
  {
   "_id" : {
    "year" : 2013,
    "month" : 6
   },
   "revenue_per_month" : 35
  }
 ],
 "ok" : 1
}

上記クエリについてすこし説明を加えておくと、まず、$project オペレータで Date Objectから年と月を取り出し、集計に使う revenue を抽出しておきます。$project オペレータに続いて、pipeline で $group オペレータを作用させ、実際に集計を行います。

上記で用いたオペレータ以外にも、$sort や $match など便利なオペレータがたくさんありますので、ぜひ試してみてください。

参考文献

MongoDB : Aggregation Framework Reference
SQL to Aggregation Framework Mapping Chart
MongoDBでゆるふわDB体験