絶対に真似してはいけない。闇のRedash入門

絶対に真似してはいけない。闇のRedash入門:

Lobi事業部データエンジニア(自称)の池田です。

この記事はKAYAC Advent Calendar 2018の4日目です。

Redashとは

Redashは様々な種類のデータソースにアクセスできる、OSSの素晴らしいダッシュボードツールです。

以前、本ブログでは、健康的な使用事例を紹介しました。

techblog.kayac.com
techblog.kayac.com

今現在のKayacでも、事業の様々な数値や状態を可視化、お問い合わせからの調査等の業務支援ツールとして広く活用されています
本日は、Redashの非健康的な使用事例を紹介します。

すべての始まり【Pythonデータソース】

Lobi - Chat & Game Communityは今年で開発・運用が8年目になるスマホゲーマーSNSサービスです。

Lobiを開発・運用するLobi事業部では、Redashを活用する上で2つの問題を抱えていました。

  1. ShardingされたDBが参照しづらい問題
  2. Detail JSON Parse辛い問題
1つ目の問題は、Sharding*1されたDBをRedashからアクセスする場合、単純なSQL文では水平分割の台数分だけRedashのクエリが必要になります。 2つ目の問題は、8年という長い期間で生まれた、detail_json という名前の、どうみてもJSONな文字列が入ったTEXTカラムが存在するテーブルがあります。単純なSQL文では特定のキーの情報だけ参照するのはとても大変です。

この問題を解決するソリューションとして、Pythonデータソース

このようなPythonデータソースを使うRedashのクエリが誕生する。

import json  
import re  
 
# query_params validation 
validator = re.compile('[0-9]+(,[0-9]+)*') 
ids = '{{{ids}}}' 
if not validator.match(ids): 
    print 'plz Comma-Separated Values format' 
    return  
 
#shard_map access  
shard_map_query = ''' 
select user_id, shard 
from shard_map 
where user_id in (%s) 
''' % ids 
rows = execute_query('mysql main',shard_map_query)['rows'] 
ids_by_shard = {} 
for row in rows: 
    shard = row['shard'] 
    if not shard in ids_by_shard: 
        ids_by_shard[shard] = [] 
    ids_by_shard[shard].append(row['user_id']) 
del rows 
 
#query detail json 
data_source_by_shard = { 
    'shard01': 'mysql shard1', 
    'shard02': 'mysql shard2', 
} 
for current_shard, current_ids in ids_by_shard.items(): 
    query = ''' 
    select id, detail_json 
    from user_opt  
    where id in (%s) 
    ''' % (','.join(map(lambda x:str(x), current_ids))) 
    data_source = data_source_by_shard[current_shard] 
    rows = execute_query(data_source,query)['rows'] 
    for row in rows: 
        data1 = '' 
        data2 = '' 
        if row['detail_json'] != '': 
            detail = json.loads(row['detail_json']) 
            if 'data1' in detail: 
                data1 = detail['data1'] 
            if 'data2' in detail: 
                data2 = detail['data2'] 
        add_result_row(result, { 
            'id': row['id'], 
            'data1': data1, 
            'data2': data2, 
        }) 
 
add_result_column(result, 'id', '', 'integer') 
add_result_column(result, 'data1', '', 'string') 
add_result_column(result, 'data2', '', 'string') 
このときは最強のソリューションに見えた。

参考文献

tbpgr.hatenablog.com
techblog.lclco.com

気軽にエンジニア以外でも扱える【Googleスプレットシートデータソース】

とある平日。

カスタマーサポート担当から『こちらのリストにのっている方のアクセス情報を一覧できない?』
別のある平日。
営業担当から『このリストにのっているグループの発言量を一覧できない?』
そして、一ヶ月後のある平日
『この間の一覧した情報、定期的に自動更新できない?』

等々、様々な業務を行う関係各所から このリストにのっている○○ シリーズの業務支援を依頼されることがあります。
Kayacでは多くの場合、Google スプレットシート*2を使ってリストが渡されます。

そんな依頼にこちらのソリューション

なんと! エンジニア以外でも扱える素敵なデータソースとして、Googleスプレットシートを使えます。

もちろん!Google Apps Scriptも併用して更に便利になるチャンス!
これは仕事が捗ります

そして、簡易アプリケーション爆誕

ここまでは、健康的な範疇の活用方法ですが、
皆様お気づきだろうか、ここまで環境を整えたRedashは以下のように捉えられるということに。

Redash機能 要素
様々なデータソース Model 特に、柔軟に入出力可能なGoogleスプレットシートは扱いやすい
様々なVisualization View 折れ線グラフや棒グラフ、箱ひげ図、サンキーチャートなど。
Pythonデータソース ViewModel 柔軟なデータ処理を行える。module importすれば可能性は無限大
そう、環境の整ったRedashはMVVMとみなすこともできる!!?

そして、いつの間に、Redash上で動く簡易アプリケーションの爆誕することになります。

もちろん、Git管理されてない

そして、事業の中核になるアプリケーションのリポジトリ外なのでコードレビュー対象外
この簡易アプリケーションは非健康的です。保守の観点で…

現在のLobi事業部のRedash運用

保守が必要になるような割と業務で重要なものは、アプリケーションのリポジトリに

redash/query_3121.py 
redash/query_3122.py 
︙
のように保存してGit管理するケースが出てきています。

まとめ

Redashの登場により、Kayacではいたるところで業務改善が行われました。

PythonデータソースもGoogleスプレットシートデータソースも適切に利用すれば、とても『イノベーティブ』です。

しかし、過度の利用は保守が大変な簡易アプリケーションの生んでしまいます。

用法・用量を守って素晴らしきRedashライフを送りましょう!

そんな感じで、あらゆる業務改善・事業可視化をするエンジニアもカヤックでは募集しております!

次回予告

明日は、id:wyumikokhさんが『gitbookで幸せ計画』について書いてくれるようです。

オリジナルのエンクロージャ:


コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)