はじめに
技術部インフラGの鈴木です。先日金沢競馬で最終レースで全てを取り返す体験をしたところ、久しぶりに生きていると感じました。
ところで、今回は以前こちらの勉強会にて話した内容をもとに、今年から始まった「会社に紐づくエンジニアリング」を行うソリューションチームの活動についてお話しします。
勉強会の時に使用したスライドは以下となります。
立ち話から株価通知くん、爆誕
リブセンスはフルリモートなのでSlack上で積極的に話す文化であるWOLを実践しても、出社時と比べてどうしても雑談が少なくなりがちです。他部署等、自分と積極的に関わりのない人たちとは特にそれを感じます。
そのため、出社時には雑談がてら「欲しいものないですかね?w」「困ってることないですかね?w」など聞いていました。株価通知くんはその流れで生まれたもので、「Slackに自社の株価通知bot欲しいよね〜」という話をしたのがきっかけです。
なぜこの話になったかというと、先日リブシェアという譲渡制限付株式制度が発表されました。いわゆる従業員向け株式報奨制度です。
これを機に自社の株価を意識したいよね、ということで株価をSlack通知するbotを作りました。これが株価通知くんで、ソリューションチームの仕事として行いました。
自社の株価について意識したことはこれ以前にもありました。転職会議で口コミ要約機能がリリースされたときです。プレスリリースの発表に伴って株価があがりました。エンジニアリングによって株価を動かすというのは一度はやってみたいことですね…。
その時の記事はこちらです。
このようにソリューションチームではプロダクトに紐づくエンジニアリングではく、会社に紐づくエンジニアリングを行っています。
今の所メンバーはインフラから2名、情シスから1名、VPoEの4人の兼務でチームを構成しています。今回はこのチームの仕事について私目線で説明します。
技術投資とソリューションチーム
リブセンスには技術投資という制度があります。
プロダクト開発をしていると、どうしても短期的に売上やユーザー価値を高める施策や、優先度の高いタスクに着手してしまいがちです。 そこでエンジニアと経営陣が相談し、導入されたのが『技術投資10%ルール』です。このルールは、エンジニアの工数の10%を、コードの改善や中長期的に導入したい技術の検証など、エンジニアが自ら判断した技術的挑戦に割り当てるルールです。個々人の技術投資の積み重ねは、組織の挑戦意欲とスキルを高めます。この個人の"10%"の自由な取り組みが、技術負債の解消やチーム開発の効率改善に繋がることはもちろん、サービス成長のロードマップに組み込まれることで、組織の成果にも繋がっています。
この制度を使うことで、趣味の延長線上において仕事ができる感覚が好きです。私はPythonのOSSライブラリにコントリビュートして技術投資を行っていました。
しかし、インフラの仕事ではIaCやシェルスクリプトなどを除いて、意識的にコードを書こうとしない限りコードを書くことはあまりありません。
そこで私はインフラの仕事で積極的にPythonを書くことを意識しました。成果物の例は以下です。
インフラの仕事のおまけでPythonを書くことが多かったので、Pythonを書くこと自体が仕事という感覚はあまりありませんでした。
しかしソリューションチームでは「Python書きてーなあ」が動力として仕事を生み出せています。まさに技術投資が拡大したような感じです。
越境とソリューションチーム
ソリューションチームの行なっていることは会社に紐づくエンジニアリングです。リブセンスにはもともと越境という会社の文化があるため、このような仕事がやりやすい環境にあります。わかりやすい例ですとセールスの方でもSQLを使うのが普通です。
リブセンスには創業当初から『越境』という言葉を大切にする文化があります。 越境は、チームや事業の垣根を超えて課題解決のために試行錯誤をすることだけではなく、職種をも越えていくことを意図しています。
これにより、エンジニアは部門やプロジェクトの枠を超えて、自由にアイデアを実現することができます。
ソリューションチームでは、この「越境」をさらに一歩進め、会社に紐づくエンジニアリングを推進しています。このような環境において楽しいのは、エンジニアが一から仕事を創出できることです。具体的なプロダクトの要件に縛られず、自由な発想で技術選定や開発を行うことが可能です。
私の場合は「Python書きてーなあ」が原動力で、先ほどの株価通知くんを作成しました。しかし、これはあくまで一例であり、他にも様々な活動が行われています。
直近ですと、Q by LivesenseをWordPress on EC2からHugo on Cloudflare Pagesに置き換えた例があります。これにより、オウンドメディアのメンテナンスの負担を軽減することができました。
他にもConfluenceのSaaS移行において、リダイレクターを自作し、OSS公開した例もあります。
ソリューションチームでは、必ずしもコードを書く必要はありません。技術を使って課題を解決することが目的です。例えば、情シスと兼任しているメンバーは、SaaSの導入を進め、バックオフィスの運用を改善するプロジェクトを進行中です。
では、株価通知くんを含めて私が行なった具体事例を紹介します。
具体事例
株価通知くん
株価通知くんは以下のような仕様で作成しました。
- 会社の株価を取得
- データフレーム化
- mplfinanceを用いてデータフレームをグラフ化
- Slackに通知
まず株価を取得し、それをデータフレーム化します。以下はデータフレームの例です。
日付 | 開始価格 | 高値 | 安値 | 終値 | 出来高 |
---|---|---|---|---|---|
2024-05-14 | 223.0 | 234.0 | 223.0 | 234.0 | 38300 |
2024-05-15 | 252.0 | 253.0 | 235.0 | 236.0 | 169100 |
2024-05-16 | 235.0 | 238.0 | 231.0 | 234.0 | 31300 |
2024-05-17 | 232.0 | 235.0 | 231.0 | 234.0 | 17800 |
2024-05-20 | 247.0 | 248.0 | 239.0 | 241.0 | 51400 |
2024-05-21 | 241.0 | 247.0 | 240.0 | 243.0 | 28800 |
2024-05-22 | 243.0 | 243.0 | 238.0 | 239.0 | 8700 |
2024-05-23 | 236.0 | 240.0 | 236.0 | 239.0 | 7500 |
2024-05-24 | 238.0 | 239.0 | 236.0 | 237.0 | 10200 |
2024-05-27 | 237.0 | 238.0 | 221.0 | 224.0 | 139900 |
2024-05-28 | 226.0 | 228.0 | 223.0 | 225.0 | 13700 |
2024-05-29 | 225.0 | 225.0 | 221.0 | 221.0 | 14700 |
2024-05-30 | 220.0 | 221.0 | 219.0 | 219.0 | 19400 |
2024-05-31 | 218.0 | 221.0 | 215.0 | 219.0 | 52500 |
2024-06-03 | 217.0 | 222.0 | 217.0 | 222.0 | 27700 |
2024-06-04 | 221.0 | 222.0 | 220.0 | 222.0 | 10300 |
2024-06-05 | 222.0 | 222.0 | 220.0 | 222.0 | 22000 |
2024-06-06 | 221.0 | 222.0 | 219.0 | 221.0 | 9500 |
2024-06-07 | 219.0 | 221.0 | 219.0 | 221.0 | 7900 |
2024-06-10 | 219.0 | 222.0 | 219.0 | 222.0 | 16100 |
2024-06-11 | 222.0 | 224.0 | 221.0 | 222.0 | 9000 |
2024-06-12 | 221.0 | 222.0 | 219.0 | 220.0 | 29200 |
2024-06-13 | 220.0 | 221.0 | 218.0 | 219.0 | 10700 |
データフレームをmplfinanceを用いてグラフ化します、こだわりポイントとしてグラフの色を会社のカラーにしました。
def plot_candlestick_chart(dataframe, filename, company_name): # 会社のカラーを指定するカスタムスタイルを定義 market_colors = mpf.make_marketcolors(up='#E45E19', down='#1BA1E6', inherit=True) # グリッドラインのスタイルを定義 style = mpf.make_mpf_style(marketcolors=market_colors, gridstyle='-', gridcolor='#CCCCCC') savefig_dict = { "fname": filename, "dpi": 100, "bbox_inches": "tight" } title = f'{company_name} - 1 month candlestick' mpf.plot(dataframe, type='candle', style=style, title=title, ylabel='Price', savefig=savefig_dict)
この画像をSlackに投稿します。
def upload_image_to_slack(file_path, channel, token, text, filename): with open(file_path, "rb") as file: files = {"file": file} params = { "token": token, "channels": channel, "filename": filename, "initial_comment": text, "title": "今日の株価", } response = requests.post(url="https://slack.com/api/files.upload", data=params, files=files) return response
このPythonをコンテナを使用したLambdaで動かしています。Lambdaはランタイム毎にOSが異なり、対応している実行環境上でライブラリをインストールしないとエラーになってしまうというトラップがあります。Layerを使う方法とコンテナを使う方法がありますが、今回はLambdaのデプロイツールであるlambrollとの相性の良さからコンテナを使用しました。
このLambdaをEventBridge Schedulerを用いて毎日実行するように設定しました。
メンション集約くん
これも出社時、バックオフィスの人と競艇行きたいですね〜と立ち話している時に生まれたものです。「グループメンションが多いと通知が多く追いきれない」という課題を解決するために作成しました。要件は以下でした。
- 大量のチャンネルからグループメンションが飛んでくる
- 1つにまとまってるとありがたい
- 契約周りのセンシティブな情報がある
- オープンチャンネルで一括で問い合わせを受け付けるのは難しい
これを解決するために、以下のような仕様でLambdaを使用し、バッチを作成しました。
graph TD; 事業部1 --メンション--> backoffice_slack_usergroup 事業部2 --メンション--> backoffice_slack_usergroup 事業部3 --メンション--> backoffice_slack_usergroup 事業部4 --メンション--> backoffice_slack_usergroup 事業部5 --メンション--> backoffice_slack_usergroup backoffice_slack_usergroup --任意の実行頻度でメンションを取得(メンション集約くん)--> lambda --データを格納--> AWS_S3((AWS S3)) AWS_S3 --> lambda --問い合わせの差分を任意の実行頻度で転記(集約メンション通知くん)--> メンション集約用のプライベートチャンネル
転記する際に発言のURLを転記することで、権限のない人には見られないようにしたのがポイントです。SlackのURLは以下のようになります。
# チャンネルに投稿された場合 https://hoge.slack.com/archives/${チャンネルID}/p${unix timestamp} # スレッドに投稿された場合 https://hoge.slack.com/archives/${チャンネルID}/p${unix timestamp}?thread_ts=${unix timestamp}
作っていてハマったことが1つあります。スレッドの場合はthread_tsを指定しなくても、発言はカードとして展開されるのですが、thread_tsを指定しないとリンクをクリックした際に、ランダムな場所に飛ばされてしまうということがありました。これはSlackの仕様なので、上記のようにthread_tsを指定することで解決しました。
また、作り終わってから気がついたことですが、ユーザーグループにアプリを入れ、そのアプリがメンションを受け取った起因で動かせば良かったのでは?と気がつきました。最近発表されたSlack PlatformであればSlack内にアプリを完結させることができるので、AWSにリソースを展開するのも不要です。これに関しては今後の仕事としてやってみたいです。
ユーザー管理システムの権限移譲
事業部1と事業部2が使っていた共通のユーザー管理システムがありました。当時横断部署だった情シスが管理していたのですが、事業部2が撤退。その後も名残で情シス管理になっていました。
しかしユーザー管理システムを使っているのは事業部1しかなかったので、その管理を事業部1付にしました。
これに気がついたのはユーザー管理システムのクラウド移行の担当が私だったからです。オンプレからAWSへの移行だけではなく、正しい運用まで導線を引いた形になります。
いわゆる落ちているボールを拾う仕事です。
今後について
本記事で挙げた私の仕事だけですと、面白ツールおじさん便利なツール屋さんで終わってしまうので、今後はより会社にインパクトを与えるエンジニアリングをしていきたいと思っております。
チームとして始まったばかりなので、まさに暗中模索の最中です。ただ、越境して初めて見えてくる課題は確かにありました。これらに対して1つ1つ技術を用いて解決していこうと思いました。