TECH PLAY

ニフティ株式会社

ニフティ株式会社 の技術ブログ

487

挨拶 はじめまして、新卒3年目サービスインフラチームのムサシです。 ツールのアクセス成功率を可視化したいなあ 先日私のチームでは、とあるツールのアクセス成功率をCloudWatchのダッシュボードに可視化しました。やったことは以下になります。 ① CloudWatchに流れているログを利用してメトリクスフィルターを作成する ② メトリクスを利用して、ログの発生回数から成功率のグラフを作成する ③ 一定の値を下回った場合にアラートを設定し、Slackに通知 ④ ダッシュボードに成功率のグラフとアラートの状態を表示する すべて説明すると長くなってしまうので、今回は①、②について手順、詰まったことなどを備忘録的に書いていこうと思います。これを書いているのは2024年1月末の情報なので画像・内容が古いこともありますがご了承ください。 ①CloudWatchに流れているログを利用してメトリクスフィルターを作成する フィルターパターンを作ろう まずはログをカウントするためにメトリクスを作ります。CloudWatchからロググループを選択しメトリクスフィルター内の「メトリクスフィルターを作成」から作ることができます。 パターンを定義という画面が出てくるので、抽出したいログに含まれる文字列をフィルターパターンに設定します。フィルターパターンは若干癖があるのですが、 一部の正規表現が使える ので複数のアラートをまとめて抽出したい場合に便利です。 ただし正規表現を利用したメトリクスは1つのロググループにつき5個までの制限があるので注意。 ## こんなエラーが出てつまづいた メトリクスフィルター「ほげほげ」を作成できませんでした。 Resource limit exceeded. 注記 クォータ メトリックスフィルターまたはサブスクリプションフィルターを作成するとき、ロググループごとに regex を含むフィルターパターンが最大 5 つあります。 メトリックスフィルターとサブスクリプションフィルターの区切りまたは JSON フィルターパターンを作成するとき、またはログイベントまたはライブテールをフィルタリングするとき、フィルターパターンごとに 2 つの regex の制限があります。 https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html もしログを新しく出す場合は以下の記事のように抽出しやすい形で出すと正規表現の枠を使い切らずに済みそうです。 Amazon CloudWatch Logs に出力するログは JSON 形式だと分析が楽になるかもしれない話 パターンをテストでは、どのログが引っかかるかを確認することができます。直近のログがテストデータの候補として表示されますが、「カスタムログデータ」を選択することでテストデータを自由に変える事ができます。あまり発生しないログ(処理に失敗したときのログなど)の場合はこちらを利用してフィルターパターンが正しいか確認できて便利です。 良い感じのフィルターパターンができたら次へ 次はメトリクスの設定を行います。オプションと書かれているデフォルト値とUnit以外が必須項目となります。埋めていきましょう。 まずは名前を入力します。フィルター名は後から変えられないので気をつけましょう。いくつか作ることを見越して命名ルールを決めておいた方が良いです。(1敗) メトリクス名前空間はフォルダみたいな感じでしょうか。既にメトリクス名前空間を作っている場合は、新規作成をオフにすると既存のメトリクス名前空間から選ぶ事ができます。今回はメトリクス名前空間を新規作成し、そこに作ったメトリクスを入れていきました。 メトリクスを参照するときには、このとき作ったカスタム名前空間の中に入ることになるので、その辺りも考えつつ名前を付けましょう。画像はメトリクス名前空間の意味がよくわからずに名付けしてしまった名前空間です。わかりやすい名前を付けましょう。 メトリクス名にもわかりやすい名前を付けてあげましょう。こちらはフィルター名と違い後から変更できそうでした。 メトリクス値には1を、デフォルト値には0を設定します。こうすることで、ログをカウントすることができます。 全て埋められたら次へ。確認画面に進むので、問題なければメトリクスフィルターを作成ボタンで作成完了です。 作成したフィルターはロググループの「メトリクスフィルター」で、ロググループごとに見る事ができます。後から編集したい場合もここからできます。 ②メトリクスを利用して、ログの発生回数から成功率のグラフを作成する 成功率を計算するための準備 成功率を出したい時、 ( ( 全体数 - 失敗数 ) / 全体数 ) * 100 で計算できます。初めは成功パターンをカウントしようとしていたのですが、成功とするログのパターンが多かったため、数が少なく絞り込みやすい失敗パターンをカウントする方向で進めていくことにしました。全体数をカウントするメトリクスと失敗パターンをカウントするメトリクスの2つが必要なので、これらを①で説明した手順で作成していきます。 ステータスコードやURLをフィルターパターンとして設定し、「アクセス失敗ログをカウントするメトリクス( m2 とする)」「ツールのアクセス全体のログをカウントするメトリクス( m1 とする)」を作成しました。 グラフを作ろう メトリクスができたら、グラフを作っていきましょう。CloudWatchのすべてのメトリクスを選択し、参照タブで先ほど作ったm2とm1を探してチェックを入れます。すると上にグラフとして表示させることができます。表示した各グラフはグラフ化したメトリクスタブで設定が変更でき、統計を「合計」にすることでログの発生回数をカウントすることができます。 全体数(m1)、失敗数(m2)が揃ったので、あとはこれを用いて計算したものをグラフとして出せばOKです。成功率を出すための式を作るため「数式を追加」ボタンを押します。関数などいろいろ選べますが、今回はシンプルな四則演算を設定したいため「空の式で始まる」を選択することにします。 グラフ化したメトリクスの欄に式 e1 が作成されました。 詳細の欄には数式が設定できます。この数式には既に参照したメトリクスを設定可能です。成功率の数式にメトリクスm2、m1を当てはめると、 ( ( 全体数 - 失敗数 ) / 全体数 ) * 100 = ( ( m1 - m2 ) / m1 ) * 100 となります。e1に ( ( m1 - m2 ) / m1 ) * 100 を数式として設定しましょう。成功率がグラフとして表示されれば完成です。 もし全くアクセスがない場合は 全体数が0になることで上手く計算されず、グラフが表示されないかもしれません。そのときはIF式を使うことで計算エラーを回避できます。IF式は IF ( n , n ≠ 0 のときの値 , n = 0 のときの値 ) のように使えるみたいです。今回は、アクセスが無い場合は問題なしとして成功率100%になって欲しいので IF ( m1 , e1 , 100 ) という式 e2 を新たに追加しました。e1のチェックを外して非表示にし、e2のみをグラフとして表示することで欲しいグラフを見ることができました。 終わりに 説明は割愛しましたが、この後アラート設定やダッシュボード作成をすることで、監視の手間や問題の把握までの時間を小さくする事ができます。アラートはSlackへ飛ばしているのですが、この後どうするかの相談や、なぜアラートが上がったのかというような情報共有もそのままSlack上で行えるため非常に便利です。 ぜひ試してみてください。 ~special thanks~ 手間取ってたらチームのタスクとしてやってくれたチームメンバーに感謝 ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も随時受付中! ニフティに興味をお持ちの方は キャリア登録をぜひお願いいたします! キャリア登録 connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
こんにちは、IaCお姉さんです。 CloudFormationにIaC ジェネレーターという新しい機能が出たので使っていきます。 IaC ジェネレーターについては、以下の公式ページをご覧ください。 https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC-write-only-properties.html 今回はLmabda関数をIaC化します。 コンソールからLambda関数を作成 言語はPythonを選んで、デフォルトのソースコードのまま作成しました。 CloudFormation IaCジェネレーターでテンプレートを作成 コンソールのIaCジェネレーターから「テンプレート作成」をクリックし、今回作ったLambda関数を選択し、テンプレートを作成します。 できたテンプレートがこちらです。 --- Metadata: TemplateId: "arn:aws:cloudformation:ap-northeast-1:999999999999:generatedTemplate/hoge" Parameters: LambdaFunction00iacgentest00hDmeyCodeS3BucketOneOftEfZZ: NoEcho: "true" Type: "String" Description: "An Amazon S3 bucket in the same AWS Region as your function. The\ \ bucket can be in a different AWS account.\nThis property can be replaced with\ \ other exclusive properties" LambdaFunction00iacgentest00hDmeyCodeS3KeyOneOfI1FJJ: NoEcho: "true" Type: "String" Description: "The Amazon S3 key of the deployment package.\nThis property can\ \ be replaced with other exclusive properties" Resources: LambdaFunction00iacgentest00hDmey: UpdateReplacePolicy: "Retain" Type: "AWS::Lambda::Function" DeletionPolicy: "Retain" Properties: MemorySize: 128 Description: "" TracingConfig: Mode: "PassThrough" Timeout: 3 RuntimeManagementConfig: UpdateRuntimeOn: "Auto" Handler: "lambda_function.lambda_handler" Code: S3Bucket: Ref: "LambdaFunction00iacgentest00hDmeyCodeS3BucketOneOftEfZZ" S3Key: Ref: "LambdaFunction00iacgentest00hDmeyCodeS3KeyOneOfI1FJJ" Role: "arn:aws:iam::999999999999:role/service-role/iac-gen-test-role-tzzzpewe" FileSystemConfigs: [] FunctionName: "iac-gen-test" Runtime: "python3.12" PackageType: "Zip" LoggingConfig: LogFormat: "Text" LogGroup: "/aws/lambda/iac-gen-test" EphemeralStorage: Size: 512 Architectures: - "x86_64" テンプレートを手直しする テンプレートを作成するとこのような画面になります。 黄色い枠の中にwarningが出ています。 The template contains properties that can be replaced with other mutually exclusive properties. Additionally, some optional properties were not included. You can download the template and edit it to modify the properties to suit your needs. 「このテンプレートはまだ未完成だから自分でなんとかしてね」と言っています。 「View warning details」をクリックしてみると、どうやら「Code/S3Bucket」と「Code/S3Key」は自分で値を用意しないといけないようです。 CloudFormationでLambda関数を作成する際、コードのアップロード方法として、以下の3種類があります。 S3からアップロード ECRのイメージとしてアップロード zipファイルをアップロード ですが、IaCジェネレーターから既存のLambda関数のテンプレートを作成する時に、コードがどうやってアップロードされたかは検知できず、「Code」部分にはS3からアップロードした場合のソースが作成されるようです。 (ECRイメージの関数もテンプレート化してみましたが、同様に「Code/S3Bucket」と「Code/S3Key」のパラメータでテンプレートが生成されました。) テンプレートを実際に使う時は、適宜アップロード方法を書き換えないといけません。 詳細はこちらのドキュメントを参照 https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC-write-only-properties.html 今回は、凝ったことはせずzipファイルでアップロードするようにテンプレートを書き換えます。 Lambda関数の画面からコードをコピーして、テンプレートの「Code」部分に貼り付けます。 Code: ZipFile: | import json def lambda_handler(event, context): # TODO implement return { 'statusCode': 200, 'body': json.dumps('Hello from Lambda!') } インポートする テンプレートが完成したら、インポートして、リソースをCloudFormationの管理下に置きます。 画面の「Import edited template」から、先ほど「Code」部分を編集したファイルをアップロードしてインポート完了です。 まとめ IaCジェネレーター、とっても便利なので皆さんも使ってみましょう^ヮ^ ただし、一部のリソースではテンプレート作成後に人力で修正を加えないといけないようです。 ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も随時受付中! ニフティに興味をお持ちの方は キャリア登録をぜひお願いいたします! キャリア登録 connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
Notionの管理者をしている石川です。 先日行われたNotion Japan チャンピオンズコミュニティアワード2023で「Notion導入推進賞」をいただきました! Notionチャンピオンズコミュニティとは Notionチャンピオンズコミュニティは、Enterprise利用している(なにかしらの有償プランに入っている)企業のチャンピオンが集まる公式コミュニティです。アンバサダーとは別のコミュニティとなってます。 参考: Notionチャンピオンズコミュニティ Notionアンバサダー Notion導入推進賞 トロフィーとお土産 受賞記念にいただいたクリスタルトロフィーは重量感あってとても綺麗 具体的な評価ポイントは教えてもらってないですが、モデルケースとなりやすい移行や導入時のノウハウを発信していったところが評価されたのかなと思ってます。 今後もこれに驕らず実運用の中でよいノウハウが出てきたらアウトプットしていきます! 参考リンク いままでNotion関係でアウトプットしたブログやスライドを以下にまとめました。 Notionのアップデートはとても多く一部古い情報になっている部分はありますが、導入や推進などのアクションは大きく変わるものでもないので、まだまだ参考になるかと思います。 2022-12-25 Notionで社内情報をスムーズに検索!移行前の大掃除と再配置で効率アップ – NIFTY engineering 2023-03-14 Notion全社導入に伴う移行とデータ整理のノウハウ | ドクセル 2023-04-27 NotionのWiki機能を使ったページ管理を考えてみる – NIFTY Tech Talk #10 – Speaker Deck 2023-11-08 Notionへのデータ移行体験談とTIPS | ドクセル 2023-11-18 Notionへのデータ移行を成功させる5つのポイント – NIFTY Tech Day 2023 – Speaker Deck ちなみに昨年アップデートがあったもの一覧は以下のURLから確認ができます。 アップデートがあるごとに、ちょくちょくフィードバック送っていたんですが、要望として挙げていたものが実現されると嬉しいですよね。昨年出た中だとユニークIDプロパティが一番嬉しかったです。 参考: 2023年 – Notionアップデート総まとめ90 ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
NIFTY Tech Talkは、ニフティ株式会社の社員が主催するトークイベントです。 本イベントではニフティグループの社員が業務を通じて学んだことを発信しています! 概要 日程:01/30 (火曜日) 12:00~13:00 配信方法:YouTube Live 視聴環境:インターネット接続が可能なPC/スマートフォン 参加方法 connpass にて登録をお願いいたします。 ※YouTube Liveにて配信いたします。 ※YouTube LiveのURLは決定後、参加者への情報欄に記載いたします。 こんな方におすすめ スクラムマスターの経験がある方 1on1に興味がある方 タイムテーブル コンテンツ 12:00 – 12:10 オープニング+会社紹介 12:10 – 12:25 LT: スクラムマスターの自律について 12:25 – 12:40 LT: 社内で行なっている1on1トレーニングについて 12:40 – 12:55 QAなど 12:55 – 13:00 まとめ+クロージング テーマ スクラムマスターとしての学習や研鑽活動について 登壇者プロフィール 西野 香織(登壇者) ニフティ株式会社 会員システムグループ 第2開発チーム ニフティのスペシャリストを任命するN1!制度にて、スクラムエヴァンジェリストを担当しています。 2019年スクラムマスターとして、ニフティへのスクラム導入を開始。 8チーム、エンジニア約30名以上に対しスクラム導入を支援しています。 アドバンスド認定スクラムマスター(A-CSM)資格所持。 三浦 拓実(登壇者) ニフティ株式会社 会員システムグループ 第2開発チーム お客様向けセキュリティサービスのシステム開発担当で、2023年3月に認定スクラムマスターを取得しました。 ニフティグループでは一緒に働く仲間を募集中です 新卒採用、キャリア採用を実施しています。ぜひ リクルートサイト をご覧ください。 ニフティエンジニアが業務で学んだことやイベント情報を エンジニアブログ にて発信しています! ニフティエンジニアのTwitterアカウントを作りました NIFTY Tech Talkのことや、ニフティのエンジニアの活動を発信していきます。 Tweets by NIFTYDevelopers アンチハラスメントポリシー 私たちは下記のような事柄に関わらずすべての参加者にとって安全で歓迎されるような場を作ることに努めます。 社会的あるいは法的な性、性自認、性表現(外見の性)、性指向 年齢、障がい、容姿、体格 人種、民族、宗教(無宗教を含む) 技術の選択 そして下記のようなハラスメント行為をいかなる形であっても決して許容しません。 不適切な画像、動画、録音の再生(性的な画像など) 発表や他のイベントに対する妨害行為 これらに限らない性的嫌がらせ 登壇者、主催スタッフもこのポリシーの対象となります。 ハラスメント行為をやめるように指示された場合、直ちに従うことが求められます。ルールを守らない参加者は、主催者の判断により、退場処分や今後のイベントに聴講者、登壇者、スタッフとして関わることを禁止します。 もしハラスメントを受けていると感じたり、他の誰かがハラスメントされていることに気がついた場合、または他に何かお困りのことがあれば、すぐにご連絡ください。 ※本文章はKotlinFest Code of Conductとして公開された文章( https://github.com/KotlinFest/KotlinFest2018/blob/master/CODE-OF-CONDUCT.md )を元に派生しています。 ※本文章はCreative Commons Zero ライセンス( https://creativecommons.org/publicdomain/zero/1.0/ ) で公開されています。
アバター
AWSコスト削減が巷で話題になってますね。 こんにちは、ニフティのAWS組織管理をしている石川です。 とんでもない削減額を叩き出したわけではないですが、長年やりたかったSPs(Savings Plans)とRI(Reserved Instance)の一括購入を行いましたので、そのときに得たノウハウを共有していこうと思います。 .article__content ul > li > ul > li { list-style: circle; } .article__content ul > li > ul > li > ul > li { list-style: square; } .article__content ul > li > ul > li > ul > li > ul > li { list-style: disc; } .article__content table thead th:first-child { background: #005AD7; } Before/After Before After 購入したもの SPsカバレッジ 21% 95〜99% Compute Savings Plans 3年 前払いなし RI(RDS)カバレッジ 15% 83% RDS Reserved Instance 1年 前払いなし 表1: SPs/RIのカバレッジ ※表の値は購入直後のもので現在はリソースが増えてカバレッジはちょっと下がっています ※RIをRDSのみにしているのは他のRIは利用アカウント数が少数でしたので一括購入していません 管理アカウントで一括購入することの是非 個々のAWSアカウントで買うか、管理アカウントで一括で買って共有したほうがいいのか問題。 各プロダクトチームが個々のAWSアカウントで買う場合、リソースの調整がしやすいためリソースごとに最適なプランで購入することができ割引効率がよくなります。一方、AWSアカウント×リソース×購入タイミングごとに購入タスクが発生するため、買い忘れが発生したり、少額だから買わないという状況が起きたりします。 組織管理者が管理アカウントから一括で買う場合、共有前提なので常時起動分はカバーできるように買うことができます。一方、再利用性を考慮して買うため柔軟なプランを選ぶことになり割引率が下がります。また会計上、共有して利用したAWSアカウントの費用として計算する必要があり、一手間増えます。 それぞれメリット・デメリットがあります。AWSアカウントやリソースを統制管理しているのか各チームで管理しているのか、現状適切に購入できているのかを見て、自身の組織に合う方を選ぶと良いでしょう。 ニフティの場合、各プロダクトチームごとに管理していましたが、AWSアカウントも多いためかカバレッジも低く、適切に購入できている状態とも言えなかったため今回一括購入を採用しました。 SPs/RIの仕様確認 高額な買い物となるため、AWSのSPs/RIの共有や利用のされ方をちゃんと理解しておかないといけません。個人的にここはしっかり把握しておきたかったという点をいくつか紹介します。 ※2023年11月時点で公式ドキュメントやサポートに確認した内容となります 共有されたSPs/RIが使われる順番 ざっくりいうと SPsよりRIが先に使われ、適用範囲が狭い順 に使われていきます。 割引共有がない状態での適用順番 Own: Reserved Instances Own: Savings Plans (EC2 Instance) Own: Savings Plans (Compute) 割引共有がある状態での適用順番 Own: Reserved Instances Share: Reserved Instances Own: Savings Plans (EC2 Instance) Share: Savings Plans (EC2 Instance) Own: Savings Plans (Compute) Share: Savings Plans (Compute) SPs/RIが適用される単位 1時間単位に割引効率が一番いいリソースから順 に割り当てられていきます。 消費した順に適用されるわけではないです。 即時割引額が反映されるわけではなく請求レポート上への反映は翌日以降。 正規化係数の仕様 購入期間だけ異なる同じプランのRIを買い増ししたときに合算されて適用されるかどうか。 購入期間が異なっていてもRIは正規化係数で合算されて適用される。 購入期間が異なっていて問題になるのは、RIの変更時に結合できない点。 例: 購入したRI 2023-09-01: t2.medium 1つ購入 2023-09-08: t2.medium 1つ購入(期間以外は上記と同じ設定) 稼働中のインスタンス t2.large 適用状況 2023/09/01-2023/09/08: t2.largeにt2.mediumのRI1つ分の割引が適用 2023/09/08以降: 先に購入されたRIが失効するまで: t2.largeにt2.mediumのRI2つ分の割引が適用 先に購入されたRIが失効した以降: t2.largeにt2.mediumのRI1つ分の割引が適用 参考: リザーブドインスタンス がどのように適用されるか – Amazon Elastic Compute Cloud リザーブドインスタンス の変更 – Amazon Elastic Compute Cloud 購入額の見積もり 基本的に管理アカウントで確認できる推奨値を買えば問題ないです。 推奨値と同じ値をコストエクスプローラーで出せないか試してみたところ、期間内の最小か平均で推奨値を出してくれているように見えました。スパイクは無視してくれるし、一時的に立ち上がっているものも無視してくれています。 そのため直近での変化がないかだけ購入前に確認するだけでよいです。ただ古いインスタンスは購入推奨に含まれない場合があるので、古すぎるものがないかはチェックして可能なら最新のインスタンスタイプに上げておきましょう。 今回は推奨値から以下のものを抜き足しした額を購入しました。 除外 直近でSPs/RIを購入していたもの 近いうちにリソースを削除する予定のもの ライセンスありのリソース 個別購入して管理したいAWSアカウント or リソース 追加 近いうちに個別で購入していたSPs/RIが切れるもの 直近で立ち上げられた永続利用するリソース 購入作業 買うだけではあるんですが、何度も確認や再計算して購入したのですごく疲れる作業でした。 SPsの購入は、見積もり額通りに時間あたりの費用を入力して買うだけなので比較的楽です。 ただ 額が大きくて購入ボタンを押すのがすごく怖かったです。。 ここの心理的負荷を下げるなにかが欲しい。 購入した翌日の昼過ぎくらいにコストエクスプローラーへ反映されていました。CURにも反映されていました。 購入した翌日に確認したコストエクスプローラー(時間単位) RDSのRIの購入は、推奨値のままだと購入台数多くて上限に引っかかりそうなので、合計正規化係数の変わらないインスタンスタイプと台数に変更後それぞれ購入するのですが、インスタンスファミリーやらエンジンやら組み合わせ数が多くてオペミスがすごく怖かったです。。 CLI で予約購入を入れて、画面で確認して問題なかったらそのまま購入、問題があったらキャンセルというフローにしたかったのですが、RDSのRIは予約購入機能なかった(EC2にはある)ため実現できず。予約購入というかRDSのSPsが欲しい。 想像より調整・確認工数や精神的疲労が大きかったので、買い足しは半年に1回の運用にするつもりです。 効果確認 コストエクスプローラーでは購入したSPs/RI単位の効果を調べにくいので、AthenaからCURにクエリーを投げて調べます。 購入したSPsごとにarnが振られるので、それを使ってSPsが適用されたリソースのオンデマンド価格(pricing_public_on_demand_cost)からSPsが適用された価格(savings_plan_savings_plan_effective_cost)と未使用分(savings_plan_total_commitment_to_date – savings_plan_used_commitment)を引いてコスト削減額を出せます。 SELECT savings_plan_savings_plan_a_r_n, sum(pricing_public_on_demand_cost) as pricing_public_on_demand_cost, sum(savings_plan_savings_plan_effective_cost) as savings_plan_savings_plan_effective_cost, sum( savings_plan_total_commitment_to_date - savings_plan_used_commitment ) as savings_plan_unused_cost, sum( pricing_public_on_demand_cost - savings_plan_savings_plan_effective_cost ) as savings_plan_reduction_cost FROM "aws_billing"."aws_billing_cur_month_parquet" WHERE year = '2023' and month = '11' and line_item_line_item_type != 'Tax' and savings_plan_savings_plan_a_r_n like 'arn:aws:savingsplans::{AWSAccountID}%' group by savings_plan_savings_plan_a_r_n RIも同じように管理アカウントのRDSのarnを使って、RIが適用されたリソースのオンデマンド価格(pricing_public_on_demand_cost) からRIが適用された価格(reservation_effective_cost)と未使用分(line_item_unblended_cost – reservation_effective_cost)を引いてコスト削減額を出せます。 SELECT reservation_reservation_a_r_n, sum(pricing_public_on_demand_cost) as pricing_public_on_demand_cost, sum(reservation_effective_cost) as reservation_effective_cost, sum( line_item_unblended_cost - reservation_effective_cost ) as reserved_unserd_cost, sum( pricing_public_on_demand_cost - reservation_effective_cost - ( line_item_unblended_cost - reservation_effective_cost ) ) as reserved_reduction_cost FROM "aws_billing"."aws_billing_cur_month_parquet" WHERE year = '2023' and month = '11' and line_item_line_item_type in ('RIFee', 'DiscountedUsage') and reservation_reservation_a_r_n like 'arn:aws:rds:ap-northeast-1:{AWSAccountId}%' group by reservation_reservation_a_r_n 費用の付け直し 管理アカウントでSPs/RI一括購入すると、unblended cost(非ブレンドコスト) では管理アカウントの費用として請求されます。組織内のAWSアカウントに共有されて使われた分は、それぞれのAWSアカウントの費用として計算したいので、内部的に請求費用の再計算を必要があります。 サクッと出すには amortized cost(償却コスト) を使うのが良いです。前払いでも月ごとに期間按分してくれます。amortized cost は便利な項目ではあるものの、なぜかCURには amortized cost という列がありません。なにか調査したいときにCURで同じような値(完全に同じ値は出せなかった)を出すには、そこそこ複雑なSQL書く必要があります。 最終的にどの数字を元に費用の付け直しをするかは社内で相談して決めましょう。 -- 擬似amortized cost算出、前払いには未対応 WITH b AS ( SELECT year, month, bill_invoice_id, line_item_usage_account_id, line_item_line_item_type, line_item_unblended_cost, CASE WHEN line_item_line_item_type = 'SavingsPlanCoveredUsage' THEN savings_plan_savings_plan_effective_cost WHEN line_item_line_item_type = 'SavingsPlanNegation' THEN 0 WHEN line_item_line_item_type = 'SavingsPlanRecurringFee' THEN ( savings_plan_total_commitment_to_date - savings_plan_used_commitment ) WHEN line_item_line_item_type = 'DiscountedUsage' THEN reservation_effective_cost WHEN line_item_line_item_type = 'RIFee' THEN reservation_unused_recurring_fee ELSE line_item_unblended_cost END AS line_item_unblended_cost_haihu FROM "aws_billing"."aws_billing_cur_month_parquet" WHERE year = '2023' and month = '11' ) SELECT year, month, bill_invoice_id, line_item_usage_account_id, SUM(line_item_unblended_cost) AS line_item_unblended_cost, SUM(line_item_unblended_cost_haihu) AS line_item_unblended_cost_haihu FROM b WHERE b.line_item_line_item_type != 'Tax' GROUP BY year, month, bill_invoice_id, line_item_usage_account_id ORDER BY bill_invoice_id, line_item_usage_account_id; line_item_line_item_type item type説明 差し替えて使っている値 SavingsPlanCoveredUsage SPsが適用された分のオンデマンド費用 (集計用ではなくデータとして残すために出力されていると思われる) savings_plan_savings_plan_effective_cost (SPsが適用された費用、要は使った分) SavingsPlanNegation SavingsPlanCoveredUsageを相殺する行 (集計用ではないので相殺しているのだと思われる) 0 SavingsPlanRecurringFee 前払いなしまたは一部前払い時に対応する定期的な時間単位の料金 SPsを購入したアカウントに表示される savings_plan_total_commitment_to_date – savings_plan_used_commitment (定期的な時間単位の料金から使った分を引いたもの、要は余った分) DiscountedUsage RI適用後の費用 reservation_effective_cost (RIを使った分) RIFee RI前払いなしか一部前払いで買った場合、時間単位の料金 reservation_unused_recurring_fee (RIが余った分) 表2: SQL内に使われているCURスキーマの説明 参考: 予約の明細項目を理解する – AWS コストと使用状況レポート 予約の詳細 – AWS コストと使用状況レポート Savings Plans について – AWS コストと使用状況レポート 見落としていた点 唯一見落としていたのがサポート費用の増大。 SPs/RIを一括購入した管理アカウントには請求書上ではかなりの額が乗るので、それに合わせてサポート費用も増大します。 仕方ないこととはいえ、どうにかならんかという気持ちではあります。最安を目指すなら専用のAWSアカウントを新設してサポートプランをベーシックのまま、そのアカウントで一括購入するのがよいかと思います。 最後に 今回ドキュメントからは判別つかない点も多く、AWSサポートにだいぶ助けられました、本当にありがとうございました。実際に購入してみないとわからない点や、CURの複雑な点はどうしても自力でどうにかするのは難しいですね。 おかげさまで見積もり通りミスなくSPs/RIが購入できて、カバレッジも高められ、それなりの額のAWSコスト削減ができました。 ただ定期的に買い足しや買い直しをしなければならない運用はありますし、精神的負荷も変わらずあります。ここは定型化やチェックフローを自動化できるところはして負荷を下げていきたいと思います。 最後にこれからSPs/RIを買おうとしている方達へアドバイス。 事業が成長し続ける限り、買った方が得なので買うなら早く買おう 割引額が少し低くても柔軟性があるほうが事前調整が楽 Compute SPsが再利用されないことはほぼないので許可が取りやすい 不要インスタンスは削除、稼働インスタンスも最適化してから買いましょう 参考: 適切なサイズ設定に関する推奨事項によるコストの最適化 – AWS コスト管理 SPs/RIの仕様をしっかり理解しておこう 大きい買い物になるのでちゃんと説明できるようになっておく必要がある 購入時の恐怖がちょっと和らぎます CURと戯れておこう コストエクスプローラーだけでは出せない数字もあるので、欲しい数字がありそうな列を思いつけるくらいになっておくとなにかと便利です 参考: AWS CUR Query Library :: AWS Well-Architected Labs 初めて買うなら少額買って適用具合や費用の付き方を調べよう 買ってからじゃないと体験できないことも多いので、買って学ぶほうが早い ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
はじめに こんにちは。ニフティに新卒で入社して5年目の佐々木です。今回はAWSのサービスの一つである CloudWatch についてコスト削減を行う方法を紹介します。 以前ご紹介したコスト削減手法ついては、以下のブログ記事をご参考ください。 S3編 CloudFront編 背景 ニフティではサービス基盤にAWSを活用しており、コスト削減のためにサービスのインフラ効率を追求する取り組みや、有志で取り組んでいる社内でのコスト削減勉強会なども実施しています。 CloudWatchのコスト削減においてのポイントや注意点について簡単にご紹介したいと思います。 この記事の内容 触れること CloudWatchのコスト削減方法 CloudWatchのコストを削減する上での注意点 実際に試した社内でのコスト削減事例とTips 触れないこと CloudWatch自体の詳細の説明 自社での詳しいインフラ構成(コスト削減が目的のため、今回は一般的なインフラ構成のご紹介に限らせていただきます) CloudWatchの基本 CloudWatchとは、AWS上で展開されるサービスを監視するサービスです。 CloudWatchのコスト削減 課金形態 サービスの運用にかかるコストを正確に把握するため、いつもの如くAWSの公式をチェックしましょう。 2024年1月現在では主に以下のようになっています。(ap-northeast-1の場合で無料利用枠は除きます) ログの収集(データ取り込み)に対する課金 例えば「 収集 (データインジェスト )」の場合はスタンダードへの配信で0.76USD/GB課金される 取り込むログのデータサイズの取り込み量に依存される ログのデータの保存に対する課金 取り込むログ量だけでなく、ログデータの保存期間や保存先によっても追加で課金対象となる 例えば、CloudWatchの「 保存(アーカイブ) 」の場合は0.033USD/GB課金される メトリクスに対する課金 最初の 10,000 メトリクスの場合0.30USD課金される アラームに対する課金 アラームが発生した最初の時間からが課金対象 例えば「 標準解像度メトリクスアラーム 」の場合はアラームメトリクスあたり 0.10USD課金される その他にも課金要素はありますが、主に重要なのはこの3つだと思います。 詳細はこちらの AWS公式の資料 をご参考ください。 コスト削減方法 次に、CloudWatchに対する一般的なコスト削減方法をご紹介します。 ログのサイズの削減 CloudWatch Logs は基本的には安価でかつ活用場面も多いかと思いますが、ログ量が多くなると保存に対する課金も無視できなくなってきます。 そのため、まずは大元のログの量そのものを減らす方向で検討すると良いかと思います。 ログのデータ保存方法の最適化 前述した通り、CloudWatchの「 収集 (データインジェスト )」の場合は0.033USD/GBですが、S3の「 S3標準 」の場合は0.023USD/GBなので、データ保存先としてはS3の方がコストメリットが大きいです。 監視方法や保存期間などによりますが、リアルタイムでの監視が必要がないデータはS3へ移行し、CloudWatch Logs に保存する期間をその分短く設定するなどの最適化を行うことで、コスト削減の効果が狙えます。 実際に削減する際には、ログ保存期間の社内ルールなどと照らし合わせつつ最適な保存方法を検討すると良いかと思います。 使われていないメトリクス・アラームの見直し こちらも一つあたりの単価は安いので積極的に使いたいところですが、量が多いとそこそこの料金がかかります。 もし環境ごとや機能ごとなどに個別にアラームやメトリクスなどを定義していた場合は、開発環境で明らかに必要のないアラートを既に使われなくなったメトリクスなどを見直してみても良いかもしれません。 実際に社内で試したこと ログサイズの削減 担当したサービスでは、バックエンドで定義したAPIのデータ取得のタイミングで、特定のINFOログを生成していました。該当のログでは、接続先のURLやユーザーIDなどのメタ情報を出力しています。 これは、障害等が発生した場合などに、該当のAPIが問題なく動作していることを確認するために必要で、CloudWatch Logs への出力によりログの解析ができるようになっています。 CloudWatchに出力することを想定したINFOログが冗長なものになっていたので、ログ出力時の文言などを調整することでサイズを最適化しました。 また、今回のコスト削減の方針としては、「開発者として必要な情報量は減らさずにコストのみを削減する」といったことを目的としています。 出し分ける必要のないログは1つのログに集約する 削減自体の内容としては非常に簡単に行えました。 一部のログで、単一のリクエストを送るタイミングで複数のINFOログを送信する仕様になっていたため、コスト削減のためこちらを単一のログに集約してみます。 出力する文言としては、分かりやすさを重視するために以下のような形でした。(以下の例では、Goのロギングライブラリである Zap を使用しています) logger.Info("msg", zap.String("id", "XXX-001"), zap.String("body", "接続先URL: "+url), ) logger.Info("msg", zap.String("id", "XXX-002"), zap.String("body", "生成パス: "+filePath), ) 上記の形だと、個別のログそれぞれに対してタイムスタンプ等の情報が付与されてしまうので、余分にログのサイズに計上されてしまう恐れがありました。 そのため、以下のように1つのログに集約することで、全体のログサイズを削減しました。 logger.Info("msg", zap.String("id", "XXX-001"), zap.String("body", "接続先URL: "+url + " 生成パス: "+filePath), ) このような形で、チームメンバーと都度相談しながら出力されるログを必要なものだけに整理することで、結果的にCloudWatch全体の約5%のコスト削減を達成することができました! 学んだ教訓とTips 全体を通しての感想ですが、CloudWatchは気軽に利用できる反面、コストについて考える機会はあまりなかったと感じました。ただ、課金内容を詳しく調べてみると「意外とここで指定したログがかなり料金を食ってるなー」みたいな箇所が割とすぐに分かったので、対処自体はしやすいですし取り組むモチベーションにもつながるのかなと個人的には感じました。 まとめ 今回はCloudWatchのコスト削減方法についてご紹介しました。 重ねてになりますが、現状のコストを分析することで不要なリクエストや課金形態の発見に繋がることがあるので、普段使用しているサービスをCostExplorerなどで確認することが大事だなと思います。 CloudWatchについては、やや課金形態が細かく様々な要因で課金発生することも多いので、サービスの要件とも照らし合わせて要不要を分析しながら改善していけると良いのかなと思います! 他のAWSサービスでもコスト削減事例が思いついたら別のブログ記事にする予定なので、また機会があれば紹介したいと思います! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
こんにちは!ニフティ基幹システムグループの佐藤です。 業務では、主にまかせて365, Wi-Fiルーターレンタルの開発・運用を担当しています。 最近、Zapierを使ってコードを書かずにSlackワークフローを投稿すると自動でNotionDBにアイテムが追加されるようにしてみたのでお話したいと思います。 背景 私の所属チームでは複数のサービスのシステムの開発・運用を担当しています。そのため問い合わせを各方面からいただくのですが、問い合わせ用のSlackチャンネルでそれらのやり取りをしていました。その度に管理用に使用しているNotionDBに問い合わせのアイテムを手動で作成していて、それが本当に大変でした・・・(手間がかかる・・・) 登場人物 Slackワークフロー Zapier スプレッドシート NotionDB この4つが登場します。 全体構成 以下のような構成になります。 手順 1. Slackワークフローを準備する Slackワークフロービルダーから、Slackワークフローを作成します。 全体のイメージとしてはこんな感じです。 フォームの内容にはサービスが複数あるので、ワークフローにサービス名のドロップダウンを仕込みました。(後で使います)あとは、タイトルと質問内容を記入欄として用意しました。 次に、「スプレッドシートに追加する」を選択します。 スプレッドシートは「フォームからスプレッドシートを選択する」にすると勝手に作られます。これを選択するとシートも勝手に作って指定してくれます。特定のスプレッドシートを選択したい場合は「自分のスプレッドシート」から選択すればできそうです。 列はフォームに入力した内容を「変数を挿入する」から選択してください。 こうすることで、フォームに入力された内容がスプレッドシートに投入されるようになります。 最後に、フォームを投稿したらチャンネルに投稿した内容が通知がされるようにします。 (全体イメージを参考にしてみてください) 2. Zapierを準備する 全体構成 トリガーにスプレッドシートを設定する Eventには「 New Spreadsheet Row 」を選択します。ワークフローで書き込まれるスプレッドシートとシートをここで指定します。そうすることでワークフローで行が追加されたらZapierが発火するようにできます。 問い合わせワークフローのSlackリンクを取得する NotionDBのアイテムから問い合わせスレッドを追いたかったのでこの処理を入れています。必要なければカットでもOK 結構無理矢理ですが、「 Find Message in Slack 」で検索をして問い合わせワークフローのスレッドを引っ張ってきています。タイトルが全く同じものでなければ複数取れないし、取れちゃっても一番最新のものが取れるようにしてるので大丈夫・・・! NotionDBにアイテムを作成する Eventには「 Create Database Item 」を設定します。 追加したいNotionDBを選択し、プロパティ・本文に追加する内容を設定します。 Nameはアイテムのタイトルに当たるものなので、スプレッドシートのタイトルを指定しました。 チームで使用している問い合わせ用のNotionDBには、プロパティに「サービス名」という欄を設けているので、そこにはスプレッドシートのサービス名を指定しました。 本文はContentから指定できるので、ここにはスプレッドシートの質問内容と手順2で取得したSlack問い合わせのURLが入るように設定しました。 アイテムが作成されたらSlackに通知されるようにする Eventには「 Send Channel Message in Slack 」を設定します。 Channelに手順2で取得した ChannelId を指定します。MessageTextには好きな文言を入れてください。アイテムのタイトルやNotionURLなどを文面に含めるとSlackからNotionに飛べるので便利で良さそうですね。 問い合わせフォームを通知したスレッドに通知する場合は、Threadに手順2で取得した Ts を指定すれば良いです。 感想 問い合わせがそこそこあるので、その度にアイテムを作成するのが大変だったので、自動化できてよかったです。githubとの連携もできるので、それについても今後ブログにできたらと思います。 ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
はじめに こんにちは。宮永です。 最近X(Twitter)やYouTubeで「公衆電話でダイヤルアップしてみた」のような投稿をよく見かけます。令和の時代になぜかブームが来ているようです。そこでダイヤルアップ接続ブーム(?)に乗って、「PPPサーバを立てて公衆電話から自宅にダイヤルアップ接続してみた」ブログを投稿します。 今回はUbuntuサーバと入手が容易なアナログモデムを用いてダイヤルアップサーバを構築し、実際に公衆電話から接続してみるところまでやります。 ちなみに、本来ダイヤルアップの接続先は契約したISPです。ニフティは2024年1月現在も ダイヤルアップ接続サービス を提供しているため、多くの「ダイヤルアップ接続してみた」投稿では接続先として使われていることが多いようです。 開発環境 作業は以下の環境で行いました。汎用的な作業しか行っていないので、異なっていても問題ないことが多いと思います。 ひかり電話 HGW PR-400MI Ubuntu 22.04.3 LTS アナログモデム ×2(サーバ用と公衆電話で接続する用) アナログモデムはブログの性質上特定の製品をおすすめできませんが、USB接続でドライバインストール不要の物を選んでください。Amazonで探すと選択肢はあまりないはずです。 方針 今回は、以下の流れで動くものを作成していきます。 mgettyがアナログモデムを接続したデバイスを常時監視し、着信があった際にpppdを起動する。 接続要求を受けたpppdはログイン可否をサーバ機に登録されているユーザか否かで判定し、パスワード認証する。 ログインできるユーザであれば設定したIPアドレスをクライアントに割り振り、内部ネットワークに加える。 開発 さっそく作業内容に入ります。 サーバ機のUbuntuは基本的な設定を完了し、root以外のユーザが登録してあるものとします。 アナログモデムをサーバ機に接続し、アナログモデムとHGWの「電話機2」接続口をモジュラーケーブルで接続します。接続口にある数字が内線番号になるため、今回接続したアナログモデムは内線番号2番になります。 HGWの設定 192.168.1.1 にブラウザでHGWの管理画面へアクセスし、ログインします。 電話設定→内線設定に移り、内線番号2の編集ボタンを押します。下の表にある自宅の電話番号の「着信音選択」が「IR」であることを確認します。 なお、HGWの管理画面へのアクセス方法やログインパスワードは環境により異なります。デフォルトの着信音はIRなので、もし管理画面にアクセスできない場合はそのまま次の作業に進んでしまっても問題ないケースが多いと思います。 パッケージインストール ここから先の作業はすべてrootで行います。 Ubuntuなのでapt-getでインストールします。mgettyはシリアルポートを監視するデーモンで、pppdは名前の通りPPPを扱うデーモンです。 # apt-get update # apt-get upgrade # apt-get install mgetty # apt-get instal ppp mgettyの設定 シリアルポートの確認 アナログモデムがどのシリアルポートに接続されているかを確認します。 # ls -lrt /dev/serial/by-id/ total 0 lrwxrwxrwx 1 root root 13 Dec 30 13:42 usb-Conexant_USB_Modem_24680246-if00 -> ../../ttyACM0 この例だとttyACM0になります。後で使うのでメモしておきます。 mgettyの起動設定 /etc/systemd/system/mgetty.service を以下のように編集します。 [Unit] Description=mgetty modem getty After=network.target [Service] ExecStart=/usr/sbin/mgetty -D ttyACM0 33600 Restart=always RestartSec=3 Type=simple [Install] WantedBy=default.target ExecStartの行にあるttyACM0の場所は、先ほど調べたシリアルポートの名前にします。 設定ファイルの編集 /etc/mgetty/mgetty.login に /AutoPPP/ から始まる行がコメントアウトされているので、そこを以下のように編集します。 /AutoPPP/ - a_ppp /usr/sbin/pppd auth -chap +pap login debug mgetty.configの設定 /etc/mgetty/mgetty.config に一番下に以下2行を追加します。 port /dev/ttyACM0 init-chat "" ATH OK ATS0=0Q0M0&D3&C1&M5&S1 OK ttyACM0の場所は、先ほど調べたシリアルポートの名前にします。 起動設定 systemd に新しいサービスを認識させ、有効にし、サービスを起動します。 # systemctl daemon-reload # systemctl enable mgetty.service # systemctl start mgetty.service pppdの設定 /etc/ppp/options に以下の設定を加えます。一部コメントアウトですでに書かれているものもあります。 ms-dns 8.8.8.8 proxyarp defaultroute usepeerdns pppdの認証設定 /etc/ppp/pap-secrets に以下の設定を加えます。似たような形でコメントアウトされているところがあるので、コメントアウトを外して編集します。 * server02 "" 192.168.100.200 この行は、<client_name> <server_name> <password> <IP_address>の順に記載します。 今回はPAMを使って認証するので、誰からでも受け付ける(ただし認証が通るかは別の話)ようにするために、<client_name>を*にします。同様の理由で<password>は””にします。 <server_name>にはサーバ名を記入します。この例だとserver02です。 <IP_address>はppp接続するクライアントに割り振りたいipアドレスを記述します。この例だと192.168.100.200です。サーバ機と同じサブネットに入るように、かつ重複がないようにします。 IPパケットの転送設定 以下の1行を実行します。 # echo 1 > /proc/sys/net/ipv4/ip_forward PAM(認証システム)の設定 nano /etc/pam.d/ppp に以下を追記します。 auth required pam_unix.so account required pam_unix.so session required pam_unix.so 動作確認 完成したので、あとは動作確認をするのみです。実は家の内線でも検証できるのですが、せっかくなので流行りに乗って公衆電話から接続します。 公衆電話はよくある緑色のものとグレーのものがあります(厳密にはピンク等もありますが省略)。今回は受話器を使うのではなくモジュラーケーブルを差し込む必要があるため、グレーの公衆電話を利用します。 しかしこれが全然見つかりません。 公衆電話の設置場所一覧ページ はNTT東日本が提供しているのですが、公衆電話のタイプまでは記載がありません。自宅の近くはすべて緑色でした。 調べてみると、都庁・ディズニーランド(本当に?)・品川駅にあるという噂を得たので、パソコンとアナログモデムと大量の小銭を持って品川駅に行きました。 あれだけ探していたグレーの公衆電話が3つもありました。パソコンを取り出し作業します。周りからの目がかなり痛いですが、気にしてはいけません。 公衆電話の端末接続口にある「アナログ」の方とアナログモデムをモジュラーケーブルで接続します。液晶に表示されている「データ通信」のボタンを押し、お金を入れます。 PC側も設定します。Windowsであれば、設定→ネットワークとインターネット→ダイヤルアップ→新しい接続を設定する→インターネットに接続します→ダイヤルアップ から簡単に設定できます。「ダイヤルアップの電話番号」に自宅の電話番号を入力します。ユーザ名とパスワードはサーバ機(Ubuntu)に登録されているユーザのものを入力します。 接続をクリックしてしばらく待つと接続が完了します。ここからは電話代がかかるのでサクサク作業していきます。といってもダイヤルアップ接続なので通信速度は遅く、今どきのデラックスなwebページは開けません。今回は検証のために軽量なサイトを見ることにします。 google検索は重くて使えないので、ブラウザにURLを直書きし、サイトが読み込まれるのをしばらく待ちます。(この時間が一番周りからの目が痛いです) じっと待っているとじわじわサイトが表示されます。これで検証完了です!恥ずかしいので急いで撤収します。 まとめ 完成しましたが、実は課題がいくつか残っています。何回か接続しないとうまくゲートウェイの情報が割り振られない時がある、ユーザを増やしたいときに逐次サーバ機のユーザを追加しないといけない等々、完ぺきではありません。設定をもっと見直す、radius認証に対応するといった作業が残っていますが、とりあえず完成ということにします。 PPPサーバに関する情報は古いものが多く調べても情報が出てこない場面が多かったので、ブログを書くことができてよかったです。(googleで「PPPサーバ」と調べても、PPPoEに関する情報ばかり出てきます……) デーモンの起動方法がinit.dからsystemdに代わっている、PAMではpam_pwdb.soではなくpam_unix.soを使うなど、現代のOSに合わせた設定を見つける作業にも時間を取られてしまいましたが、そういった知識を身に着けるきっかけにもなり楽しかったです。 みなさんもPPPサーバを立てて、令和に起きているダイヤルアップ接続ブームに乗りましょう! 参考文献 高原 利之, ひとりで作れる Linuxインターネットサーバー入門, ソシム, 2000年 ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
この記事は、 ニフティグループ Advent Calendar 2023 19日目の記事です。 はじめに こんにちは。会員システムグループの川上です。普段はiOS/Androidアプリ「マイ ニフティ」の開発をしています。(弊チームではエンジニアを 募集中 です!) 今回は、ISUCONという競技イベントにニフティ社員でチームを組んで参戦するにあたって実施した準備について紹介します。 イベント当日のレポートについては下記の記事をご覧ください。 ISUCON13にニフティ社員で参戦してみた ISUCONとは? ISUCONは制限時間8時間でWEBアプリケーションを高速化してスコア化された性能を競い合うコンテストです。今年は11月25日に ISUCON13 が開催されました。 ※ 「ISUCON」は、LINEヤフー株式会社の商標または登録商標です。 メンバー集め 私は去年の ISUCON12 が初参戦で、今年も出ようかな〜とゆるく考えていました。 そんなとき、ニフティの部活制度でISUCON部を作らないかという話が出て、その流れで部員の中から自分を含め3名の出場メンバーを集めることができました。 ちなみにニフティの部活には、フットサル部やe-sports部など幅広いジャンルがあります。 参戦するまでにやったこと 1. 初心者向けの問題を解いてみる 基礎的なノウハウから学ぶため、ISUCON本と呼ばれる下記の書籍を各メンバーが購入しました。 達人が教えるWebパフォーマンスチューニング 〜ISUCONから学ぶ高速化の実践 ザックリと全体を読んだ後、まずはシンプルな問題でISUCONの典型的な流れを体験することにしました。そのため、ISUCON本にも登場するpixiv株式会社の社内ISUCON「private-isu」を解くことから始めました。 https://github.com/catatsuy/private-isu 進め方は初出場のメンバーがドライバー、それ以外のメンバーがナビゲーターをして、実際のISUCONの流れに沿う形で学習しました。 例えば、下記のような内容です。 マニュアル確認 systemctl・journalctlをはじめとした基本的なコマンド alp・pt-query-digest等の計測ツールの使い方 mysqlやnginxの設定 インデックス追加、N+1の解消 また、理解をアウトプットする場として、社内でハンズオンを開催しました。そのときの様子はぜひ下記の記事をご覧ください。 ニフティ株式会社 社内ISUCONを実施しました! 2. 過去問を解いてみる ISUCONにおいて最も効果のある練習法は過去問を利用した素振りだと思います。 私のチームでも、もちろん素振りをしました。今回は技術的に新しいコンテストの方がマッチしているため、ISUCON 11予選と12予選を実施しました。 https://github.com/isucon/isucon11-qualify https://github.com/isucon/isucon12-qualify 環境の構築はAWS上に行い、下記のリポジトリのAMIを利用させていただきました。 https://github.com/matsuu/aws-isucon/tree/main この時点では、時間制限を設けることがなく、気が済むまで思いついた改善を試していきました。練習した項目は主に次の項目です。 nginxによる静的画像の配信(認証なし/あり) キャッシュ戦略(Redisなど) 外部コマンド呼び出し解消 インデックス追加、N+1の解消、テーブルの変更 解いた後は公式の解説を読み、実施できていなかった改善を挑戦しました。 本当はその後、本戦の問題や8時間制限での素振りをした方が良かったのですが、時間の都合により叶わずでした。 3. 本番の直前準備 本番1週間前には下記のようなことを改めて振り返りました。 デプロイ等のスクリプト準備 初動の役割分担 再起動試験のタイミング デプロイ等のスクリプト準備 本番中は「ベンチ → 計測 → 修正 → デプロイ」のサイクルを大量に回すため、それぞれを実行する時間を短縮することは重要です。対象のサーバーは複数台あるので、手動で行うより一括で実行できる方法を準備しておく必要があります。 今回は実行内容を4つに分割して用意しました。(ベンチはISUCON公式コンソールから実行されます) プロビジョニング デプロイ(ファイル同期とサービスのrestart) ログのtruncate 計測(alpやpt-query-digest等の実施) 私のチームではAnsibleの知識が疎かったため利用せず、練習段階ではGithub Actionsで実行していました。しかし、Actionsは立ち上がるまでの時間が長く、待ち時間が非効率に感じたため、シェルスクリプトに落ち着きました。計測だけはそのままGithub Actionsで行い、自動でIssueに結果を作成するようにしました。 また、シェルスクリプトを含めたリポジトリはテンプレートリポジトリとして、簡単に複製できるようにしておきました。 初動の役割分担 初期段階では未知のアプリケーションがサーバーに動作している状態から始まるため、可能な限り早く必要な情報を取得して、改善に入れるように役割分担が必要です。 私のチームでは次の3つで役割を分担して、やることをNotionのチェックボックスで管理するように認識を事前に合わせておきました。 サーバーから必要なファイルの取り込み・デプロイスクリプトの整備 ソースコード解読、SQLの抽出 当日マニュアル読み、アプリを触ってみる 完了時間の目標も定めて、1時間以内にデプロイスクリプトが動作し、並行してアプリの気になる点やマニュアルの概要をNotionに抽出することにしていました。(実際にはメンバーが最速で終わらせてくれて、10分ほどでデプロイできるようになりました) 再起動試験のタイミング ISUCONには競技終了後にいくつか追試項目が存在します。そのなかに主催者が全サーバーの再起動後にベンチマークを実施して、再現スコアが最終スコアの75%以下の場合は失格になるという内容があります。 全チームに対して行う追試項目 再起動後の負荷走行でfailした場合 再現スコアが最終スコアの75%以下の場合 envcheckを利用したサーバ環境の確認 最終スコアで上位のチームに対して行う追試項目 負荷走行実行時にアプリケーションに書き込まれたデータが、サーバー再起動後に取得できない場合 https://github.com/isucon/isucon13/blob/main/docs/cautionary_note.md#追試 実は私が去年参加したチームではこの再起動試験でfailになってしまい、ランキング外になってしまったという経験があったので、今回は17:00には一度再起動を試すように決めました。本番当日は焦りもあるので、忘れないように連絡に利用していたDiscordにもリマインダーを仕込みました。 おかげで、当日はリマインダーが来た時刻に再起動試験を行い、無事failになることなく追試OKでした。 おわりに この記事では、私のチームがISUCON13本番までに実施した内容を振り返りました。事前の準備を固めておくことで、去年参加した際より、本番でスムーズに改善に取り組むことができ、見落としも少なくすることができました。 ちなみに当日の結果は661チーム中81位でした。 25,674  nisucon-bu ISUCON13 受賞チームおよび全チームスコア ISUCONは参加するたびWEBアプリケーション開発に足りないスキルを知ることができる貴重な機会だと思っています。最近は過去問も実施しやすい環境が整っているため、ぜひ未経験の方も体験してみてください! ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
この記事は、 ニフティグループ Advent Calendar 2023 22日目の記事です。 こんにちは。ニフティ会員システムグループの増井です。 みなさん業務や趣味でPythonを使っていますか。 高い汎用性とシンプルな文法で知られるPythonは、データ分析や機械学習のプロジェクトから、Web開発、さらには日々の作業を自動化するスクリプトまで、幅広い分野で活躍しています。 私の所属するニフティ契約者向けオプションサービスを開発するチームではサーバーサイドロジックを記述する言語としてPythonを採用しています。 今回のブログはそんなPythonの超基礎的な話です。 動機 先日、他の人が書いたPythonのテストコードを書いていてこんなことがありました。 with self.assertLogs(logger, level='WARNING') as log: response = obj.request(HogeHogeClass(param=some_value)) # responseの確認 self.assertIsInstance(response, HogeHogeResponse) self.assertEqual(response.fugafuga, 0) 自分「なんでresponseがwithブロックの外で参照できてるの?」 これ、ちゃんとPythonの仕様を理解している人からしたら至極当たり前のことかもしれないのですが、withブロックの中で定義した変数はwithブロックを抜けたあとも参照できます。 しかし自分はwithのコードブロックはスコープを形成するものだと思い込んでいたので、このコードを読んで非常に違和感を感じたのです。 また、ifやfor, while, tryブロックについても自分の直感に反してスコープを形成しないということに気づきました。 そこで自分への戒めを込めてPythonのスコープについてという初歩的な記事を書こうと思ったのでした。よく理解している人は笑いながらお読みください。 主な対象者 初学者 他の言語を書ける状態からPythonを速習で学んだのでちゃんと仕様を理解できている自信がない人 Pythonを書いているが他の言語も並行して書いているのでよく言語間の仕様がごっちゃになる人 スコープとは 基礎的な話なのでまず変数のスコープについての説明も書いておきます。 スコープとはその変数が参照可能な範囲のことです。 アセンブリのような低レイヤーな言語を除いて大半の高級言語に変数スコープはあると思います。 例えばJavaだとif文などで {} で囲われた中で宣言された変数は {} 内のみで有効で、{} を脱出すると寿命が尽きてその変数は参照できなくなります。 なぜ今まで気づかなかったか 自分が冒頭で書いたようなPythonの仕様に今まで気づかなかった大きな理由は、 これまではコードを1人で書くことが多かった 自分は数ヶ月前に中途で入社した者で、前職では社内に手を動かしてコードを書ける人があまりいなかったため自分一人でコーディングすることが多かったです。 先ほどのようなコードを一人で記述するならいつもこう書いていました。 response = None with self.assertLogs(logger, level='WARNING') as log: response = obj.request(HogeHogeClass(param=some_value)) # responseの確認 self.assertIsInstance(response, HogeHogeResponse) self.assertEqual(response.fugafuga, 0) with句の中で値を入れる変数をwithの外で予め宣言しておき、ブロックスコープ(と思い込んでいる)の外でも確実に参照できるようにします。 実際にこれでも問題なく動くのでずっと気づくことができなかったのです。 また、最初に学習したときにwithを抜けた後にwithの中の変数を参照しているようなサンプルコードを見たことはあるが使われている変数はwithの前のどこかで宣言されているもの、と暗黙的な前提を置いてコードを読んでいた可能性もあるでしょう。 Pythonのスコープ まず改めてPythonについて調べていて個人的に少し衝撃的だったのは Pythonにブロックスコープは存在しない ということです。ブロックスコープとは変数が定義されたブロックの中でのみアクセス可能で、外側からアクセスできない範囲のことを指します。 ブロックとはPythonではインデントされたコードの塊、Python以外の多くの言語の場合はコードのまとまりを中括弧 {} で表すものが多いと思いますがその場合は {} で囲まれた部分の塊です。 Pythonにあるスコープは以下の4種類です。 ローカルスコープ 関数内で定義された変数。関数が呼ばれると新しいスコープが作成され、関数が終了するとそのスコープも終了する。 def function() -> None: a = "nifty" function() print(a) # エラー エンクロージングスコープ ネストされた関数(内部関数)の外側にある関数内でスコープが作成される。内部関数が外側の関数の変数を参照できるが、内部関数からは外側の関数のローカル変数を変更することはできない。 def outer_func() -> None a = "nifty" def inner_func_read() -> None print(a) # nifty def inner_func_write() -> None a = "another_isp" # エラーにはならないがaはouter_func()直下のaとは別物として扱われる print(a) # another_isp inner_func_read() inner_func_write() 通常は関数をこのようにネストして書くことは少なく、主にlambda式を記述するときに意識する。 グローバルスコープ モジュールレベルで定義された変数。プログラム全体からアクセス可能。 a = "nifty" # グローバル変数 def hoge() -> None: print(a) # nifty ←グローバルに宣言された変数を参照できる a = "another_isp" # 同名の変数が初期化されるとhoge()内のローカル変数扱いとなりグローバルなaとは別物になる hoge() print(a) # nifty def fuga() -> None: global a # global文でグローバルに宣言されたaを使うことを明示する a = "another_isp" # グローバル変数aの値が変わる fuga() print(a) # another_isp ビルトインスコープ Pythonの組み込み関数や属性にアクセスするスコープ。 グローバルスコープよりもさらに広い。 以下のコードではmain.pyでhogeモジュールをインポートしてグローバル変数を参照しています。 hoge.py a = "nifty" #グローバル変数 main.py import hoge print(hoge.a) # nifty しかし、モジュール名を指定しないと参照できません。 main.py import hoge print(a) # モジュールを指定しないとエラー そこでhoge.pyでbuiltinsをimportしてビルトインスコープに加えるとimportさえしていればモジュール名を指定しなくても参照できるようになります。 hoge.py import builtins builtins.a = "nifty" main.py import hoge print(a) # nifty クラスとカプセル化について もう一つ、スコープに絡めてクラスを作る上で陥りがちな罠を紹介しておきます。 主に他の言語でオブジェクト指向のものを書いたことがある人向けの内容になります。 Pythonでclass直下に宣言されている変数はクラス変数 これはオブジェクト指向言語をメインで書いている人が陥りがちな罠だと思いますが、まず以下のコードを見てください。 class TestClass: _a = "nifty" def set_a(self, value: str) -> None: self._a = value def get_a(self) -> str: return self._a instance = TestClass() instance.set_a("another_isp") print(instance.get_a()) print(instance._a) print(TestClass._a) 出力はどうなると思いますか。 まず print ( instance . get_a ( ) ) の部分は another_isp が出力されることが分かると思います。 では print ( instance . _a ) の部分はどうなるでしょうか? Pythonではクラス内でプライベートな使い方を意図した変数には「_」を付ける慣習があるのでそれを考慮するとエラーが出力されそうですが実は 「_」を付けるのはあくまで慣習に過ぎず、言語の機能的に変数をプライベート(参照可能範囲をクラス内に限定)にすることはできない のです。 よってエラーにはならずちゃんと文字列が出力されます。 another_isp print ( TestClass . _a ) はどうでしょうか。 _a はインスタンスに属する変数なのでエラーでしょうか。 これもちゃんと出力されます。 nifty 「あれ、_ a は”another_isp”で上書きしたはずでは…」とも思うかもしれません(数週間前の自分なら思っていました) Pythonではクラス直下のフィールドに定義した変数はクラス変数 Javaのようなメジャーなオブジェクト指向言語では static キーワードなどを付けることによって初めてクラス変数になりますが、Pythonでは変数に対して明示的に static を付けることがありません(メソッドに対しては @ staticmethod がありますが)。 そういった事実を知らずにオブジェクト指向脳で上記のコードを読むと TestClass のインスタンス変数 _a に set_a ( ) で値をセットしているように見えますが クラス変数 _a (”nifty”で初期化されている) インスタンス変数 _a ( set_a ( ) をした時点で初めてインスタンスに変数が追加されている) の2つの変数が別々に存在している状態になっています。 ネームマングリング クラスを定義してオブジェクト指向的な書き方をしているのに変数をプライベートに出来ないのは不便です。そこでPythonではネームマングリングと言って変数の名前を自動で書き換えることで参照しづらくする(しかし厳密にプライベートにはできない)機構が備わっています。 class TestClass: __a = "nifty" def set_a(self, value: str) -> None: self.__a = value def get_a(self) -> str: return self.__a instance = TestClass() instance.set_a("another_isp") print(instance.get_a()) # another_isp print(instance.__a) # エラー print(TestClass.__a) # エラー print(instance._TestClass__a) # another_isp print(TestClass._TestClass__a) # nifty 変数名の先頭に「__(アンダースコア2つ)」を付けて「__name」などとすることで「_(クラス名)__name」という変数に内部的に置き換えることができます。 普段からプライベート変数を定義するとき当たり前にこうしている人にとっては「未だにアンダースコア1つでプライベートの意味を持たせてたの!」と思われてしまいそうですが。 ちなみに上記のコードでクラス変数とインスタンス変数がそれぞれ別個に作られるのは先ほどと同様です。 まとめ 以上、Pythonのスコープやクラス変数で陥りがちな罠についてでした。 冒頭で述べたようにちゃんと理解している人にとっては笑ってしまうような内容だったかもしれませんが、言語の仕様は今一度しっかりと確認してから使いたいですね。 今後新しい言語を学習するときも既存の言語の仕様から思い込みで判断していないか気をつけながら学んで行きたいところです。 ニフティでは私のチーム以外にもPythonを使った開発をしているチームが数多くあります。Pythonを使ったWebサービスの開発などに興味がある方はぜひ下のリンクからお気軽にご連絡ください! ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
この記事は、 ニフティグループ Advent Calendar 2023 25日目の記事です。 概要・はじめに 開場! 共通セッション ニフティの過去・現在・未来 KDDI共同講演:@￰niftyメール基盤移行プロジェクト 生成AIが切り拓く未来〜AWSにおける機械学習と自然言語処理〜 職種と企業を飛び越えたNTT Comとの新規ビジネス共創 Expert Tech Talk!〜ニフティスペシャリスト対談〜 2レーン開催セッション ポイントサービス設計の異常な挑戦 または我々は如何にして心配するのを止めてドメイン駆動設計を愛するようになったか ニフティ社内ISUCON開催への道のり ニフティLT大会大公開スペシャル クロージング セッション終了後 抽選会 懇親会 まとめ 概要・はじめに こんにちは。NIFTY Tech Day 2023 実行委員の西根です! 11/18(土)に初のハイブリッド開催でテックカンファレンス「NIFTY Tech Day 2023」を開催しました! ご参加いただきありがとうございました。 今年は会場とオンラインのハイブリッドで開催し、配信も一部2レーンで行うという初めての試みでしたが、無事大きな問題もなく終了することができました! NIFTY Tech Day 2023 では、ニフティのいまと未来をお伝えするセッションを15個ご用意いたしました! この記事では実施されたセッションの様子や裏話をお届けします アーカイブ動画の再生リストは こちら 発表資料は こちら 開場! 9:30から受付を開始しました! 続々と参加者の方も来てくださり、運営的にはホッと一安心でした(笑) 受付の様子です!ノベルティや名札をお渡ししました! 受付では、オリジナルのトートバッグに来場特典のノベルティを入れてお渡ししました! 今回のノベルティ内容は、NIFTY Tech Book #1・クリアファイル・パンフレット・ステッカー・ニフティラベルのお水と豪華内容!!! NIFTY Tech Book #1 は オンラインでも配布 されていますので、ご興味のある方はぜひご一読を! ノベルティが入っているトートバッグ。 こうして揃えると、イベントやってるんだなという気持ちになりました…! 可愛い女性のイラストが描かれた NIFTY Tech Book #1 です NIFTY Tech Book #1 の執筆の経緯などは こちら から確認いただけます! 今年は会場参加の方もいらっしゃるということで、前日までにconnpassにて参加登録をしてくださった来場者の方には、connpassの名前とアイコンを記載したオリジナルの名札をお渡ししました。 実はこの名札は前日に印刷所へ駆け込んで作成しました 共通セッション ニフティの過去・現在・未来 開場して最初のセッションは弊社代表取締役社長の前島による「ニフティの過去・現在・未来」です! 社員にも大人気の社史講話を拡張し、ニフティの創業期から現在、これからの展望を社長直々にお話しました。 現在計画中のプロジェクト の初公開の場でもありました! パネルでイベントらしい雰囲気に 朝一番のセッションですが、会場には参加者がたくさん!新プロジェクトのお話には驚きと喜びの声がXでも上がっていました! KDDI共同講演:@￰niftyメール基盤移行プロジェクト 続いて、KDDI株式会社 プラットフォームエンジニアリング部 足立様と弊社メール基盤移行チームマネージャーによる「KDDI共同講演:@￰niftyメール基盤移行プロジェクト」です! ニフティは今年@￰niftyメールの基盤移行を行いました。 その背景や、それぞれのメールシステムについての発表と、裏話や苦労について対談形式で語られています 大規模な基盤移行を終えたお二方は、まさに苦楽を共にした戦友のようでした! 登壇者は黒いTシャツでした! 生成AIが切り拓く未来〜AWSにおける機械学習と自然言語処理〜 午前中ラストのセッションは、アマゾンウェブサービスジャパン合同会社 ソリューションアーキテクト 馬様、シニアソリューションアーキテクト 石見様の2名と弊社 N1! Machine Learning Product Engineerの3名によるディスカッション「生成AIが切り拓く未来〜AWSにおける機械学習と自然言語処理〜」です! 前半はニフティニュースの記事要約について2022年までと2023年の比較を行い、AWS様からはAWSの生成系AIの開発・運用支援ができるサービスなどについてお話がありました 後半は3人のディスカッションパートでした! ニフティでも様々なサービスでAWSを利用しています! 職種と企業を飛び越えたNTT Comとの新規ビジネス共創 午後イチのセッションは、NTTコミュニケーションズ株式会社 ビジネスソリューション本部 浅川様と山下様、ニフティ N1! スクラムエバンジェリストと基幹システム バックエンドエンジニアの4名による、共創をテーマにした「職種と企業を飛び越えたNTT Comとの新規ビジネス共創」です! 昨年から新たに取り組んでいる共創プロジェクトの取り組みや、エンジニアとビジネス視点についてのLTを行いました! ベンダーとしてではなく、1つのチームとしてプロジェクトに取り組む4名が振り返りや苦労話を特別に公開しました。こちらのセッションはエンジニアだけでなく、ビジネスサイドの方でもわかりやすいと思われる内容でした 登壇中も楽しそうな雰囲気でした! Expert Tech Talk!〜ニフティスペシャリスト対談〜 ニフティには N1!というスペシャリスト制度 があります。 データサイエンス、スクラム、オートメーション、ID基盤のスペシャリストが一堂に会して、どんな制度なのか?どんな活動をしているのか?といった、普段あまり社外に出ない内容についてお届けしました! 今後のビジョンについては私も聞いていてワクワクする内容でした! 司会もN1!という豪華セッションでした! 皆さん良い笑顔ですね 2レーン開催セッション ここからは会場を2つに分けての開催になります。 開催されたセッションの中からアンケートで人気だった3セッションをご紹介します ポイントサービス設計の異常な挑戦 または我々は如何にして心配するのを止めてドメイン駆動設計を愛するようになったか ドメイン駆動設計 x 実際の事例 といった、実用性がある内容のセッションでした! 理想と現実のお話など、ドメイン駆動設計に挑戦したことがある方ならつい共感してしまうような内容がたくさんありました ニフティポイントクラブの開発・運用を担当しているエンジニアによる裏話です ニフティ社内ISUCON開催への道のり 2023年8月に社内で行われた ニフティ社内ISUCON の運営メンバーによる、200台もの大量のEC2インスタンスを立ち上げるために工夫したこと、悩んだことと、その解決策についての発表を行いました! ※「ISUCON」は、LINEヤフー株式会社の商標または登録商標です。 https://isucon.net 社内ブカツであるニフティISUCON部にも所属しているエンジニアが登壇しました ニフティLT大会大公開スペシャル まず始めは「 VRの世界でLTしていく 」です。 社内のLT大会でもVRで登壇していましたが、ついに目の前でVRゴーグル姿を見ることができました VRゴーグルがあると人の視線が気にならなくて気が楽だったそうです!配信で見ていた方は素顔が気になっていたかもしれませんね 2番手はニフティライフスタイル株式会社のバックエンドエンジニアによる「 コードを読みやすくしよう!〜秒で身に付くよい命名〜 」です! こちらはすぐに実用できそうな良い命名を身に着ける方法がぎゅっと詰まったLTでした コードを書く時間より、読んでいる時間の方が遥かに多い、沁みる言葉です… お次は新入社員による「 朝起こしてくれるメイドさんがほしい 」です! 朝起こしてくれるメイドさん、皆さんも欲しいですよね?欲しいなら作ればよいのです… メイドさんへのこだわりを話しているみたいですね さらに「 ニフティ開発インターンで使うAWS環境をできるだけ楽に構築した話 」です! こちらは開発インターンでのAWS環境の構築についてです!手作業でやりたくない様々な面倒なことを解決したお話でした 7分で資料を作成してしまった…と冒頭でお話ししていましたが、1つのセッションとして成立しそうなほどモリモリな内容でした LT大会のトリを飾るのはニフティライフスタイル株式会社のモバイルアプリエンジニア!タイトルは「 文系出身・開発未経験エンジニアが入社から5年間で実践した学習法〜エンジニアの世界で圧倒的に成長するために〜 」です! 開発経験がほぼない文系学生からエンジニアとして自信を持てるようになるまでにやったことが語られており、新人エンジニア必見の内容でした 輝けるもの、見つけていきたいですね クロージング 全てのセッションが終わり、システム統括部 統括部長である最上によるクロージング映像でNIFTY Tech Day 2023 は幕を閉じました! かなりの長丁場でしたが、朝からずっといてくださった来場者の方もいらっしゃいました…!本当にありがとうございました セッション終了後 抽選会 セッションの会場は懇親会会場を兼ねていたので、一度受付へ移動していただき、抽選会を行いました! 当社社員おすすめの技術書が当たるということで、以下の5冊をプレゼントしました! 良いコード/悪いコードで学ぶ設計入門 ―保守しやすい 成長し続けるコードの書き方 プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則 プロダクトマネージャーのしごと ―1日目から使える実践ガイド プログラマー脳 ~優れたプログラマーになるための認知科学に基づくアプローチ ノンデザイナーズ・デザインブック 抽選会にもたくさんの人が参加してくださいました!この間、運営は懇親会の準備に勤しんでいました 懇親会 お寿司やケータリング、お酒もあり、活気のある懇親会となりました スタッフもおいしいご飯ににこにこです まとめ ニフティとしては初めてのハイブリッド開催でのイベントで、対面形式のイベントを開催すること自体が久しぶりでしたが、無事終えることができました! 個人的な意見ですが、来年はもっとパワーアップさせて開催できたらいいな~と思っています また、今後も日頃の業務や取り組みについて発信していきますので、ぜひNIFTY Tech Talkなどにもご参加いただけると幸いです! ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
この記事は、 ニフティグループ Advent Calendar 2023 25日目の記事です。 メリークリスマス!!! こんにちは!メリークリスマス! ニフティグループアドベントカレンダー2023 も無事完走いたしました!! 読んでくださった皆様、書いてくださったニフティ社員の皆様のおかげです。 今年は去年よりも多くの記事を書いてもらいました! 良かったこと 記事公開通知や週次ブログランキングをSlackにポスト 記事を公開するだけでなく、それをSlackにポストすることで社員同士の交流が一層深まりました。 リアクションやコメントを通じて直接のフィードバックを得られ、記事に対する興味や感想が分かち合えたことは大きな収穫でした。 社内LT大会に登壇 アドベントカレンダー開始前に社内LT大会に登壇することで、参加の促進に繋げることができました。 LT大会に積極的に参加している社員はアウトプットすることにとても積極的だと思うので、 参加してくれたと思っています! ↓LT大会で使用した資料の一部 分報チャンネルで投稿したことを共有している人がいた ニフティでは、分報文化があります。個人の分報チャンネルにブログ書いた〜と共有している社員が割と多くいました! 社内で盛り上がってる感が出てていいなぁと思いました! 大変だったこと カレンダーに埋めてもらうこと カレンダーを社員の方々に埋めてもらうことが予想以上に大変でした。 作ってそのまま放置しても自然に埋まっていくわけではありませんでした。 枠自体は少しずつ埋まってきたのですが、少し足りないなぁと思っていました。 そこで、上長経由でこの記事を書いてほしいと依頼したり、先述のLT大会に登壇(これが意外と反響をもらえた)しアドベントカレンダーへの参加を促したりしました。 記事を書くこと 無事に開催されたアドベントカレンダーですが、 ブログ運用チームが積極的に書かないと、社員の皆さんは書いてくれないと考えていました。 なので、ブログ運用チームは積極的にアドベントカレンダーへ参加していました。 私自身も3つ登録していたのでなかなか大変でした。。。 根気でブログを3本とも書き切って、なんとか締め切りまで間に合わせることができました。 また、社員からも「そろそろ書かないと…」と悲痛の声がありました。。。 ですが、ブログ運用チームから、カレンダー当日には遅れても良いことを事前に知らせていました。 なので自分のペースで書いていただけたのではないかなと思います! おわりに 今年のアドベントカレンダーも盛り上がっててよかったと思います! ブログ運用チームではこれからもアドベントカレンダーのようなイベントを開催し、NIFTY engineeringを盛り上げていけたらと思います! ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
この記事は、 ニフティグループ Advent Calendar 2023 24日目の記事です。 はじめに こんにちは。会員システムグループの上原です。 みなさん、コーディングは好きでしょうか?私は業務ではGo, Python, TypeScript, プライベートでゴリゴリRustを書いていて毎日楽しいです。 さて、業務でコーディングしていると付きまとうのがコードレビューです。コードのどこを変えたのかGitHubが頑張って出してくれますが、見た目であったり動作はどう変わったのか?は頑張って自分で追ってやる必要があります。 テストコードを見れば仕様の変化はわかるようになっているのでは?というのはあるんですが、やっぱり自分で試しにAPIを叩いたりブラウザを動かしてみないと安心できません。 ただ、手動で動かして確かに意図した通りに動作が変わっているのか?を追いかけるのは面倒です。特にAPIが返すjsonを比較するのは大変です。 例としてSpotifyのアルバム情報を取得するAPIのレスポンス例と、その例を一部改変したレスポンスを載せています。ぱっと見何が変わったかわかりますか?一瞬でわかったあなたはすごいです。 {"album_type":"compilation","total_tracks":9,"available_markets":["CA","BR","IT"],"external_urls":{"spotify":"string"},"href":"string","id":"2up3OPMp9Tb4dAKM2erWXQ","images":[{"url":"https://i.scdn.co/image/ab67616d00001e02ff9ca10b55ce82ae553c8228","height":300,"width":300}],"name":"string","release_date":"1981-12","release_date_precision":"year","restrictions":{"reason":"market"},"type":"album","uri":"spotify:album:2up3OPMp9Tb4dAKM2erWXQ","artists":[{"external_urls":{"spotify":"string"},"href":"string","id":"string","name":"string","type":"artist","uri":"string"}],"tracks":{"href":"https://api.spotify.com/v1/me/shows?offset=0&limit=20","limit":20,"next":"https://api.spotify.com/v1/me/shows?offset=1&limit=1","offset":0,"previous":"https://api.spotify.com/v1/me/shows?offset=1&limit=1","total":4,"items":[{"artists":[{"external_urls":{"spotify":"string"},"href":"string","id":"string","name":"string","type":"artist","uri":"string"}],"available_markets":["string"],"disc_number":0,"duration_ms":0,"explicit":false,"external_urls":{"spotify":"string"},"href":"string","id":"string","is_playable":false,"linked_from":{"external_urls":{"spotify":"string"},"href":"string","id":"string","type":"string","uri":"string"},"restrictions":{"reason":"string"},"name":"string","preview_url":"string","track_number":0,"type":"string","uri":"string","is_local":false}]},"copyrights":[{"text":"string","type":"string"}],"external_ids":{"isrc":"string","ean":"string","upc":"string"},"genres":["Egg punk","Noise rock"],"label":"string","popularity":0} {"name":"string","popularity":0,"release_date":"1981-12","images":[{"url":"https://i.scdn.co/image/ab67616d00001e02ff9ca10b55ce82ae553c8228","width":300,"height":300}],"tracks":{"items":[{"is_playable":false,"duration_ms":0,"explicit":false,"is_local":false,"id":"string","external_urls":{"spotify":"string"},"track_number":0,"disc_number":0,"available_markets":["string"],"artists":[{"uri":"string","name":"string","href":"string","type":"artist","id":"string","external_urls":{"spotify":"string"}}],"preview_url":"string","restrictions":{"reason":"string"},"href":"string","linked_from":{"uri":"string","type":"string","id":"string","href":"string","external_urls":{"spotify":"string"}},"type":"string","name":"string","uri":"string"}],"limit":20,"next":"https://api.spotify.com/v1/me/shows?offset=1&limit=1","offset":0,"href":"https://api.spotify.com/v1/me/shows?offset=0&limit=20","previous":"https://api.spotify.com/v1/me/shows?offset=1&limit=1","total":4},"type":"album","uri":"spotify:album:2up3OPMp9Tb4dAKM2erWXQ","restrictions":{"reason":"market"},"id":"2up3OPMp9Tb4dAKM2erWXQ","album_type":"compilation","artists":[{"uri":"string","external_urls":{"spotify":"string"},"id":"string","href":"string","name":"string","type":"artist"}],"genres":["Egg punk","Noise rock","House Music"],"release_date_precision":"year","total_tracks":9,"label":"string","available_markets":["CA","BR","IT"],"external_ids":{"upc":"string","ean":"string","isrc":"string"},"copyrights":[{"type":"string","text":"string"}],"external_urls":{"spotify":"string"},"href":"string"} どうでしょうか?自分もいきなり出されたら自信がありません。 すぐにはわからない方が自分を含め大半だと思いますが、この記事を読むとすぐに違いがわかるようになります。 手始めにファイルを比べてみよう 今回はシェルを用いて違いを見つけてみます。 diffコマンドを用いて、まずはファイルの差分を見てみましょう。 AというファイルとBというファイルを比較するには以下のようにコマンドを実行すれば良いです。uオプションをつけておくとGitの差分ぽく表示されるのでさらにわかりやすくなります。 diff -u A B 実行してみると以下のように2ファイルの差分がわかりやすく表示されます。 diff -u a.txt b.txt --- a.txt 2023-12-22 10:43:55 +++ b.txt 2023-12-22 10:44:01 @@ -1 +1 @@ -hello world +hello rust コマンドの実行結果を比べてみる 今度はファイルではなくコマンドの実行結果を比較する場合を考えてみましょう。 実行結果をファイルに書き出す機能であるリダイレクトをご存知であれば、以下のようなコマンドを実行すれば良いかなという想像がつくと思います。 コマンド1 > result_a.txt コマンド2 > result_b.txt diff -u result_a.txt result_b.txt まずはリダイレクトでファイルに実行結果を書き出してやり、生成したファイルをdiffコマンドで比較するという感じです。試しに使うとこんな感じです。 $ date > a.txt $ date > b.txt $ ls a.txt b.txt $ diff -u a.txt b.txt --- a.txt 2023-12-22 10:49:34 +++ b.txt 2023-12-22 10:49:39 @@ -1 +1 @@ -金 12 22 10:49:34 JST 2023 +金 12 22 10:49:39 JST 2023 はい。無事日時の差分が出てきました。dateは現在日時を出力するだけのコマンドです。 とまぁやってみましたが、コマンドの実行結果を比較するためにわざわざファイルに書き出すのは面倒ですし、なにしろ謎のファイルが増えていきますよね。 ここで使えるのがプロセス置換という方法です。 プロセス置換は、bashでコマンドの出力を一時ファイルとして扱うための機能です。これにより、複数のコマンドの結果を比較したり、変数に代入したりすることが容易になります。 プロセス置換を使用すると上のコマンドが以下のようにワンライナーに書き直せます。 diff -u <(date) <(date) では実行してみましょう。 $ diff -u <(date) <(date) (何も表示されない) あれ?何も表示されないですね。あ、dateは現在日時を出すので、同時に実行すると差分が何も出なくなってしまうのでした。わざと1秒ずらして実行タイミングをずらしてみましょうか。 diff -u <(date) <(sleep 1 && date) --- /dev/fd/11 2023-12-22 10:58:05 +++ /dev/fd/13 2023-12-22 10:58:06 @@ -1 +1 @@ -金 12 22 10:58:05 JST 2023 +金 12 22 10:58:06 JST 2023 デモンストレーションのためsleepコマンドを挟む必要がありましたが、無事1回で実行結果の差分を表示させることができました。 このように本来は引数としてファイル名しか受け付けないコマンドであってもプロセス置換を用いることで、コマンドの実行結果を引数として渡すことが可能になります。 diff以外でもプロセス置換は使えるのですが、コマンドの実行結果を比較したい場合は以下のようなコマンドをイディオムとして覚えておきましょう。 diff -u <(コマンド1) <(コマンド2) <と(の間にスペースを入れると動かなくなるので注意です。 レビューでの使用例 APIのレスポンスがどう変わったかわかりやすくする 記事冒頭で話したAPIのjsonの比較方法について考えてみます。 まずはAPIを叩くにはcurlコマンドを使用すれば良いです。 curl example.com そのままだと進捗状況が画面に出てくるので-Sを入れて表示されないようにします。 curl -S example.com APIからはjsonが一行にまとめられて返却されることが多いため、jqコマンドに通して整形しましょう。ついでにSオプションでオブジェクトのキーでソートしておくと、捗ります。 curl -S example.com | jq -S "." 仕様変更によってリリースしたいAPI(ここでは仮にステージング環境としておく)のレスポンスをとるコマンドも作っておきましょう。 curl -S staging.example.com | jq -S "." さて、この二つのAPIを比較したい場合は、diffとプロセス置換を組み合わせると簡単に差分を取れます。 diff <(curl -S example.com | jq -S ".") <(curl -S staging.example.com | jq -S ".") 引数の順番はどちらでも良いのですが、1番目に変更前、2番目に変更後の内容を入れるようにすると差分がわかりやすくなります。 先ほど出てきたjsonが返ってくるサーバーを立てて、curlしてみると以下のような結果になります。 diff -u <(curl -S example.com | jq -S ".") <(curl -S staging.example.com | jq -S ".") --- /dev/fd/11 2023-12-22 13:33:26 +++ /dev/fd/13 2023-12-22 13:33:26 @@ -33,7 +33,8 @@ }, "genres": [ "Egg punk", - "Noise rock" + "Noise rock", + "House Music" ], "href": "string", "id": "2up3OPMp9Tb4dAKM2erWXQ", 誰が見てもHouse Musicがgenresの中に追加されているとわかるので、いい感じですね! ついでにこのコマンドをPRやissueのコメントに貼っておくと、レビュアーも自分も幸せになれると思います。 Amazon RDSのインスタンスの設定を比較する インスタンスを複製する際にちゃんと同じ設定になっているかなど気になったことはないでしょうか?そんな時は、インスタンス同士の設定を比較して、想定した通りの設定になっているか確認してみましょう。 AWSのコンソールを横に並べて、左右見て設定が同じかどうか確認すれば良さそうですが、項目数が多く確認漏れがありそうです。 そこで今回もdiffコマンド使って比較してみます。インスタンスの設定は以下のようにAWS CLIを使えば取得することができます。 aws rds describe-db-instances --db-instance-identifier database-1 --query 'DBInstances[0]' --output json --region ap-northeast-1 db-instance-identifierオプションにインスタンスの識別子を指定します。outputオプションにjsonを指定するとjsonで結果が返却されます。 返ってきたjsonを比較しやすくなるように、jqコマンドで整形してやります。jqでjsonのキーをソートしないと順番がバラバラで見にくくなるので気をつけてください。以下のような感じです。 aws rds describe-db-instances --db-instance-identifier database-1 --query 'DBInstances[0]' --output json --region ap-northeast-1 | jq -S "." データベースの情報をとるコマンドは組み立てられたので、あとはいつも通りdiffコマンドとプロセス置換に突っ込んでやりましょう。 diff -u <(aws rds describe-db-instances --db-instance-identifier database-1 --query 'DBInstances[0]' --output json --region ap-northeast-1 | jq -S '.') <(aws rds describe-db-instances --db-instance-identifier database-2 --query 'DBInstances[0]' --output json --region ap-northeast-1 | jq -S '.') 実行してみると以下のようになります。 --- /dev/fd/63 2023-12-22 04:20:42.250700418 +0000 +++ /dev/fd/62 2023-12-22 04:20:42.250700418 +0000 @@ -4,7 +4,7 @@ "AssociatedRoles": [], "AutoMinorVersionUpgrade": true, "AvailabilityZone": "ap-northeast-1d", - "BackupRetentionPeriod": 7, + "BackupRetentionPeriod": 1, "BackupTarget": "region", "CACertificateIdentifier": "***********", "CertificateDetails": { @@ -13,9 +13,9 @@ }, "CopyTagsToSnapshot": true, "CustomerOwnedIpEnabled": false, - "DBInstanceArn": "arn:aws:rds:ap-northeast-1:************:db:database-1", + "DBInstanceArn": "arn:aws:rds:ap-northeast-1:************:db:database-2", "DBInstanceClass": "db.t3.micro", - "DBInstanceIdentifier": "database-1", + "DBInstanceIdentifier": "database-2", "DBInstanceStatus": "available", "DBParameterGroups": [ { @@ -57,28 +57,26 @@ "VpcId": "vpc-*****************" }, "DbInstancePort": 0, - "DbiResourceId": "db-**************************", + "DbiResourceId": "db-**************************", "DedicatedLogVolume": false, "DeletionProtection": false, "DomainMemberships": [], "Endpoint": { - "Address": "database-1.************.ap-northeast-1.rds.amazonaws.com", + "Address": "database-2.************.ap-northeast-1.rds.amazonaws.com", "HostedZoneId": "Z24O6O9L7SGTNB", "Port": 5432 }, "Engine": "postgres", "EngineVersion": "15.4", - "EnhancedMonitoringResourceArn": "arn:aws:logs:ap-northeast-1:************:log-group:RDSOSMetrics:log-stream:*****************************", "IAMDatabaseAuthenticationEnabled": false, - "InstanceCreateTime": "2023-12-22T02:57:01.355000+00:00", - "Iops": 3000, + "InstanceCreateTime": "2023-12-22T02:59:15.979000+00:00", "IsStorageConfigUpgradeAvailable": false, "KmsKeyId": "arn:aws:kms:ap-northeast-1:************:key/************************************", - "LatestRestorableTime": "2023-12-22T04:14:32+00:00", + "LatestRestorableTime": "2023-12-22T04:14:34+00:00", "LicenseModel": "postgresql-license", "MasterUsername": "postgres", - "MonitoringInterval": 60, - "MonitoringRoleArn": "arn:aws:iam::************:role/rds-monitoring-role", + "MaxAllocatedStorage": 1000, + "MonitoringInterval": 0, "MultiAZ": false, "NetworkType": "IPV4", "OptionGroupMemberships": [ @@ -88,14 +86,16 @@ } ], "PendingModifiedValues": {}, - "PerformanceInsightsEnabled": false, - "PreferredBackupWindow": "18:51-19:21", - "PreferredMaintenanceWindow": "thu:14:38-thu:15:08", + "PerformanceInsightsEnabled": true, + "PerformanceInsightsKMSKeyId": "arn:aws:kms:ap-northeast-1:************:key/************************************", + "PerformanceInsightsRetentionPeriod": 7, + "PreferredBackupWindow": "18:47-19:17", + "PreferredMaintenanceWindow": "sat:15:00-sat:15:30", "PubliclyAccessible": false, "ReadReplicaDBInstanceIdentifiers": [], "StorageEncrypted": true, - "StorageThroughput": 125, - "StorageType": "gp3", + "StorageThroughput": 0, + "StorageType": "gp2", "TagList": [], "VpcSecurityGroups": [ { コンソールを頑張って確認しなくてもコマンドの実行結果を見て差分を見ることができるようになりました! ついでにこのコマンドをPRやissueのコメントに貼っておくと、レビュアーも自分も幸せになれると思います。(2回目) まとめ レビュー時、想定通りの動作になっているか細かい部分を血眼になって確認するのは大変です。 目で見て一つ一つ比較するしかないこともあるかもしれませんが、エンジニアなので可能な限り楽をできないか考えてみるのも時には大事です。 自分のためにも、またレビュアーのためにも短い時間で正しいことが確認できるような動作確認方法が何かを考えていきましょう。その際にこの記事が参考になれば幸いです。 明日は、@ike-chanさんの「AdventCalendarお疲れ様でした!ブログ」です。 お楽しみに! ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
この記事は、 ニフティグループ Advent Calendar 2023 23日目の記事です。 はじめに こんにちは。新卒1年目の終わりが近づいてきていることに怯えている西根です。 ニフティでは複数のチームでスクラム開発を採用しています! ジョブローテーションで配属されていたチームでもスクラム開発(厳密にいうとなんちゃってスクラム開発)を採用していました! 今回は、あるスプリントのレトロスペクティブでTRYとして挙がったデイリースクラムの改善に取り組んだ方法について紹介します。 この記事の対象読者 スクラムイベントの改善方法がわからない人 デイリースクラムを改善したい人 チケットの管理が難しいと感じている人 背景 チーム編成とプロダクト 私が所属していたチームは5人の先輩と、私を含めて2人のジョブローテーションの新人という編成でした。 そのチームが抱えているプロダクトは4つあり、そのうち1つのメインプロダクトについてスクラムで開発を行っているという状況でした。 メインプロダクトのみをスクラムで行っているとはいえ開発メンバーは同じなので、すべてのプロダクトをプランニング時に考慮し、デイリーでの進捗確認も行っていました。 当時のデイリースクラム TRYに改善が挙がった当時は9:45-10:00の15分間で以下の流れでデイリースクラムを行っていました。 チームメンバーがそれぞれ以下を報告する。その間画面共有をしてるファシリの人が、なんとなくGitHubのProjects(開発側のチケット)やNotionのチケット(事業側のチケット)を確認する。 前営業日に行ったタスク、参加したミーティング その日行うタスク、参加するミーティング ファシリがNotionチケット(事業側のチケット)の更新内容を確認する。 今日のアラート確認、運用作業の担当者を確認する。 共有事項や困っていることの相談を行う。 ですが、 個人の作業報告で時間を取られてしまい、肝心の相談や共有にあまり時間を割けていません でした。 また、15分を超えてしまうこともあり、デイリーの直後のミーティングに十分な時間が割けなくなってしまうこともありました。 課題 私は時間がかかりすぎてしまうのは以下が原因だと考えました。 誰が担当のタスクかを把握できていないのでファシリは誰に話を振れば良いかわからない(特にスプリントの前半) Projectsの今スプリントの中に半期継続の作業(改善タスクやモブプログラミング)や進展がなくなったタスクも含まれており、今スプリントのPBIがわかりづらい また、開発の進捗に影響がある課題だと感じていた以下についてもデイリーで解決できないかと考えていました。 slackで行っているレビュー依頼が流れてしまい、2日以上放置になってしまっていることがある 具体的な改善に向けて TRYに挙がったレトロスペクティブでは、 今スプリントの対応内容のストーリーごとに作業を報告する それ以外の作業があれば別途共有する ということになりましたが、実際にやってみると思うように進めることができませんでした。 slackの自分のtime(分報)チャンネルで悩んでいると、別のチームの先輩から見学しにくる?とお声がけをいただきました!(timeはこれがあるから最高ですよね) 改善までの道のり 自分が実際にデイリースクラムの改善までに踏んだ手順は以下の通りです。 見学先のチームへのアポ & 自分のチームへの説明 実際に見学 そもそもデイリースクラムとは何かを勉強 チームへの共有資料作成 チームへ共有し、実際にどう改善するか相談 1つ1つ細かく取り上げていきたいと思います。 1. 見学先のチームへのアポ & 自分のチームへの説明 timeでお声がけしていただいた先輩に行きたい旨を伝えたら、見学先のチームへの共有までしてくださっていました(本当にありがとうございます) 自分のチームとデイリーの時間帯がかぶっていたので、自分のチームには事前にデイリーで「他のチームの見学に行くのでデイリー欠席します」と伝えておきました! 2. 実際に見学 宣言通り見学に行きます。 最初に挨拶をした以外は基本的にそのチームのデイリーを見てメモして…という形で見学していました。 わからないことが出てきたらslackで聞く形を取らせていただきました!手厚いサポートがありがたいですね。 3. そもそもデイリースクラムとは何かを勉強 改善を行うにあたり、まずはデイリースクラムってそもそも何なの?という部分をスクラムガイドと、社内で行われていたスクラムガイド輪読会の資料から考えていきます。(関係ないですが、輪読会や勉強会の資料が自由に見れるとこういうときに助かったりしますよね) デイリースクラムの⽬的は、計画された今後の作業を調整しながら、スプリントゴールに対する進捗を検査し、必要に応じてスプリントバックログを適応させることである。 スクラムガイド 2020年11月 進捗共有の意味合いはありそうな気がしますね。 開発者は、デイリースクラムがスプリントゴールの進捗に焦点をあて、これからの1⽇の作業の実⾏可能な計画を作成する限り、必要な構造とやり⽅を選択できる。これは集中を⽣み出し、⾃⼰管理を促進する。 スクラムガイド 2020年11月 「実行可能な計画を作成する」ということは、どこまでやる!と決めるということですが、このチームではステークホルダーが多く、割り込み作業が少なくなかったため、ここを完璧に実行する必要はないと判断しました。 (開発者という集団として)「自己管理を促進する」ということは、極論開発者たちが自走していけるならば、デイリーのやり方自体に正解はないということだと解釈しました。 そうなってくると、自分のチームに合ったやり方を模索する必要が出てくることがよくわかりますね! 4. チームへの共有資料作成 見学時のメモは自分の思ったことと事実がごちゃごちゃになってしまっていたので、後から共有用にまとめなおしました。 共有用資料は以下のような構成にしました。 デイリースクラムが目指すべき姿について これは先ほど学んだ内容をそのまま共有しました。 デイリーがどういう役割でどうあるべきなのか、という部分について考えながら改善アクションを決定したいと考え、共有資料に含めました。 他のチームとの比較(違う / 同じ) 今回見学にいったチームは、扱うプロダクトが自分のチームと近いチームだったので、似ている部分もありました。 反対に全く違う部分もあったため、比較して共有しました。 自分が良いなと思った点 自分のチームで実現できるかや、課題を解決できるかに関わらず純粋に良いと感じたものを以下のようにまとめました! GitHub Projectsが整備されていて使いやすそう reviewやwaitingステータスがあるため、状況がわかりやすい Assigneesが登録されていることで担当者が一目でわかる 協力会社のタスクについても状況確認を行っている 私のチームでも協力会社にお願いしているタスクが存在するプロダクトがあり、そのプロダクトが属人化しがちで不透明であるということが数スプリント前にProblemとして挙がっていた スプリントのゴールがデイリーの進め方をまとめているslackチャンネルのcanvasに書かれている あまり今まで意識していなかったが、デイリーはスプリントゴールに対する進捗の確認なので、確認しやすいことは大切 レビュー依頼はslackのワークフローで行い、終わるまではチャンネルにピン止めしている デイリーですぐ確認できるのでレビュー依頼が流れてしまうことがない マネできそうな部分 良いと思った点から実行できそうなものと具体的なアクションを以下のようにまとめました。 全プロダクトがまとまったProjectsを作成する 既に上期計画の時に上がっていたが断念していた 今スプリント全体で一気に見れた方が時短&わかりやすい issueの管理方法 Assigneesを必ず登録する reviewやwaitingステータスを作成する PBIステータスを作成し、そのステータスにはPBIのissueのみ設定する レビュー依頼の管理方法 PRで管理するのが理想だが、GitHub移行できているのは一部のプロダクトのみなので、暫定対応でピン止めで対応する すでにピン止めが使われているし微妙かもしれない… 5.チームへ共有し、実際にどう改善するか相談 4でまとめた資料をチーム全員に共有しました。 その中でデイリーの進め方を決めたり、Projectsの運用を改めたりなどのアクションまで行いました。 共有したときに取り組んだこと まずはGitHub Projects自体の改善から行いました。 デイリーの時間でこれを見れば進め方が自ずとわかるものを目指し、以下の4点を変更しました。 Reviewステータスを追加 不要なビューの削除 今のスプリントの開発対象のissueが一目でわかるボードビューの作成 ワークフローを設定 プロダクトのリポジトリにissueがopenされたらProjectにissueを追加する issueがProjectに追加されたらstatusをTodoにする issueが再度openされたらstatusをIn Progressにする issueがcloseされたらstatusをDoneにする また、このProjectが活用できるように運用ルールを2つ新たに定めました。 スプリントプランニングで担当者が決まったらissueにAssigneesを登録する Assigneesが自分でステータスを動かす こうすることで、Projectを見るだけで進捗を確認し、各々が最大限スプリントゴールに向かって自律的に行動することができるようになりました。 デイリーの進め方 各プロダクトのProjectsを見ながらファシリが担当者に確認 想定より進んでいる、オンスケ、遅れているなどの進捗 必要なフォローなどがあれば調整 今日何をやるかもその時に共有する Reviewステータスのものについて漏れがないか確認する Notionチケットの確認 アラート確認、運用作業の担当者確認 共有事項、確認事項 まとめ 実際に他のチームのデイリーに参加するのはとっても勉強になりました! GitHubのProjectsはどんどん使いやすくなっている最中なので、リリースをチェックして便利に使っていきたいです。 ワークフローが非常に便利で複製することもできるので、複数Projectを1つのProjectにまとめることも簡単にできそうです! 今回は近しいチームのデイリーでしたが、全然違うプロダクトを扱っているチームのデイリーと比較しても面白い収穫がありそうだな~と思いました。 実際にデイリーもやりやすくなった(と思う)ので、見学に行って良かったです! timeでいろいろ言ってるとこういうチャンスをつかめるのでとても良いですね…すべての作業や疑問をtimeに吐き出していくことを推奨しています。 明日は、上原さんです。クリスマスイブの記事もお楽しみに ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
この記事は、 ニフティグループ Advent Calendar 2023 22日目の記事です。 はじめに こんにちは。最近はGitHub Copilot無しでコーディングしたくない ShibataRyusei です。 業務ではiOS/Androidアプリ「マイ ニフティ」の開発を行っており、iOS, Android, バックエンドなどほとんどの開発に携わっています。 (ちなみに弊チームではエンジニアを 募集中 です!) 個人では日々Flutterを使った開発を楽しんでいます。 かなり昔の話ですが今年の2月ごろにFlutterにコントリビュートしたのでメモとして残します。 今年のことは今年のうちにアウトプット… コントリビュートとは? 「コントリビュート」とは、日本語で「貢献する」という意味で、OSSに貢献することを指します。 コントリビュートするメリットとして、下の記事では「コントリビュートすることはやりがいがあり、…学習し、教え、経験を積むことができます」と述べています。 https://opensource.guide/ja/how-to-contribute/ コントリビュートというと、コードを書いてPull requestを出すイメージがありますが、コードの作成だけでなく、ドキュメントの作成やイシューの整理、カンファレンスの企画なども含まれるようです。 Flutterとは? 今回コントリビュートするFlutterを簡単に紹介します。 FlutterはGoogleが中心に開発しているOSSです。 Dartという言語のフレームワークであり、Dartのコード1つでマルチプラットフォーム(iOS, Android, Web, Windows, macOS, Linux)のネイティブアプリケーションを作ることができます。 実はFlutterはコントリビューターの多いOSSランキングでnext.jsを抑えて3位に入るような活発なOSSです。 https://octoverse.github.com/2022/state-of-open-source Flutterへのコントリビュートのしかた 今回はコードを書いてPull Request(PR)を出す方法をまとめます。 1. Flutterのルールを学ぶ まずはFlutterのコントリビュートに関するルールを学びます。 ここら辺は見ておくと良いと思います。 CONTRIBUTING.md CODE_OF_CONDUCT.md FlutterのWiki コントリビュート関連のページ(values, Issue-hygieneなど) 2. 環境構築をする ドキュメントに従って、Flutterのengineとframeworkの開発環境を構築します。 frameworkであればこれです。 https://github.com/flutter/flutter/wiki/Setting-up-the-Framework-development-environment 3. Issueを探す コントリビュートするためのIssueを見つけましょう。 Flutterには多くのIssueがあるため、自力で探すのは大変です。そのためラベルから絞り込んで探すのがおすすめです。 おすすめのIssueラベルは”good first issue”、”a:first hour”です。 昔は”easy fix”もあったけどいつの間にかなくなってる… 4. 実装をする Issueを決めたらコードを実装します。 GitHubにあるFlutterのレポジトリからforkして自分のレポジトリで作業をします。 5. Pull Requestを出す forkしたレポジトリからFlutterのレポジトリに対してPull Requestを出します。 Pull Requestを出す際、PRテンプレートのチェックボックスを確認しましょう。 6. Mergeされたら完了! Pull Requestがマージされたら、コントリビュートは完了です! 実際にやってみた まず、Issueを選択します。今回は、”a:first hour”のラベルがついている(2月には”easy fix”も付いてた)このIssueに取り組みました。 https://github.com/flutter/flutter/issues/115357 このIssueは、flutter createで使用するテンプレートのLintテストを追加する内容です。 実装を完了し、Pull Requestを提出しました。 https://github.com/flutter/flutter/pull/120526 FlutterではCIが整備されており、約30分間テストなどが実行されていました。 数日後レビューがきて何回か修正したらLGTMをもらいマージされました。 3.10.0のリリースノートにも載りました! Add lints test for all templates by @ShibataRyusei in 120526 @ShibataRyusei made their first contribution in 120526 https://docs.flutter.dev/release/release-notes/release-notes-3.10.0 終わりに コントリビュートは難しいイメージがありましたが、全然自分でもできるものが結構ありました。 そして実際にコントリビュートすることでFlutterコミュニティの活発さを感じました。Pull Requestのレビューも早いですし、放置されているIssueもあまりなかったです。 Issueを探しているとFlutter EngineのIssueはまだまだ難しいと感じます。既存コードのコードリーディングがまだまだ足りなかったり、C++, Skia, Metalなどの深い知識が必要だと感じました。 皆さんもぜひOSSに貢献していきましょう!! 明日の ニフティグループ Advent Calendar 2023 は@nishine829です。お楽しみに!! Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC. ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
この記事は、 ニフティグループ Advent Calendar 2023 4日目の記事です。 ニフティ株式会社の仲上です。 私は以前Notionの作図機能についてまとめたことがあります。 私的Notion作図ベストプラクティス【2023年5月版】 – Qiita こちらの記事はあくまで個人利用を前提として書かれているため、会社で利用している状況とは若干異なります。また、時間が立ってNotion側の機能にもいくつか更新が入ったので、2023年12月版【会社利用編】ということでNotionの作図機能について紹介しようと思います。 5月からの変化 最初に2023年5月から現在(2023年12月)までの変更点についてまとめていきます。 Notionの更新内容は こちらのリリースノート にまとめられています。 この中で、作図機能に関係しそうなものをいくつかピックアップして紹介します。 コードブロックにコード整形機能が追加 September 22, 2023 – Notion 2.33: Automate workflows コードの整形をNotionの標準機能で行えるようになった mermaidのコードを整形できる figmaのデータをNotionDBに追加できるようになった Link previews & synced databases – Notion Help Center Figmaはブラウザベースで動くインターフェースデザインツール NotionDBに直接リンクできるようになったので、「画面のデザインを考える」といったチケットを作ったときの管理がしやすくなった インテグレーションギャラリーの追加 August 8, 2023 – Notion 2.32: new features for project management, AI, and more インテグレーションとは、Notionに他のサービスのアカウントを連携し、データの編集や作成などをシームレスに行える機能のこと miroやCanvas、Adobe XDなどのインテグレーションが追加さた miroについては、前回の記事で紹介 ( 私的Notion作図ベストプラクティス【2023年5月版】 – Qiita ) このページの最後で少しだけ紹介 Notion Q&A(ベータ)の追加 November 14, 2023 – Notion 2.35: Introducing Q&A by Notion AI (now in beta) 現状作図機能とはあまり関係ありませんが、Notion Q&A(ベータ)が追加されました。 生成系AIを応用して作らたツール チャット形式で情報を検索できる ワークスペースの情報を学習して解答を生成してくれること が最大の特徴 ベストプラクティス(会社版) ベストプラクティス 用途 ツール シーケンス図、ER図、フローチャート https://qiita.com/nahiro_tus/items/131514c49187c3eb08cd#mermaid グラフ https://www.google.com/intl/ja_jp/sheets/about/ その他の図 https://app.diagrams.net/ 前提条件 GWSを契約している 当社のルールで、データは原則Google Driveやローカル環境、準備されたサーバー以外にはアップロードしない メリットとデメリット メリット 追加料金が発生しない GWSのサービスをフルに活用できる データのグラフ化はGoogle Sheets 作図データの保存先はGoogle Drive デメリット 作図機能に不足を感じる時がある 各ツールの使い方 mermaid 前回の記事 参照 Google Sheets グラフの描画にはGoogle Sheetsを利用しています。 NotioinにはGoogle Sheetsにデータを同期する機能はないので、Google Apps Scriptを使って自前で実装しています。定期的にNotion APIを叩いて、データを取り出しています。 コードはGitHubに公開しています。 https://github.com/Nalagami/synch-notiondb-to-spreadsheet Diagram.net(旧 draw.io) 無料で使えるブラウザベースの作図ツールです。保存場所をクラウドストレージ(Google DriveやOneDrive、Dropboxなど)にすることで、複数人で編集できるようになります。 Notionへの連携方法は、主に以下の2つがあります。 Google Chromeの拡張機能を使う 以前はこれが最も手軽にNotionに図を埋め込める方法でした。 ただ、最近はDiagram.netで図を作成してから次の方法をでリンクを発行することが多いです。 埋め込みリンクを作成する方法 Diagram.netでNotion用の埋め込みリンクを作成し、それをNotionに埋め込む方法です。 編集するときオリジナルのデータを操作するか、編集者が作成した複製を編集するか選ぶことができます。オリジナルのデータを操作する場合は、編集者にNotionのアクセス権限とは別に保存先へのアクセス権限を付与してあげる必要があります。そのため、「Notionのアクセス権限はあるけど、Diagram.netのデータ保存先(Google Driveなど)にはアクセスできない」場合は編集も表示もできなくなります。(「複製を編集」を選んだ場合は閲覧も編集もできる) まとめ 自分が仕事で使っているNotionの作図機能についてまとめてみました。今回はあくまで当社のセキュリティルールに則った場合のベストプラクティスなので、会社のセキュリティ要件によっては若干変わってくることをご了承ください。 ぜひセキュリティ担当と相談して、理想のNotion環境を構築していってください。 (番外編)miroインテグレーションの使い心地 前回の記事で紹介したので、少し使ってみました。軽く触った感じだとあまり変わった感じはしなかったです。ただ、公式でmiroの埋め込みがサポートされるようになったのは大きいですね。 ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
この記事は、 ニフティグループ Advent Calendar 2023 21日目の記事です。 この記事を読んで分かること ニフティの情シス(コーポレートエンジニア)の概況 スクラムとは何か(ざっくりと) 情シスでスクラムをやるにあたってどんな工夫をしているか  ニフティで情シス、スクラムマスターをやっている小浦です。人生で初めてクリスマスケーキを予約したので、今年はクリスマスがとっても楽しみです。豪快に1/4に切って大きいフォークでワシワシと食べる予定です。  さてさて、今日はスクラムの話をします。スクラムといっても開発チームではなく、運用メインの情シスでスクラムをどう工夫してやっているかについて話したいと思います。 ニフティの情シスとは?  名前に情シスの冠を持った組織はありますが、ニフティはエンジニア集団なので情シス的役割を果たしている人がその組織外にもいたりします。  私のチームはその冠をもった組織の中にあり、GWSやSlackなどのSaaSやオンプレのアプリケーションetcの管理運用を行っています。この記事では各SaaS、アプリを「プロダクト」と呼ぶとして、プロダクトを数えてみると24個ありました。 私のチームは情シスですが、スクラム体制を採用しています  情シスでスクラムを採用しているところはあまりないと思いますが、私のチームは約3年前からスクラム体制で活動しています。  スクラムとはチームが一丸となってプロダクトを迅速に良くしていくためのフレームワークです。スクラムでは、チームメンバーが スクラムマスター (スクラムチームをうまく機能させる人)、 プロダクトオーナー (プロダクトの未来を決め、願いを表現する人)、 開発メンバー (プロダクトオーナーの願いを実現する人)に分かれ、 スプリント と呼ばれる短い期間の中で決められたイベントを通してコミュニケーションをとりながら、そのスプリントにやるべきことだけに集中して開発とリリースを行い、それを繰り返していきます。  情シス的には次のようなメリットがあります。 目的意識を強く持ち続けることができる 突然の変更、変化に適応できる 業務共有が進み、属人化、スキルの偏りが解消される コミュニケーションの機会があらかじめ設定されているので、シャイな人が集まりやすい情シスチームでも交流が持てる などなど  複数のプロダクトを抱えていて、運用が多く、ウォーターフォール式でプロジェクトが進みがちな情シスにはあまり用いられていませんが、上記のようなメリットを享受するべく日々工夫してスクラムしています。  情シスでスクラムやっているよ、の触りについては以前のLT(下記)や、技術書典で頒布した「 ニフティのスクラム 」で紹介しているのでよろしければご覧ください。 ※当時プロダクトは14個でしたが、2023年の4月に別の情シスチームを吸収したことにより24個に増えました。開発メンバーも3名→9名に増え、スクラムチームとしてはかなり賑やかな体制になりました。 【本題】情シスでスクラムをやるにあたってどんな工夫をしているか  以前のLTや本記事の冒頭でも「情シスはスクラムに向いていない」と散々書いてきましたが、工夫したポイントについてすべて書きます。 プロダクト横断的に優先順位がわかるようにした 24個のプロダクトを1つの大きなプロダクトと見なし、スプリント内のタスク(※スクラムでは スプリントバックログアイテム といいます)を一元管理することでチーム全体で優先すべきタスクが分かるようになりました。 <そうした理由> スクラム前はプロダクトごとにタスクを管理しており、さらにプロダクトと人が属人的に結びついていたので「いまチームで最も重要なこと、急ぎで対応すべきことが何か分からない」「隣の人が忙しそうだけど手が出せない」状態で非効率的だったからです。 <実際にやったこと> すべてのタスクを スプリントバックログ と呼ばれる「このスプリントにやることリスト」に集め、重要なこと/急ぎで対応することに重みづけを行い、スプリントバックログアイテムを並べ替えて確認できるようにしました。 ▼スプリントバックログのイメージです。プロダクト関係なく、 Must (対応必須)、 Should (対応すべき)、 Could (できれば対応)で並んでいます。列は状態です。 プロダクト全体に通じるチームのビジョンを作成し、全員で同じ方向へ向かえるようにした チームビルディングを兼ねてビジョンを作成し、全員のありたい姿が一致するようにしました。 <そうした理由> 私のチームは出来た当初はいわば寄せ集めで、それぞれが目指す方向や考えていることがばらばらの状態でした。その状態を続ければ考えの違いでいつかは衝突するし、推進力も生まれないと思ったからです。 <実際にやったこと> 一つの方向に向かって進めるように、全員でありたい姿を持ち寄って言葉にまとめたチームビジョンを作成しました。 ▼ビジョンのブレストの様子 スクラムのルールで決められたイベント+αを通してコミュニケーションの機会を増やした コミュニケーションをとることによりお互いを知り、悩みやタスクをシェアできるようになりました。 <そうした理由> チーム発足時、ちょうどコロナ禍が始まったところでニフティもフルリモートワークになりました。フルリモートワークで属人的に仕事をしていると、チームの誰とも会話せず一日を終える…なんてこともありました。これでは属人化の解消もできず、チームで動いている意義もありません。 <実際にやったこと> スクラムには デイリースクラム (朝会)、 プランニング 、 レビュー 、 レトロスペクティブ といったコミュニケーションをとる機会を設けるルールがあります。これらの他に、雑談タイムや作業配信(運用などをおもむろに社内向けにライブする)なども行い会話できる機会を作っています。 特に属人化しているプロダクトについて共有会を行い、他の人でもタスクがこなせるようにした <そうした理由> 属・人・化…情シスあるあるだと思います。その人がいなくなると誰も分からない、そんな状況を打破したかったからです。 <実際にやったこと> 特に属人化が激しいプロダクトについて週次で共有会を開催し、業務共有を行ったうえでそのプロダクトの細分化されたタスク(スクラムでは スプリントバックログアイテム と言います)に対し「✕✕さん以外でもできる」というタグ付けを行いました。そのタグがついたスプリントバックログアイテムを✕✕さん以外がどれだけ消化したかについてスプリントの終わりに振り返りを行いました。 3年間情シスでスクラムをやって見えてきたこと  ここまで読んだ情シスの方は、きっと「大変そう」と思われたことでしょう。そう、スクラムはコストがかかる取り組みなのです。しかし3年間継続してみた結果、投資対効果でいうと効果の方が大きく上回ったと断言できます。もし、3年前にスクラムを始めていなかったらずっと寄せ集めチームのままで活動していたことでしょう。特に情シスは長く続いている組織が多く、ヒトも固定されていて新しい取り組みがしづらいケースが多いのではないかと思います。その現状を打破したい時に、スクラムのような型にはめるようなやり方は案外気楽ではないかと私は考えます。もちろんすべてを完璧にしてから始める必要はありません。まずは「スクラムっていう良さげなやり方があるんだって…」と、デイリースクラムから始めてみるのがおススメです。 まとめ+宣伝  今回はニフティの情シスと、私のチームで取り組んでいるスクラムについて工夫点に焦点を当ててご紹介しました。  体制が変わる前の文章になりますが、当時の開発メンバーがスクラムについてどう思っているかなどのコメントが載った本がありますのでぜひご覧ください。ニフティのスクラムマスターが寄稿しあって作った本なので、スクラムそのものに関心がある方もぜひダウンロードを!(無料です) ▼クリックするとダウンロード画面に飛びます  また、ニフティの情シスメンバーも大募集中ですのでご興味がありましたら 採用サイト をご覧ください。 明日の記事は…  明日の記事を書いてくれるShibataRyuseiさんは、実は1年目のエンジニアが全員体験するジョブローテーションという制度で3カ月間情シスにきてくれました。その後マイニフティチームに配属となり、すっかりチームの顔になったShibataさんの記事が楽しみです!
アバター
この記事は、 ニフティグループ Advent Calendar 2023  20日目の記事です。 はじめに こんにちは、IWSです。 Yotutubeで配信している NIFTY Tech Talk では運営の方からYoutubeの枠を作成してほしいという依頼を受けるときにNotionのデータベースを活用し、こういったタイトル、概要欄にしてほしいというのを書いてもらっています。その際、Zapierを使って作成依頼が来たことが分かるようにSlackに通知をしています。 今回はこの通知をどうやって作っているかを書いていこうかなと思います。 Zapierとは Notionのプロパティを読み取ってSlackに通知を行うのにZapierを使っています。 Zapier  は複数のサービスやアプリと連携するワークフローをノーコードで作成できるサービスです。今回扱うNotionやSlack以外にもGoogle Workspaceや、Githubなど様々なサービスとの連携が行なえます。 今回はZapierで簡単な以下の処理を作りたいと思います。 Notionのプロパティで「新規」が付いたら実行 タイトルとURLを取得してSlackのチャンネルにメッセージで送信 Zapier まずは、あらかじめNotionにデータベースを作っておきます。 今回はプロパティのステータスが「新規」になったときにSlack通知をしてもらうので、そのプロパティを作成しておきます。 では早速Zapierを触っていきましょう! Zapierのダッシュボードを開いて Create Zap を押すとZap(ワークフロー)の作成画面が開きます。 最初はTriggerとActionの2つが配置されていると思います。 まずはTriggerから「プロパティのステータスが【新規】になったとき」のトリガーを作っていきましょう。 Triggerを選択するとどのサービスをトリガーとして使用するかが選べるので中からNotionを選択します。そうするとNotionのどのイベントをトリガーに使うか選べるので「Update Database Item」を選択。 Account, Triggerの項目ではNotionのどのアカウント、ページをZapで使用するか選んでいきます。 Notionの自分のアカウントとの紐づけ画面に移動するので Choose → Connect a new account で画面に従っていきましょう。Zapierで使いたいページにチェックするのを忘れずに、うまく行っていればTriggerの項目で使いたいDBの名前が表示されていると思います。 ここまでできたら最後に Test から使いたいDBのアイテムが取れているかを確認しましょう。 ステータス:新規 に設定した オンライン勉強会#4 がばっちりとれていますね! ここで忘れずにZapier のトリガーに使いたい条件のアイテムを選択しておきましょう(今回はステータスが新規になっているもの)、後ほどテスト実行の際に使用します。もし作っていなければ右下のペンマークからテスト用のデータを作ることもできます。 Continue with selected record を押すと Change Action のメニューが表示され、次になにを行うかを選ぶことができます。今回はFilterを選びましょう。 Filterではどの条件のときにZapを実行するかを設定できます。 今回はステータスに「新規」が付いたら実行してほしいので以下のように設定しました。 AndやOrでより複雑な条件を指定することもできます。 設定ができたらContinueからフィルターのテストをしましょう!先程選んだテストデータを使いフィルターのテストを行うことができます。 テストデータにフィルターがマッチしたらOKです! フィルターが完成したらいよいよSlackへ通知を送信する部分を作成しましょう!Continueを押すとまたChange Actionが出るので一覧からSlackを選んで追加します。 どういうEventを発生させるかを聞かれるので今回はメッセージの送信ができる Send Channel Message を選びます。 AccountタブではNotionのときと同じ用に Connect a new account からリクエストを許可します。 Actionタブでは送信先のチャンネル、送信メッセージの内容などを設定できます。 メッセージにはNotionのURLやタイトルなども含めることができるので色々試してみてください。 使用できるフォーマットはこちらのページにまとめられています。 https://help.zapier.com/hc/en-us/articles/8496025607181 というわけでシンプルに自分へのメンションとページのタイトル、URLで作ってみました 今回は使用しませんが、他にもスレッドへの投稿、画像の添付、スケジュール投稿など細かい設定ができるので触ってみてください。 最後にきちんとSlackに届くかテストをしてみましょう どうですか?Slackにメッセージが届いたでしょうか? まとめ 今回はZapierでSlack、Notionの簡単なZapを作ってみました。Zapierは思いつき次第でもっと便利なものを作ることもできます。ぜひ一度Zapierを触ってみてください!この記事を読んでZapierに興味を持ってもらえればとてもうれしいです。 また、NIFTY engineering には他にも Zapierについての記事 が投稿されています。Zapierについてもっと知りたくなった方はぜひそちらもご覧ください! 明日の ニフティグループ Advent Calendar 2023 は @yCola さんです。お楽しみに! ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
インフラチームに所属しております松本と申します。 当社のお客様サポートセンター内の業務作業環境は、 情報漏洩やセキュリティ強化を考慮し、約15年前から タイトルにある環境を採用しております。 接続元機材は環境初期より、下記4点の特徴【コンセプト】 がある端末(筐体)を用いております。 1.記憶装置を搭載せず 2.単体で起動するOSでは業務遂行ができない 3.【画像転送型】シンクライアント方式に特化 4.端末ごとのキッティング作業が不要 また上記機材から接続する先は、時代とともに オンプレミス環境のBladePCから仮想デスクトップ、 そして現在はDaaSへと変化しております。 接続元機材や接続先環境自体は、H/WやHyperVisorの EOLもしくはEOSLごとにリプレースや見直しを行い、 事業継続を最優先に計画されますが、デスクトップOSの 寿命もこのリプレース計画に影響を与えます。 直近の当社は、これから約一年程度で以下対応を 順次進めるリプレース期間に突入します。 ※以下の丸数字と色は、イメージ図に対応しています。 ① 接続元機材更新(約7年ぶり要因はEOL)   ※【コンセプト】に変更なし ② 接続先環境更新(約5年ぶり要因は利用中DaaS提供終了)   ※約8年ぶりにオンプレミス+設計~構築も内製化   ※自社資産化による柔軟なスケール変更への対応   ※完全内製化による技術力の向上から、日々の安定した    運用・保守だけではなく、迅速な障害対処を目指す    ③ デスクトップOS更新(Windows10のEOLまでに)   ※無償期限:2025年10月14日   ※有償期限(ESU):2028年10月(無償期限から最長+3年間)   ※ESUとは「拡張セキュリティ更新プログラム」のことです ご興味がある方、一緒にリプレースしましょう。 ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
この記事は、 ニフティグループ Advent Calendar 2023 18日目の記事です。 風邪を引いてアドベントカレンダー遅刻しました はじめに ニフティ株式会社新卒入社一年目の中井です。今日は皆さんに会社でも回せるガチャを実装する方法、もとい、SlackワークフローからGoogle Apps Scriptを実行する簡単な方法についてご紹介します! 早速ですが、皆さんは普段、Slackを使われていますか? ニフティでは、社員なら使わない日はないんじゃないかというほどSlackが利用されています。やっぱり単なるチャットツールとして以上に、Slackから様々なアクションを起こすことができる点が強いんですよね。そんな部分の一つの例として、今回は簡単に実行できるガチャを作ってみましょう。 ちなみにガチャというのは別に私がガチャを引きたかったわけではなくて、私自身は全然ソシャゲとか知らないので、単にガチャは楽しいよねという周囲の要望に応えただけであって、あくまでも技術的な探求のためにですね、はい。 なお、今回利用するSlackのワークフロー機能(を作成するワークフロービルダー)は有料プランでないと利用できないので、個人で試される場合はそこにご注意ください。とはいえ個人だと有料プラン高いですよねえ……。 SlackワークフローとGoogle Apps Scriptについてかんたんに Slackワークフロー とは、ざっくり言えばSlackの中のリンクなどから開始できる一連のアクションのことです。最近大きめのアップデートがあって、できることがかなり増えました。アクションには例えばメッセージを送信したり、チャンネルに招待したり、そしてGoogleスプレッドシートに書き込んだりということができます。 Google Apps Script とは、かんたんに言えばGoogleの基盤上で簡単なJavaScriptのスクリプトを動かすことができるというサービスです。このサービス、何がとんでもないかというと、まず1つは無料なこと、そしてもう1つは実行タイミングの設定が豊富なことです。例えばGoogleスプレッドシートに変更があった時に実行、のようなことができてしまうんですよね。 さて、なんとなくおわかりでしょうか? そう、Slackからガチャを回すとはこういうことです。 まずSlackワークフローからGoogleスプレッドシートに書き込む 書き込みに対する変更通知でGoogle Apps Scriptを発火する Google Apps Scriptさえ発火してしまえばこちらのもの。JavaScriptでなんでもできるので、ランダムに文字列を抽選して、結果をSlackのIncoming Webhook機能を通してチャンネルへ投稿するということが可能なわけですね。便利! スプレッドシートを作成する ところで、実はGoogle Apps Scriptにはざっくり2種類があります。 スクリプト単独で存在するもの スプレッドシートに結びついて存在するもの 今回は「スプレッドシートが変更されたときに発火されてほしい」ので、スプレッドシートに結びついて存在するスクリプトのほうが簡単です。すなわち我々のガチャづくりはスプレッドシートを作成するところから始まります。 おもむろに次のURLをタイプしましょう。 https://spreadsheets.new すると新規にスプレッドシートが作成され、白紙のスプレッドシートが立ち上がります。わからなくなる前に、左上のタイトル欄に適当に「ガチャ」とでも入れておきましょう。このスプレッドシートはあなたのGoogleドライブに自動保存されています。 さて、後々設定するSlackワークフローでは、スプレッドシートのシート全体を表と見立て、そこに行を追加するという形でスプレッドシートを編集することができます。そのために最低限、表として認識されるようにシートを修正します。 シート名をわかりやすく「実行履歴」に変更する。 シートの一番左上のセルに「実行者」と入力(最初の行は表のヘッダー行として扱われます)する。 これで1列の表ができました。実行されるたびに「実行者」の下にどんどんと行が増えていくイメージですね。もちろん、実行した時刻や内容など、列をもっと増やすこともできます。 さて、ここからGoogle Apps Scriptでガチャを作っていきます。 「拡張機能」→「Apps Script」を開いて、ガチャを引くコードを書いていきましょう。 一つの例ですが、ここでは次のようなコードを使ってみました。これは、いわゆるカタカナから3文字を抽出して単純に連結するというものです。もちろん他にも、もしかしたら0〜9の数字などにしてスロットっぽくするなどの応用もあるかもしれませんね。夢も膨らみます。 function gacha() { const KATAKANA = "アイウエオカキクケコサシスセソタチツテトナニヌネノ" + "ハヒフヘホマミムメモヤユヨラリルレロワン" + "ガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポァィゥェォッャュョヴー"; const pick = () => { return KATAKANA[Math.floor(Math.random() * KATAKANA.length)]; }; const word = pick() + pick() + pick(); console.log(word); } そしてプロジェクトを保存した上で実行ボタンを押すと… この通り、下部の「実行ログ」の部分に、カタカナ3文字が適当に表示されたのがわかると思います。コードは上手く動いていそうですね。 次は、これをSlackのIncoming Webhookを使ってSlackに投稿する部分を作っていきます。 SlackのIncoming Webhookをつくる Slackの Incoming Webhook とは、外から特定のURLにアクセスすることにより、予め指定したチャンネルにメッセージを送信することができる魔法です。このURLを用意するためには、まず「アプリ」を作成して、そのアプリでIncoming Webhookの機能を有効化するというステップが必要です。しかし、これをGUIでやるとなかなか大変になります。主に説明が。 そこで、その辺を簡単に作れちゃうURLを生成しておきましたので、ぜひ使ってください。 https://api.slack.com/apps?new_app=1&manifest_json=… ちなみにこのURLにアクセスすると、次のようなApp Manifestを持ったアプリを一つ新規に作成することになります。ざっくりと説明すると、Incoming Webhookを一つ、そしてそれを利用するために必要なBot情報を一つ追加しています。 { "display_information": { "name": "gacha" }, "features": { "bot_user": { "display_name": "gacha", "always_online": false } }, "oauth_config": { "scopes": { "bot": [ "incoming-webhook" ] } }, "settings": { "org_deploy_enabled": false, "socket_mode_enabled": false, "token_rotation_enabled": false } } 何はともあれ、とりあえず先のURLをクリックすればいいんです。画面の指示に従ってどんどん進めちゃってください! アプリをインストールするワークスペースを指定する。 色々進んだ後、吹き出しなどで誘導してくれるボタンに従って、アプリのインストール先のワークスペースを指定する(上と同じでOK)。 ここまで終わると、もうすでにIncoming Webhookの作成は完了しています。URLを確認しにいきましょう。 画面左側から「Basic Information」へ進む。 「Add features and functionality」をクリックして開く。 中に並んでいるボタンたちのうち「Incoming Webhooks」を選ぶ。 ページの下方にURLが表示されている。 URLの横に「Copy」ボタンがあると思いますので、URLをコピーしておいてください。 Incoming WebhookのURLをGoogle Apps Scriptのプロパティに設定する 先のURLをGoogle Apps Scriptの スクリプトプロパティ という機能に登録していきます。 一応、理屈としてはとにかくURLが叩ければよいわけですから、別に直接文字列としてソースコードに貼り付けても問題はないです。ただ、なにかできちゃう秘密の文字列を直接コードに貼るのはうっかりGitHubで流出みたいなことになりかねないのでやめておいたほうがいいな、と個人的には思います。 まず、Slackの設定からGoogle Apps Scriptの画面に戻りましょう。そして左側のバーから「プロジェクトの設定」を開き、スクリプトプロパティを追加します。INCOMING_WEBHOOK_URLという名前のプロパティで、値には先程コピーしたURLを入れ、「スクリプトプロパティを保存」を選択してください。 これで、Google Apps Scriptのコード側からはINCOMING_WEBHOOK_URLという名前のプロパティを問い合わせるだけでURLを取得することができるようになりました! 先程のコードをもう少し書き換えて、Slackに送るコードを追記します。 function gacha() { const KATAKANA = "アイウエオカキクケコサシスセソタチツテトナニヌネノ" + "ハヒフヘホマミムメモヤユヨラリルレロワン" + "ガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポァィゥェォッャュョヴー"; const pick = () => { return KATAKANA[Math.floor(Math.random() * KATAKANA.length)]; }; const word = pick() + pick() + pick(); console.log(word); const incoming_webhook_url = PropertiesService .getScriptProperties() .getProperty("INCOMING_WEBHOOK_URL"); UrlFetchApp.fetch(incoming_webhook_url, { "method": "post", "contentType": "application/json", "payload": JSON.stringify({"text": word}), }); } このコードを初めて実行すると、アクセス権限を要求されるかもしれません。これはUrlFetchAppという外部APIを叩くライブラリを利用するためです。 きちんと承認すれば、Incoming Webhookを設定したチャンネルにメッセージが届くはずです。 コード部分はこれで完成。残りはこれをSlackワークフローから呼び出せるようにするだけですね! スプレッドシート変更時に実行する Slackワークフローとの連携はスプレッドシートの変更イベントで行いますので、Google Apps Scriptにそのトリガーを設定します。左のメニューから「トリガー」を選択し、次のような設定でトリガーを追加してください。 注意点は、イベントの種類で「変更時」を選ぶことです 。ややこしいことに「イベントの種類を選択」の部分には「編集時」と「変更時」の二つがありますが、「編集時」はどうも人間が編集した場合のトリガーで、今回のようにSlackワークフローから自動で連携されるケースではトリガーされないようでした。 保存するとまた承認ダイアログが現れます。スプレッドシートを起点にしたことでスプレッドシートへのアクセスが要求されていますので、ここは承認して次へ進みましょう。 設定できたらスプレッドシートへ戻り、何でも良いので適当な変更を加えてみてください。A2セルに適当な文字を打ってみるとか。しばらく待って、Slackへガチャ結果が通知されたら問題なく動作しています! Slackワークフローからスプレッドシートへ書き込む いよいよ最後のステップです。SlackのWFを作りましょう。 左上のワークスペース名をクリックし、「ツールと設定」→「ワークフロービルダー」を選択します。この選択肢は、有料プランに入っていないと現れないかもしれません。 開いた画面の右上の「ワークフローを作成する」を押し、ついで「Slack内のリンクから」として進んでいきます。右側のステップ欄でsheetsなどと検索して、「スプレッドシートに追加する」を選んでください。 現れたフォームで、先程までに準備したシートを指定します。これで保存です。 最後にWFの公開を行います。これは別に全世界に大公開ということではなく、WFの編集が終わったからワークスペースで使用可能な状態にするよ、くらいの意味です。 公開ボタンから画面の指示に従って適当な説明を付ける。 必要ならコラボレーターを追加して「公開」にすすむ。 最後のフォームでリンクをコピーする。 最後にコピーしたリンクはもう準備万端で、踏めばガチャが引けるようになっています!次に進みましょう。 Slackで実行してみる チャンネルに貼ってみると、こんな感じの枠がでます。そして枠をクリックすると… いい感じですね!! このリンクはどこにあっても良いので、チャンネルにピン止めするでも、ブックマークバー的なところに登録するでも、お好きなところにどうぞ。 まとめ 今回はSlackワークフローからスプレッドシートの変更通知を通してGoogle Apps Scriptを実行する例を実装してみました。今回はガチャのために使いましたが、このスプレッドシートの変更通知を利用するという方針は、Zapierなど他のスプレッドシートと連携するツールへもすぐに応用できます。また、今回はSlackが外部API呼び出しに対応していないために回りくどい手法を取りましたが、元々Google Apps ScriptにはGETリクエストでスクリプトを実行するなどの、さらに便利な機能もあります。これからも色々できることを探求していきたいです。…ガチャの探求ではないですよ? ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター