Data::ObjectGeneratorを作りました

muddydixon/Data-ObjectGenerator · GitHub

ソーシャルゲームとかアクションログとかそういったものの解析を頼まれたりしたけど、
相手方の仕様が詰まり切ってなかったり、絶賛開発中で「ごめん、ログまだ出せないわ〜」って
状況ってあると思います。

途中でも仕様を聞きだして、サンプルログを作らないと解析もできないし、
集計結果をグラフ化もできないですよね。

そんな時に、次みたいな適当なスクリプトを作ってもいいんですけど

$ perl -MJSON -e 'my $json = JSON->new; for(my $i=0;$i<10000;$i++){print $json->encode({uid=>int(rand()*1000), time => time - int(rand() * 3600 * 24 * 7})."\n"; }'

同じサンプルログをチームでシェアしたいです。そういう時には、下記のような
テンプレートファイルを作成して、gitで管理すれば、同じサンプルログをチームでシェアして
開発をすすめることができます。

{
    "user_id" : {
        "type": "Number"
      , "min": 50
      , "max": 100
    }
    , "user_name": {
        "type": "String"
      , "pat": "Cccnnnnn"
    }
    , "time": {
        "type": "Number"
      , "min": 1341367130
      , "max": 1341971912
    }
    , "tag": "sample"
    , "type": {
        "type": "Enum"
      , "items": ["hoge", "fuga", "piyo"]
    }
    , "register_hour": {
        "type": "Number"
      , "min": 1341367130
      , "max": 1341971912
      , "round": 3600
    }
    , "average": {
        "type": "Number"
      , "min": 100
      , "max": 500
      , "isDouble": 1
    }
}

そんでもって

$ perl ./bin/datagen.pl -t sample.json -n 10 -f csv
average,register_hour,tag,time,type,user_id,user_name
101.062767948852,1341475200,sample,1341543083,piyo,56,Zmy23857
446.95941709805,1341435600,sample,1341405922,piyo,89,Zwd19833
406.173929082109,1341849600,sample,1341511917,piyo,64,Krp21332

$ perl ./bin/datagen.pl -t sample.json -n 3 -f json 
{"register_hour":1341478800,"average":240.581803392516,"time":1341701075,"type":"fuga","tag":"sample","user_id":76,"user_name":"Lvo08081"}
{"register_hour":1341871200,"average":140.299695887451,"time":1341497759,"type":"hoge","tag":"sample","user_id":87,"user_name":"Ynq76984"}
{"register_hour":1341428400,"average":160.925643773629,"time":1341720064,"type":"hoge","tag":"sample","user_id":50,"user_name":"Plo39381"}

$ perl ./bin/datagen.pl -t sample.json -n 3 -f fluentd
2012/07/12 23:56:51 +0900 test: {"register_hour":1341493200,"average":315.102245096014,"time":1341407924,"type":"fuga","tag":"sample","user_id":66,"user_name":"Nqs20784"}
2012/07/12 23:56:51 +0900 test: {"register_hour":1341802800,"average":173.608217359369,"time":1341696936,"type":"piyo","tag":"sample","user_id":56,"user_name":"Mtq98875"}
2012/07/12 23:56:51 +0900 test: {"register_hour":1341694800,"average":320.58444067265,"time":1341890346,"type":"fuga","tag":"sample","user_id":66,"user_name":"Tgj88138"}

のようにいろんな形式でログを標準出力に出すことができます。

ログ作成計画

1種類のログであれば、正直、うえのCPANをインストールすることを考えれば、1 linerで書きます。
でも、往々にして、「ユーザのマスター」「アイテムのマスター」「購買ログ」みたいな何種類ものログが必要になりますし、それぞれをhiveとかで集計したことにして、「分単位」「時間単位」「日単位」みたいなログも必要になります。
その時に便利な機能がplanです。

下記のようなJSONをplan.sample.jsonという名前で保存します。

{
    "file": {
        "file": "./sample.json"
      , "num": 1000
      , "output": "payment.log"
      , "format": "json"
      }
    , "stdout": {
        "file": "./sample.json"
      , "num": 10
      , "output": "stdout"
      , "format": "csv"
      }
    , "fluentd.log": {
        "file": "./sample.json"
      , "num": 10
      , "output": "stdout"
      , "format": "fluentd"
      }
    , "fluentd.forward": {
        "file": "./sample.json"
      , "num": 10
      , "output": {
          "type": "fluentd"
        , "tag": "test.mogumogu"
        , "host": "localhost"
        , "port": 24224
        }
      }
    , "mongo": {
        "file": "./sample.json"
      , "num": 10
      , "output": {
          "type": "mongo"
        , "host": "localhost"
        , "port": "27017"
        , "db": "test"
        , "collection": "mogumogu"
        }
      }
    , "mysql": {
        "file": "./sample.json"
      , "num": 10
      , "output": {
          "type": "mysql"
        , "host": "localhost"
        , "port": "3306"
        , "db": "test"
        , "table": "mogumogu"
        , "user": "root"
        , "pass": ""
        }
      }
}

これは、第一階層のキーが、作業名で、fileがテンプレートファイルです(前述)。numはログのレコード数です。
outputの部分に出力形式を指定します。
現在は

  • stdout
  • file
  • mongodb
  • mysql
  • fluentd

の5種類に対応しています。
各種設定はplan.sample.jsonを参照してください。

さあ、大量のログを作って解析をしましょう!

TODO

  • ちょっとしたプログラムを埋め込みたいので実装しています(テストも終わってます)
  • 変数とかextendsとかやらないとコピペが大量に行われるのでうんざりしています(途中まで)
{
  "$time": {
       "type": "Number"
     , "min": 100
     , "max": 10000
  }
  , "checkin": $time
  , "checkout": {
       "extends": "$time"
     , "round": 160
  }
}

とか、親ファイルを指定して、オプションを上書きしていく仕組みとかいれて、仕事を楽にしたいです。