概要 「NIFTY Tech Talk」は、ニフティ株式会社の社員が主催する、技術に関するトークイベントです。 このイベントでは、ニフティグループの社員が業務を通じて学んだ知見や経験をLT形式で発信しています。 今回は、富士通クラウドテクノロジーズ株式会社のニフクラエンジニアミートアップの方々もゲストとして参加されます。 テーマは「落ちないシステムの作り方」として、業務で扱っているシステムが安定して稼働するための工夫やノウハウを、現場社員がLT形式で紹介してくれます。 基本情報 日程:4月19日(水)20:00〜21:30 配信方法:YouTube Live, Zoom 視聴環境:インターネット接続が可能なPC/スマートフォン 参加方法: connpass にて登録をお願いいたします。 こんな方におすすめ システムの安定稼働を目指しているエンジニア ニフティやFJCTの技術や風土に興味があるエンジニア タイムテーブル コンテンツ 19:50-20:00 入場開始 20:00-20:05 挨拶 20:05-20:20 落ちないシステムって何?可用性の基本と仮想環境での可用性の高め方(仮) 20:20-20:35 「落ちないシステム」実現に向けてアプリ開発でできる事って何だろう?(仮) 20:35-20:50 サービス依存度の高い環境でも安定稼働するポータルサイトの作り方 20:50-21:05 月1億PVのニュースサイトを落とさない技術 21:05-21:30 Q&Aセッション 21:30 中締め 残れる人は残って交流 内容 落ちないシステムって何?可用性の基本と仮想環境での可用性の高め方(仮) 登壇者名:奥山 洋平 富士通クラウドテクノロジーズ株式会社 「落ちないシステム」実現に向けてアプリ開発でできる事って何だろう?(仮) 登壇者名:北條 裕 富士通クラウドテクノロジーズ株式会社 サービス依存度の高い環境でも安定稼働するポータルサイトの作り方 登壇者名:渡邊 大介 ニフティ株式会社 会員システムグループ第1開発チーム @niftyトップページなどの自社WEBサービスの開発・運用担当をしています。 最近はプライベートでChatGPTを活用したサービスを何か作れないか模索しています。 月1億PVのニュースサイトを落とさない技術 登壇者名:中村 伊吹 ニフティ株式会社 会員システムグループ第2開発チーム 新卒入社5年目。 ニフティニュースの開発リーダーを担当し、最近はモダンなフロントエンド開発を学習中。 男女混成チアリーディング元日本代表。 ニフティグループでは一緒に働く仲間を募集中です 新卒採用、キャリア採用を実施しています。ぜひ リクルートサイト をご覧ください。 ニフティエンジニアが業務で学んだことやイベント情報を エンジニアブログ にて発信しています! ニフティエンジニアのTwitterアカウント NIFTY Tech Talkのことや、ニフティのエンジニアの活動を発信していきます。 Tweets by NIFTYDevelopers 「NIFTY Tech Day 2022」を開催しました 技術イベント「NIFTY Tech Day 2022」のアーカイブはこちら NIFTY Tech Day 2022 アンチハラスメントポリシー 私たちは下記のような事柄に関わらずすべての参加者にとって安全で歓迎されるような場を作ることに努めます。 社会的あるいは法的な性、性自認、性表現(外見の性)、性指向 年齢、障がい、容姿、体格 人種、民族、宗教(無宗教を含む) 技術の選択 そして下記のようなハラスメント行為をいかなる形であっても決して許容しません。 不適切な画像、動画、録音の再生(性的な画像など) 発表や他のイベントに対する妨害行為 これらに限らない性的嫌がらせ 登壇者、主催スタッフもこのポリシーの対象となります。 ハラスメント行為をやめるように指示された場合、直ちに従うことが求められます。ルールを守らない参加者は、主催者の判断により、退場処分や今後のイベントに聴講者、登壇者、スタッフとして関わることを禁止します。 もしハラスメントを受けていると感じたり、他の誰かがハラスメントされていることに気がついた場合、または他に何かお困りのことがあれば、すぐにご連絡ください。 ※本文章は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/ ) で公開されています。
はじめに こんにちは。新卒3年目メンダコです。普段は社内NW・サポートセンターNWの担当をしています。最近午後の紅茶を午前に飲んだら怒られが発生しました。 業務とは関係ないのですが、趣味でCTFというものをやっています。初心者向けの大会にしか参加していないのですが、とても楽しかったので今回はCTFの紹介をしたいと思います!! CTFとは 概要 CTFとは「Capture The Flag(キャプチャーザフラッグ)」の略で、セキュリティに関する競技会です。CTFでは、様々なセキュリティ課題が用意され、参加者はそれらの課題を解決することでポイントを獲得します。セキュリティエンジニアやハッカーなどが参加し、自身の技術を磨くための場としても利用されています。 大会で有名なものとしては、アメリカのDEFCON、国内ではSECCONがあります。 ルール flagと呼ばれる文字列が隠されているので、それをセキュリティの知識を使って探し出します。探し出したflagを回答サーバに送信することで、ポイントを獲得できます。flagの形式については、flag{hogehoge}や、FLAG_fugafugaなど大会によって違うので、ルールを確認しましょう。 大会によって違いますが、制限時間は12時間~48時間ぐらいがほとんどです。 個人戦だけでなくチーム戦もあります。 出題される問題について セキュリティにかかわる技術を使用して解く問題が出されますが、とても出題範囲が広いため幅広い知識が必要になります。 出題分野、出題範囲については大きく分けると次の通りになります。 出題分野 出題範囲 ネットワーク 信号処理通信技術 ネットワークトラフィックのキャプチャ フォレンジクス 情報の秘匿 ログ解析 ファイルフォーマットデータの復元 Web技術 Webアプリケーションの脆弱性 データベースアクセス プログラミング プログラミング言語 組み込み技術 リバースエンジニアリング 暗号化技術 符号化公開鍵基盤(PKI) 脆弱性調査 脆弱性バグ攻撃コードの送信 チームで参加する場合は、何か一つ得意分野を作ってチームメンバーと手分けして問題を解くのがいいと思います。 取り組む際にあると便利なツール たくさんあるのでここでは主要なものだけ紹介します。 Google 一番大事。 わからないことがあったら検索しよう!!!!!!!! 大会中でも検索できます!!!!!!!!! Wireshark ネットワーク問題で、パケットを解析するのに使います。 CTFでpcapファイルが出てきたらこのツールの出番です。 バイナリエディタ その名の通りバイナリを編集できるエディタになっています。 ヘッダ情報を書き換えて、開けないファイルを開けるようにしたり、バイナリの置換をする際に使用します。 ちなみに私は私生活ではMacを使用しているので、0xEDというバイナリエディタを使用しています。 CTFの勉強法 基本は過去問・常設CTFを使って、実際に問題を解いて手を動かしてみるのが初心者・経験者ともにおすすめの勉強法になっています。 過去問 大体の大会の問題は以下のサイトを探せばあると思います。あまり古い問題だと環境によっては動かないことがあるので注意する必要があります。 GitHub captf.com 常設CTF 有名どころとしては以下の4つです。私は一部のサイトの問題しか見たことがないのですが、初心者向けの問題も結構多めです。 ksnctf akictf CpawCTF Flaggers 本 この2冊が初心者入門にお勧めと有名な本です。ルールの説明などあるのでCTFに参加したいけど、問題のイメージがつかみにくい人にいいと思います。 セキュリティコンテストチャレンジブック(通称ハリネズミ本)には、演習ファイルもついています。 セキュリティコンテストチャレンジブック -CTFで学ぼう! 情報を守るための戦い方 Hacking: 美しき策謀 第2版 ―脆弱性攻撃の理論と実際 大会の探し方 SECCONについては公式サイトに日程が載っています。 CTF関連の勉強会などの情報もあるのでとりあえずここを見るのがいいと思います。 https://www.seccon.jp/2022/ SECCON以外の大会は以下のサイトに日程が載っています。 こちらで初心者向けの大会を探すのもいいと思います。 https://ctftime.org/ 結局やって何の役に立つの? 例えば、ネットワーク問題であれば、トラフィックをキャプチャする技術を身に着けることができます。それを覚えることで、ネットワークの通信が通らないときなどの、トラブルシューティングに役立てることができます。 Web系の問題であれば、脆弱性をついて攻撃をして問題を解きます。攻撃方法を知ることにより、安全なアプリケーションの作り方を理解できるようになります。 上記のように実際の開発や運用などでも役に立つことがいっぱいあると思います! 注意点 サーバーをハッキングしたり、ソフトウェアの脆弱性を突いたりするような問題がありますが、 許可された範囲外で行うと、違法行為となる可能性があります。 CTFで出されている問題は、出題者が攻撃されることを前提に公開しているものなので問題ありません。 許可された範囲内で楽しみましょうね! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
こんにちは、気づけば入社してから3年目も終わろうとしている宮本です。先日は、NIFTY Tech Talk #9 「SvelteKit, Next.jsの導入事例紹介など 〜ニフティのフロントエンドの今とこれから〜」で担当している @nifty トップページのNext.js化について話してきました。当日ファシリテーターをしていた筑木くんの紹介記事がすでに掲載されているので、ぜひご覧ください! 紹介記事: SvelteKit, Next.jsの導入事例紹介など 〜ニフティのフロントエンドの今とこれから〜 NIFTY Tech Talk #9 を開催しました! さて、今回の記事はここからが本題です。Tech Talk中で@niftyトップページではTypeDocを使いドキュメントを作成していると軽く触れました。フロントエンドアプリケーションのドキュメント生成といえばやはりStorybookが有名どころですが、今回はTypeDocをご紹介させていただこうと思います。 TypeDocってなに? TypeDoc は、TypeScriptで記述されたアプリケーション用のドキュメント生成ツールです。記述方法は簡単で、JSDocに非常によく似たTSDoc形式でコード内にコメントを書いていくだけ。あとはドキュメント生成コマンドを打てば、自動でドキュメントが作成されます。めっちゃ便利。 簡単な例ですが、次のようなドキュメントを作成することができます。こちらは create-next-app で自動生成したサンプルアプリケーションに、いくつかコンポーネントやカスタムフックを追加したアプリケーションです。 画像は型情報についてのドキュメントで、これを生成した元のコードは下のようになってます。TypeScript本来の型定義に加え、軽くコメントで補足している程度です。細かい記法についてはかなり量が多いので、公式ドキュメントをご覧ください。 export type UseCheck = { /** * チェック済みであるかを表す */ isChecked: boolean; /** * チェック状態を切り替える * @returns */ toggleCheck: () => void; }; TypeDocの設定 ここからは、アプリケーションにTypeDocを導入する方法を紹介します。create-next-appなどでサンプルアプリケーションを作成してこの手順を試してみると、どのようなドキュメントが生成されるのかなどもわかりやすいと思います。 1. インストール yarn add -D typedoc 2. 設定 TypeDocはドキュメントをビルドするタイミングで設定を入れることもできますが、typedoc.jsonというファイルを用意していると、毎回自動で設定を読み込んでくれるので手間がかかりません。 最初に、必須の設定のみ追加しておきます。schemaは入れておくとvscodeでの補助が効くので便利です。 entryPoints:ドキュメントを生成する対象のコードが存在する最上位のディレクトリを指定します。 entryPointStrategy:ドキュメントを作成する元になるファイルの指定方法を変更します。 デフォルト設定ではentryPointsに指定したディレクトリのindex.tsファイルを起点として指定しようとするため、そもそもindex.tsを用意していない場合は生成自体ができません。ディレクトリごとに必ずしもindex.tsを用意しないフロントエンドのために、全ファイルを起点にドキュメントを生成するようにします。 typedoc.json { "$schema": "https://typedoc.org/schema.json", "entryPoints": ["./src"], "entryPointStrategy": "expand", } 3. ドキュメント生成 このコマンド一つでドキュメントを生成することができます。 yarn typedoc 4. プラグイン さて、上記までの手順でドキュメントを生成することはできるのですが、実際に生成されたドキュメントを見るとデフォルトでは結構見づらいです。特に辛いのが、このサイドバー……。スラッシュが入っていることからも分かる通り、entryPointsで指定したディレクトリからの相対pathをそのまま利用しています。 ファイルごとに表示されているが、全ファイルが同一階層で表示されてしまう だいぶ手抜き気味なこのサンプルこそ9ファイルしか用意していないのでまだ良さそうに見えますが、実際のアプリケーションではもっとファイル数も多いと思います。その分がずらっと並ぶと考えると、かなり見づらくなってしまうでしょう。 うん、これは無理です、諦めよう……。と思いましたが、幸いTypeDocにはさまざまなプラグインがあります。 フロントエンドのドキュメントを書く場合は、以下のどちらかが使いやすいと思います。なお、今回ここで挙げた両方を適用すると、ファイルが階層を無視して統合されたりと使いづらくなってしまったのでご注意を。 typedoc-theme-hierarchy typedoc-theme-hierarchyは、サイドバーに表示されるファイル名が実際のディレクトリと同じように階層化されて表示できるテーマプラグインです。テーマプラグインとは、生成されるドキュメントの見た目のみに手を入れるプラグインです。 注意点として、テーマプラグインはTypeDocが0.23にアップデートした際に後方互換無しで新しくなったため、古いテーマプラグインは使えない可能性があります。 導入方法はyarnでインストールし、設定ファイルで利用するテーマを選択します。 yarn add -D typedoc-theme-hierarchy@^3.0.0 typedoc.json { "$schema": "https://typedoc.org/schema.json", "entryPoints": ["./src"], "entryPointStrategy": "expand", "theme": "hierarchy" } hierarchyテーマを適用することで、画像右のような階層表示がTypeDocにも適用されるようになり、だいぶ見やすくなります。 defaultテーマ(左)とhierarchyテーマ(右) typedoc-plugin-merge-modules 二つ目の方法は、typedoc-plugin-merge-modulesを利用する方法です。entryPointStrategyをexpandにした場合、デフォルトでは1ファイル=1モジュールとなります。それをこのプラグインを用いることで複数のファイルをTypeDoc上で一つのモジュールとして扱い、関連する機能ごとにまとめることができます。 yarnやnpmでインストールし、設定ファイルにmergeModulesMergeModeを追記します。 yarn add -D typedoc-plugin-merge-modules typedoc.json { "$schema": "https://typedoc.org/schema.json", "entryPoints": ["./src"], "entryPointStrategy": "expand", "mergeModulesMergeMode": "module" } mergeModulesMergeModeはモジュールをまとめ方を選択するオプションです。以下の3パターンがあります。 project:全ファイルを1モジュールとして扱う ファイルや関数ごとに追記する必要がない アプリケーション全体で定義している関数の数が多いとわかりづらくなる module:明示的にファイルごとのモジュール名を指定し、同じモジュール名がつけられたファイル全てを合わせて1つのモジュールとして扱う 関連している機能をごとにまとめて1モジュールとして扱える ファイルごとにモジュール名を追記する必要がある module-category:同一のカテゴリタグに含まれるものを1モジュールとして扱う ドキュメントを記述する関数や変数ごとにカテゴリタグを追加する必要がある 個人的な感想としては、手軽さはprojectですが、コンポーネントやカスタムフックが多くなってくると、projectだとややドキュメントを追いづらいように感じました。一方でmoduleモードではファイルへの記述は増えるものの、機能の分割基準がはっきりしているのであれば、自由にモジュールの分割基準を決められるため、比較的管理しやすいように感じています。module-categoryモードもcategoryタグの使い方次第ですが、moduleモードとそう変わらないかもしれません。 下の画像の場合では、itemページに関わる以下のファイルを同一のitemモジュールとしてファイルにmoduleタグを追記し、まとめています。ごとに利用する関数やタイプがはっきりしている場合では、モジュール=機能という単位でドキュメントをまとめられるこの方法がわかりやすいかもしれません。 types/item.ts component/item.tsx pages/item/[id].tsx itemページに関連する複数のファイルをまとめて一つのモジュールとしてドキュメントを生成 実際に生成してみて まず初めにぶっちゃけてしまうと、フロントエンドのコンポーネントに特化したドキュメントとしてTypeDocを考えると、結構使いづらいかなと感じています……。というのも、UIドキュメントの代表格であるStorybookと異なり、直接コンポーネントの見た目や動作の確認などはできないためです。画像を添付することはできますが、変更があった際は画像を変更しなければどんどん古びてしまいます。そして、変更のあるたびに画像を作成して入れ替えて……というのは実際の手間としては些細なことですが、些細だからこそ凄まじく面倒です。フロントエンドのUIドキュメントという点ではやはりStoryBookの方が便利に感じました。 TypeDoc自体はフロントエンドアプリケーションというより、npmなどで公開されているような一般的なライブラリに適しています。出力結果に見た目というものが存在しない関数では、自動で型情報を取得してドキュメントとして表示してくれるだけでも結構ありがたいです。 一方で、コンポーネントそのものというよりは、細かいロジックを含むカスタムフックの振る舞いを記述するにはかなり向いていると思います。特に再利用されることの多いカスタムフックでは、しっかりドキュメントを書けばそれだけ後の開発が楽になると思います。また、コンポーネントではない関数について記述する分にも、こちらはTypeDoc本来の想定された使い方になるので十分使いやすいかと思います。 コンポーネントはStoryBook、コンポーネント以外はTypeDocに記述するようにして書き分けるというのが案外良いかもしれません。 最後に注意点ですが、exportされている関数・クラス等をもとにドキュメントを生成するという性質上、VueやSvelteのようなファイル内でコンポーネントを明示的にexportしないフレームワークでは、そもそもドキュメントの生成自体ができません。SvelteKitのサンプルアプリケーションからドキュメント生成を試してみましたが、一部のexportしているもののみドキュメントを生成し、肝心のコンポーネントについては何も出力されませんでした。この辺り、やはりそもそもフロントエンドアプリケーション向けに特化して作られたツールではないというあたりが大きい気がします。 ドキュメントを生成してみるという点では非常に楽に始めることができるため、一度自身のアプリケーションで生成してみて、使い勝手がどうか試してみるというのが良いかもしれません。 参考 Home | TypeDoc Create Next App | Next.js typedoc-theme-hierarchy – npm typedoc-plugin-merge-modules – npm We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
はじめまして、新卒2年目サービスインフラチームのムサシです。 突然ですが、こんな状況になっていないでしょうか? 「いつも同じ人が問い合わせ答えてるなあ。」 「でも自分でしっかり答えられる自信はないな…。その辺りの仕様は自信ないし…。」 とか、 「この件は自分が回答してないから聞かれてもよくわからないな。」 「時間かけて調べていたけど、この間Aさんが対応した件と全く同じだった…。」 とか。 これではいけませんね。仕様問い合わせ・調査/対応依頼回答で属人化が起きてしまっている状態です。 そんな回答の属人化を解消するために私のサブチームでは問い合わせ共有会を開いています。 問い合わせ共有会、こんな感じでやっています。 日々の問い合わせの内容と回答を共有する会です。週に1回、30分だけサブチームで共有会用に時間を取っています。 進め方を紹介するので、是非みなさんもやってみてください。 ①共有会までに問い合わせをチェック その週に来た問い合わせを見直して、「会話が長すぎて読む気がしない。3行でまとめて!」「自分では答えられなさそう。これどういうこと!?」というものをピックアップ。ピックアップした問い合わせはその日の共有会の議事録ページに書いておきます。何が聞きたいかも合わせてメモ。 【Tipsその1】 このとき、読めば理解できそうなものは個人的に読むようにします。意外と30分は短い。 【Tipsその2】 もし初歩的な質問だと思っても、どんどん聞いてOKです。新しく入ってきた人も同様に分からない可能性が高いですし、こういうのを聞いても良いんだ!っていう空気作りにもなると思います。 ②ピックアップされた問い合わせの確認タイム 議事録ページに書かれた問い合わせについて、担当した人が答えていきます。経緯や前提知識を共有していく中で、新しく疑問があれば追加質問します。 これらの質問と回答は議事録に付け加えていきます。これによって、昔対応した記憶がある…とか、口頭で伝えられてきたような「頭の中にしかない情報」をどんどん文として残すことができます。楽ちん。 【Tipsその3】 「途中で出てきた○○連携っていうのは何のこと?」「どこを見たらそれを他の人でも調べることができる?」など、次に似たような問い合わせが来た時に自分は答えられるか?という視点を持つと役立つと思います。 数ヵ月やってみた結果。そして今後の課題。 実は既に問い合わせ共有会を始めて4~5ヵ月経っています。この辺りで1度ふりかえりを入れて、参加者でGood/Badを話し合ってみました。というわけで、ここからは実際にやってみた感想の紹介です。 Goodな点 ①仕様についても詳しくなっていった 同じ問い合わせが来ることはほとんどありませんが、追加質問や関連する事項の確認を通してフローを確認したりコードを読みに行ったりしたため、少しずつ仕様に詳しくなっていきました。そのため、問い合わせ回答以外にもPBRや作業時のふとした疑問にも効果がありました。新しいメンバーが増えた時にも活用できそうですね。 ②他チームへも浸透してきた 似たような悩みを抱えていた他のサブチームでも問い合わせ共有会が浸透してきました。他のサブチームではピックアップ方式ではなく、すべての問い合わせをみんなで1つ1つ確認していく流れでやっているそうです。問い合わせの量に応じて、自分のチームに合わせてカスタマイズすると良さそうですね。 Badな点とその対策 ①準備に時間がかかる すべての問い合わせをチェックしてリストアップする、ということを私が行っていたのですが、量が多い週は準備に数十分かかってしまっていました。 この課題については週1回30分→週2回20分にすることで、1回あたりの確認対象を減らし準備期間を減らすようにしました。また、そうすることで全ての問い合わせを見る余裕も生まれました。 ②この目標って達成できるのか? 問い合わせ共有会は「チームのみんなが問い合わせに回答できるようになる」ために行っていたのですが、多種多様な問い合わせに完璧に1人で答えるというハードルはなかなか高いものでした。達成できる気がしない目標があっても飾りになってしまうので、一歩手前の段階に再設定してみました。 みんなが回答できるために「ナレッジを溜める」。こっちの方が参加のモチベ上がりますよね。 ③情報の散らばり 問い合わせ共有会の進め方に書いた通り、その場で得た情報の管理は議事録を付けているだけでした。○月X日問い合わせ共有会というタイトルの議事録群から「あの会話いつのページだ…!?」と探す必要がありました。大変。ちょうど先ほど目標を「ナレッジを溜める」にしたので、溜め方を変えてみました。 ニフティではnotionを利用しているので、DB機能を使って質問を溜めていくことにしました。DBに溜める部分はzapierで自動化しました。担当者が回答や調べた情報をページ内に簡単にまとめることでドキュメントとしてもイイ感じです。また、タグを適宜つけることで検索性を向上できないか実験中です。DB機能、便利ですね。 問い合わせ共有会やってみたい方へ 記事を参考に始めてみてもいいですし、しなくても良いのですが、もしよかったら「こんな感じでやってみたよ!」というのを発信してくれると嬉しいです。参考になります。 また、同じような悩みを抱えていて「やってみたいけど、うちのチームの文化的に厳しいな…そもそもチームじゃないんだよな…」と困っている方がいれば、私たちと一緒に働いてみませんか?お待ちしております。 私のチームの上司が絶賛カジュアル面談受付中なので(投稿日の時点では)こちらも是非チェックしてみてください。 https://meety.net/matches/cVJuDlRiIhZh We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
はじめに こんにちは。ニフティ入社新卒四年目の佐々木です。今回はAWSのリソースの一つである S3 についてコスト削減を行う方法を紹介します。 背景 ニフティではクラウドとしてAWSを活用しており、その中でサービスに対してクラウドリソースのコストを削減するといった活動も行っています。 そこで、今回は担当システムでAWSのコスト削減を行う機会があったので、何故削減するのか?どういう点で主に削減できそうか?削減する場合の注意点や考え方について紹介します。 この記事の内容 触れること S3のコスト削減方法 S3のコストを削減する上での注意点 実際に試したコスト削減例とTips 触れないこと S3そのものの説明 ストレージクラスなどの詳しい説明 S3を使用したコスト削減方法 課金形態 普段はニフティトップページの運用を担当しており、AWSにデプロイしたサービスを採用しています。 特にAWSの中でも、S3はほぼ制限なしで容量を必要な分だけ増やして使えるのでとても便利なサービスですが、使用した分だけコストがかかってしまうというデメリットもあります。 そこで、 S3の課金形態 について最初にご紹介したいと思います。2023年3月現在では主に以下のようになっています。 ストレージに対する課金 S3バケットにオブジェクトを保存するには料金がかかります オブジェクト内に保存されているデータサイズによって月額のコストが決まります リクエストとデータ取り出しに関する課金 S3バケットとオブジェクトに対して行われたリクエストに対しても料金がかかります リクエストの量に応じて課金されます リクエストタイプによって料金が異なります オブジェクトにデータを保存し取得するといった単純なフローを考える場合、基本的にはこれらの 2つの要素 がほとんどの課金要素になってくるかなと思います 削減方法 次に、主に既に使用しているS3に対して対処できそうな方法をご紹介します ストレージクラスの選択 上記でも触れたとおり、S3には様々なストレージクラスがあり、アクセス頻度に応じてコストを削減できます 例えば、サーバーのアクセスログを年単位で保存すると言った場合には、すぐにログを取りだす必要がないのであれば、低頻度のストレージクラスに移動させることでコストが節約できます ライフサイクルルールの設定 これはストレージクラスの話にも関わってきますが、アクセス頻度の低いバケットに対しては「一定期間たった後にアクセス頻度の低いストレージクラスに移動する」などといった柔軟性をもたせた対処ができます もし、ログの保存ルールが決まっている場合は、例えば最初の3ヶ月はすぐに取り出せるよう高頻度アクセス用のストレージに保管し、その後アーカイブとして1年間低頻度用のストレージに保存するといったこともできます リクエストコストの削減 S3にあるデータの取り出しにはコストがかかるので、それらを削減する方法も重要になります 例えば、S3にアクセスするためのリクエストの頻度を減らす、S3に保存するデータ量を見直すといった対処ができます 不要データの削除 単純に不要となっているバケットそのものを削除する方法です 不要なデータはそもそも保存させない、不要なバケットそのものを削除する、といった節約方法になります 実際にためしたこと 次に、S3のコスト削減を考えた際に実際に試したことや注意点などについて、Tipsを話していきたいと思います S3の課金項目の把握 何はともあれ、まずは現状のコストの把握から始めないといけません。実際にどの程度S3にコストが掛かっているのかを把握するため、Cost Explorerでサービスごとに料金を確認していきます。 例えば、S3のどの要素に課金がされているのかを把握することが重要です。S3バケットに対してタグを付与することで、Cost Explorerからのコスト把握がしやすくなります。 また、実際にタグを付与したりしたりすることで、「このバケットは何に使われていたのか?」といった目的の確認ができたりします。それらを活用し現状を把握することで、その後に削減する箇所のアイデアが浮んだり、後述するリソースの洗い出しにつながってくるといったメリットはあると思います。 S3バケットとオブジェクトの精査 次に、S3ストレージに保存されているオブジェクトサイズを把握するために精査を行いました。 ここでは、 S3 Storage Lens という機能を活用することで、S3の様々な情報をコーンソール上で確認することができます。以下はとあるバケットの例ですが、ストレージクラスごとのバケットサイズやオブジェクトの合計数などの詳細を把握できます。 また、閲覧出来る数に制限はありますが、使用量が上位のバケット一覧もこちらから確認できます。今回調査した範囲ではバケットが100個程度と数が多かったので、これを活用することでバケットサイズなどを容易に洗い出すことができました。 不要なバケットの削除 ここまでで、バケットのストレージサイズや使用用途について洗い出せたので、さらに不要なバケットの削除を行いました。 担当システムのチームで洗い出しを行った上でバケットの削除を行いましたが、今回の例ではそもそもデータ容量が多い不要なS3バケットがあまり存在しなかったので、コスト削減の効果は限定的でした。 ただ、不要なバケットを削除しリソースの整理ができたので、「このリソース何だっけ?」といった将来の管理面の負担を減らせたという点で、コスト面以外でもメリットがあったかと思います。 ライフサイクルルールの見直し検討 一方で、ストレージクラスごとの料金から現状のルールと変更後のルールを比較しコストの計算を行いました。 結局、今回はこちらも効果が限定的だったので変更は見送りましたが、もし保管しているデータ量の多いS3バケットが存在するのであれば、かなり手軽に削減出来る方法だと思いました。 まとめ 今回はS3のコスト削減について紹介しました。 全体を通した感想としては、アーキテクチャの把握からコスト削減までを一通りやることで知識も身につくので、担当プロジェクトでもし余裕があるのであれば一度そのような取り組みをやってみると良いなと思いました。それに加えて、AWSについて詳しくなれますし「この部分も実は改善できるのでは?」といったサービスに対する一歩上の視点で見れるようになったので学びになりました。 S3単体だけでなく、他のサービスと組み合わせることでさらにコスト削減を仕組みを導入する予定なので、また機会があればそちらも紹介したいと思います。 参考記事 https://aws.amazon.com/jp/s3/ https://aws.amazon.com/jp/s3/pricing/ https://aws.amazon.com/jp/blogs/news/s3-storage-lens/ We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
はじめに こんにちは! 「SvelteKit, Next.jsの導入事例紹介など 〜ニフティのフロントエンドの今とこれから〜」の司会進行を務めました新卒入社3年目の筑木(つづき)です。 先日2月21日にNIFTY Tech Talk #9として「SvelteKit, Next.jsの導入事例紹介など 〜ニフティのフロントエンドの今とこれから〜」を開催しました。 今回はその様子をレポートします! イベント概要 NIFTY Tech Talkは、ニフティ株式会社の社員が主催するトークイベントです。 本イベントでは、ニフティ社員が業務を通じて学んだことを発信しています。 第9回目となる今回は「フロントエンド」に関するテーマで開催しました。 ニフティで現在使用されているフロントエンド技術や行っている取り組み、Web制作のお話など多岐にわたる内容でお送りしました。 今回の登壇テーマは下記となります。 ニフティトップのNext.jsでのキャッシュ戦略を考えた話 テンプレートエンジン + jQueryからNext.jsに置き換える ニフティのLP(ランディングページ)ができるまで 新サービスにSvelteKitを導入してみた! 社内にWebアクセシビリティを取り入れていきたいなぁと思っている話 また、今回のTech Talkのアーカイブ動画をYouTubeにアップロードしております。ぜひご覧ください! 内容レポート 各セッションから抜粋して、どのような内容だったかを紹介します! ニフティトップのNext.jsでのキャッシュ戦略を考えた話 登壇者:会員システムグループ 佐々木 優 登壇資料はこちら まず1つ目のLTは、 @niftyトップページ のキャッシュ戦略を考えた話です。 @niftyトップページは2022年7月にシステム基盤の刷新を行っており、刷新のタイミングでNext.jsを導入しました。 刷新については、過去に開催された NIFTY Tech Talk #4 レガシーシステムからの脱却のレポート記事 を参照ください。 キャッシュの種類・内容・そしてどう分ける? キャッシュには CDNのキャッシュ と ブラウザキャッシュ の2種類があり・・・ その違いについて分かりやすく説明してくださいました。 キャッシュを行うにあたって、どのコンテンツをどうキャッシュする?と考えることに。 まず、キャッシュするコンテンツとしないコンテンツを分けました。 キャッシュするコンテンツは画像やCSSなどの更新頻度が低いコンテンツ・データ転送量が大きいコンテンツなどをあげられ、しないコンテンツとしてAPIを挙げられてました。 @niftyトップページでは、ログイン機能を用いた固有情報、つまりキャッシュする意味がないものがキャッシュされてしまう懸念があるため安全に舵を切ったとのこと。 確かに不明なコンテンツがキャッシュされていると意図しないコンテンツが出てしまったりする可能性がありますから、なるほどと思いました。 紆余曲折を経て無事リリース! ・・・と思いきや失敗談もあったとか。 画像ブラウザキャッシュが短く設定されてたため、本来不要な画像のリクエストが発生し結果コスト増加を起こしてしまったとのこと・・・。想定外はあるあるですね。 こちらはルールを追加することで対応完了! リクエスト数も減り、月1,000USD程度のコスト削減に繋がったとのことでした! およそ13万円・・・(2023年2月現在)。画期的ですね。 キャッシュを行う上でどのような考えを持って、どう取り組んでいけばいいか、どの点に注意すればよいかを1から学ぶことができたLTでした。 テンプレートエンジン + jQueryからNext.jsに置き換える 登壇者:会員システムグループ 宮本 達矢 登壇資料はこちら 続けて2つ目のLTはテンプレートエンジンとjQueryの構成をNext.jsに置き換える話です。 初めのLTと同じく @niftyトップページ の刷新において行われた取り組みとして置き換えが行われたようです。 以前の環境では、約7,000行の巨大なCSSや、ローカルに動作環境がなく開発環境にアップロードを行なって動作確認を行なったり、ページ仕様のドキュメントが不完全だったりと課題が多くありました。 刷新後は見事、モダンな環境になりました! アプリケーションの構成はNext.js + TypeScriptとなり、TypeDocを利用することで内容を充実させていきました。 となると気になるのは・・・ この構成にどうやって書き換えていったのか気になりますよね。 この構成にどう書き換えていったのか? どう手をつけていくか、から着目を行い機能ごとに分けて開発を行う方針を固めたとのこと。 @niftyトップページはニュースの枠やサービスの枠など様々あるため、分割したということですね。 書き換えていく方法については、Reactで1から作成することに。 これはjQueryのコードから部分的に移植をすると、変更漏れによるstate化した変数のsetStateを通さない更新や、最適化されていない処理によるパフォーマンス悪化の可能性が否めないからだそうです。 当然刷新したからハッピー!と思いきや、刷新したからならではの課題が出てきたとのこと。 具体的には、ブラウザ未対応の記法をしたためjsファイルが読み込まれずにエラーなどの問題等が起きていたなど・・・他にもあったみたいです。 ニフティのLP(ランディングページ)ができるまで 登壇者:事業開発グループ 新田 万智 登壇資料はこちら 3つ目のLTはランディングページができるまで、できてからの改善活動についてのお話です。 ニフティの制作チームはデザイン制作系、動画制作、撮影業務、アプリ制作など幅広い範囲を作成、関係者がとても幅広いチームです。 依頼が来てから公開までの流れを紹介してくださったり、公開から後の活動についても発表されました。 ニフティのWeb制作の特徴は、取り扱っているサービスが自社サービス!ということもあり、公開までが目標ではなく公開後にくる改善提案やそれに対する改善策を考えることが多いのが特徴です。 また、幅広い制作を行なっているため、動画やロゴ制作の経験を積むことができたり新規サービスリリースの経験を積むことができるのもまた1つの特徴となっています。 このLTでは、改善活動の一例も紹介してくださいました。 突然ですが、下の画像を見てどちらのLPの方が良いと思いましたか? 今回の場合は、 右側 のLPの方が結果が良くなりました。 PDCAで改善活動をされており、Plan → Doでは課題を見つけ、そこから仮説を立て提案を行う取り組みがされています。 課題を見つけるときはヒートマップやGoogleの分析ツールを利用し見つけています。 イメージで見るとすごくわかりやすいですね。 実際にこの改善を行ったところ、アプリのダウンロード率は改善前は9%だったのに対し、22%まで改善されました! Check → Actionでは、効果検証を進める中で色々な視点で見ることが大事でLPに誘導する前のバナーやアプリ画面に問題がないかなども見ています。 最後はディレクターとして、意識されていることを共有されました。 新サービスにSvelteKitを導入してみた! 登壇者:会員システムグループ たけろいど 登壇資料はこちら 4つ目のLTはv1.0.0がリリースされたSvelteKitを導入し、リリースを行なった話です。 Svelte愛が感じられるLTで、Svelteを導入する利点や導入に選ばれた理由などが語られました。 広告ブロックアプリ AD Cleaner の申し込みフォームのフロント部分がSvelteKitでできています。 スピード感のあるリリースができたのはSvelteKitのおかげとのことでした。 SvelteKitのポリシーとして 「高速、楽しい、柔軟」 があり、高速で動作し、書いていて楽しい!どんな環境でも柔軟に対応できる。 とても素晴らしいですね。 公式ドキュメントも充実しています。 書き方もVue Likeでとっつきやすいです。が、それだとVueで良くない?ともなりますよね。 Nust3もありますしSSRでは問題なさそう。Nust3はバージョンが1.0になりました。 ですが、Svelteは「コンパイラ」です。 ここが他とは異なり、JavaScriptにビルドされるという特徴があります。 Svelteは仮想DOMを使わないのでより速いし、学習コストが低い、コード記述量が少ないなど多岐にわたって強い点があり、SvelteKitが選ばれました。 プロダクトに採用されるメリット・デメリットも取り上げられました。 社内にWebアクセシビリティを取り入れていきたいなぁと思っている話 登壇者:会員システムグループ 関 歩武 登壇資料はこちら 5つ目のLTは、Webアクセシビリティを社内に取り入れていく取り組みの話です。 Webアクセシビリティとは、Webページにある情報や機能の利用しやすさのことであり様々な人々、様々なデバイスが利用しやすい状況を作っていきましょうという取り組みのことです。 関さんの担当されているシステムでは、改善できる点がいくつかあり社内で広めていく活動を始められました。 その活動として大きく2つに分けられます。 1つ目は社内ツールの作成です。 実際に良かった点としてJIS X 8341-3:2016の早見表を参考にされてチェックリストを作ったり、支援ツールを実際に使ってみるなどの取り組み内容が話されました。 2つ目に勉強会の開催を行われました。 実際の実装方法からアクセシビリティを学ぶ形式にし学びやすい体制を導入。こちらは 主催した社内勉強会の課題でアクセシビリティ的に優れているTODOリストの課題を出した話 というブログ記事にもなっていますのでぜひご確認ください。 こちらの勉強会では、オーサリングプラクティスを活用されました。 オーサリングプラクティスとは、アクセシブルに要素を実装する例がまとめられているドキュメントとなっており実装方法を学ぶ資料として最適だったようです。 また、ただ輪読するのではなく実装を体験する方が理解度が上がるため作ったものを後で見返すこともできとてもよかったと好評でした。 最後に今後やっていきたいこととして、向上施策の実施やその効果をまとめたり、関さんが担当されているシステムの不足点を取りまとめて改善していきたいと夢を語っていただきました! システムを全ての人に便利に使ってもらえるサービス、良いですね。 Webアクセシビリティを勉強する上で参考になる本も紹介されてましたので、気になる方はアーカイブ動画をチェックしてみてください。 まとめ 今回のTech Talkはフロントエンドの技術だけでなく、制作までの流れなど幅広い範囲を聞くことができて私自身勉強になりました。 短い1時間の枠だったため、話しきれなかった内容もありましたが参考にできるものがあれば幸いです。 ニフティでは、フロントエンド勉強会を開催しており日々フロントエンドの技術についてディスカッションを行なっています。 また機会があれば、Tech Talkもしくは別の形でできればいいなと思っています。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
はじめに ニフティでエンジニアをしている添野 翔太です。ここ最近、 @niftyトップページ システム基盤の刷新を進めています。 本稿では GitHubプロバイダー を利用してCI/CDパイプラインに関するリソースをTerraformで管理しようとした際にハマったポイント、そしてそれに対する解決方法を紹介します。 背景 担当するシステムではGitHubでコードを管理しているのですが、CI/CDパイプラインに関連するCodeファミリーへソースコードをミラーリングするにあたりWEBフックを仕掛けています。そしてこちらのコードはモジュール側に存在します。 resource "github_repository_webhook" "web" { repository = var.repository_name configuration { url = aws_codepipeline_webhook.webhook.url content_type = "json" insecure_ssl = true secret = aws_ssm_parameter.github_personal_access_token.value } events = ["push"] } resource "aws_codepipeline_webhook" "webhook" { name = replace("${var.application_name}_webhook_deploy", "-", "_") authentication = "GITHUB_HMAC" target_action = "Source" target_pipeline = aws_codepipeline.dummy_codepipeline.name authentication_configuration { secret_token = aws_ssm_parameter.github_personal_access_token.value } filter { json_path = "$.ref" match_equals = "refs/heads/{Branch}" } } ハマったポイント その他のコードの記載は割愛しますが、デプロイしたところ以下のような404エラーが出てくるようになりました。このままだとTerraform Applyを行うGitHub Actionsワークフロー上でもコケてしまう状態に…… % terraform apply POST https://api.github.com/repos//dummy-repo-nifkuji/hooks: 404 Not Found [] 質問サイト などを閲覧し調査を進めてみたのですが、解決に向けてなかなか進展しない状況でした。 ハマった原因 上記の404エラーを受けて、プロバイダー周りの設定がおかしくなっているのではないかという仮説を立てて、以下のコマンドを打ってみました。 % terraform providers Providers required by configuration: . ├── provider[registry.terraform.io/hashicorp/aws] ~> 4.59.0 ├── provider[registry.terraform.io/integrations/github] ~> 5.18.3 ├── module.ci_cd │ ├── provider[registry.terraform.io/hashicorp/aws] │ └── provider[registry.terraform.io/hashicorp/github] 上記の結果を見るとモジュール側と呼び出し側とでGitHubプロバイダーの設定が違うことに気付きました。この事が今回の404エラーを引き起こした原因です。 より具体的には、 公式ドキュメント によれば、sourceの指定がintegrations/githubに変わり、デフォルトだとhashicorp/githubの方が落ちてきている状態だったことです。 解決方法 そこで今回はモジュール側にもrequired_providersを用いた設定を施したファイルを配置しました。 terraform { required_version = ">= 1.4.2" required_providers { aws = { source = "hashicorp/aws" version = "~> 4.59.0" } github = { source = "integrations/github" version = "~> 5.18.3" } } } そうしたらプロバイダーの設定が揃いました。 % terraform providers Providers required by configuration: . ├── provider[registry.terraform.io/hashicorp/aws] ~> 4.59.0 ├── provider[registry.terraform.io/integrations/github] ~> 5.18.3 ├── module.ci_cd │ ├── provider[registry.terraform.io/hashicorp/aws] ~> 4.59.0 │ └── provider[registry.terraform.io/integrations/github] ~> 5.18.3 そうして404エラーは無事に解決されました。ついでにterraform init時のWarningメッセージも消えました。思い返すとこのWarningメッセージで原因と解決策を思い付けたかもしれないなと思いました。 │ Warning: Additional provider information from registry │ │ The remote registry returned warnings for │ registry.terraform.io/hashicorp/github: │ - For users on Terraform 0.13 or greater, this provider has moved to │ integrations/github. Please update your source in required_providers.<code></code> まとめ 今回はGitHubプロバイダーを利用してCI/CDパイプラインに関するリソースをTerraformで管理しようとした際にハマったポイント、そしてそれに対する解決方法を紹介しました。 何かの参考になったら幸いです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
会員システムグループ 駆け出しSREの川端です。 今回は「Terraformで環境変数を使って変数値を与える」ということをやってみます。 GitHub ActionsなどのCI/CDで活用できます。 環境 $ terraform -v Terraform v1.3.0 on linux_amd64 + provider registry.terraform.io/hashicorp/aws v4.12.1 + provider registry.terraform.io/hashicorp/local v2.4.0 + provider registry.terraform.io/hashicorp/tls v4.0.4 実現したいこと AWS RDSのクラスターを環境変数から与えたスナップショットARNで起動する resource "aws_rds_cluster" "mysql" { # # 省略 # snapshot_identifier = 環境変数から与えたARN } 公式ドキュメントを読んでみる As a fallback for the other ways of defining variables, Terraform searches the environment of its own process for environment variables named TF_VAR_ followed by the name of a declared variable. https://developer.hashicorp.com/terraform/language/v1.3.x/values/variables#environment-variables TF_VAR_db_snapshot_arn を環境変数で与えればterraform内では db_snapshot_arn で読み取れるようだ やってみる 環境変数設定する。 export TF_VAR_db_snapshot_arn=arn:aws:rds:ap-northeast-1:xxxxxxxxxx .tfファイルを編集する。 resource "aws_rds_cluster" "mysql" { # # 省略 # snapshot_identifier = db_snapshot_arn } planを実行する。 terraform plan エラーが出ました。 │ Error: Invalid reference │ │ on aurora.tf line 63, in resource "aws_rds_cluster" "mysql": │ 63: snapshot_identifier = db_snapshot_arn │ │ A reference to a resource type must be followed by at least one attribute access, specifying the resource name. どうやらvariableの定義が必要らしい。。。 .tfファイルに追加する。 variable "db_snapshot_arn" { type = string } .tfファイルを修正する。 resource "aws_rds_cluster" "mysql" { # # 省略 # snapshot_identifier = var.db_snapshot_arn } 再度plan実行。これでplanが通りました。 もう一度公式ドキュメントを見てみる 公式ドキュメントを読み直すと Environment Variables 項目は Assigning Values to Root Module Variables 配下にありました。 Variable に値を与えるために環境変数が使えるのであって単体で使用はできません。 学び TF_VAR_example と環境変数で設定することでTerraformの変数 example に値を与えることができる ドキュメントは一部だけじゃなくてその前後も読もう We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
こんにちは!会員システムグループの渡邊です。普段はニフティトップページの運用を担当しています。 今回はGoogle Apps Script(GAS)を使い、コストをかけずにサイト表示速度の見える化を行う方法を紹介します。 なぜ見える化を行おうと思ったか Googleが2020年にWebサイトのパフォーマンスを評価するための指標であるCore Web Vitals(CWV)を導入しました。 この指標には、Webサイトのパフォーマンス改善に非常に役立つ内容が含まれています。 CWVの指標はUX改善に直結するため、担当サービスではCWVを軸に改善活動を行っています。 しかし、改善活動を行っていく中でリリースによる影響やGoogleのアルゴリズム変更によってスコアが変動することが増えてきたので、継続的な見える化を行う必要が出てきました。 表示速度見える化の検討 初めはLightHouse CIを使って見える化を検討していましたが、いくつかの懸念点があり断念しました。 LightHouse CIは実行するサーバー環境によってスコアが左右されてしまうため、安定した計測を行うには高いサーバースペックが求められるため、コストがかかってしまう 推奨スペック またLightHouse CIはサーバーなどに置いて管理することが必要になるので運用コストが増える 以上のことから最終的には以下のツールを使って作成することにしました。 PageSpeedInsights API Google スプレッドシート Google Apps Script(GAS) 今回利用したGCPが提供しているPageSpeed Insights APIは、リクエストに制限はありますがコストはかからずに利用できます。現在、1時間おきに実行していますが、特に問題は起きていません。 PageSpeed Insights APIのコスト APIキーを使わなくてもPageSpeed Insights APIは実行できますが、すぐに上限に引っかかってしまうため、今回はAPIキーを発行して計測を行っています。 構成とデータ取得スクリプト 構成図 データ取得(GAS) まずAPIキーを取得します。 PageSpeed Insights API を使ってみる にアクセスし、「キーを取得する」ボタンを押すとモーダルが開くのでGCPのプロジェクトを選択します。 次にAPIキーが発行されたらGASのスクリプトプロパティにAPIキーを設定します。 GASのスクリプトは以下のようになっていて、処理を簡単に説明するとPageSpeed Insights APIのレスポンスからCWVの指標を一つ一つ変数に格納し、指定したシートの末尾に追記していきます。 function myFunction() { // 対象のスプレッドシートを取得 const ss = SpreadsheetApp.getActiveSpreadsheet(); // 書き込むシートを指定 const sheet = ss.getSheetByName("結果"); writeResult(sheet, getResult()); } function getResult() { // APIキーを取得 const key = PropertiesService.getScriptProperties().getProperty('PSI_API_KEY'); // URLを指定 const url = "https://www.example.com/" // PageSpeed Insights APIを実行 const result = UrlFetchApp.fetch( 'https://www.googleapis.com/pagespeedonline/v5/runPagespeed' + `?url=${url}` + "&locale=ja" + "&strategy=desktop" + `&key=${key}` ); return JSON.parse(result); } function writeResult(sheet, arr) { // 実行日時取得 const date = new Date(); const ExecDate = date.getFullYear() + '/' + (date.getMonth() + 1) + '/' + date.getDate() + ' ' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds(); // パフォーマンススコア取得 const performance = arr["lighthouseResult"]["categories"]["performance"]; // First Cotentful Paint取得 const fcp = arr["lighthouseResult"]["audits"]["first-contentful-paint"]; // Time to Interactive取得 const tti = arr["lighthouseResult"]["audits"]["interactive"]; // Speed Index取得 const si = arr["lighthouseResult"]["audits"]["speed-index"]; // Total Blocking Time取得 const tbt = arr["lighthouseResult"]["audits"]["total-blocking-time"]; // Largest Contentful Paint取得 const lcp = arr["lighthouseResult"]["audits"]["largest-contentful-paint"]; // Cumulative Layout Shift取得 const cls = arr["lighthouseResult"]["audits"]["cumulative-layout-shift"]; // シートに追加 sheet.appendRow([ ExecDate, performance["score"] * 100 + "%", parseFloat(fcp["displayValue"]), parseFloat(tti["displayValue"]), parseFloat(si["displayValue"]), parseFloat(tbt["displayValue"]), parseFloat(lcp["displayValue"]), cls["displayValue"] ]); } 参考: PageSpeed Insights API を使ってみる また、1時間おきに実行するためにトリガーを以下のように設定しています。 結果 スプレッドシートへの出力結果 出力結果をもとにグラフ化 過去のリリースやアルゴリズム変更の影響を確認したかったので、期間を自由に変更できるタイムライングラフを使っています。 終わりに 今回はコストをかけずにサイト表示速度の見える化を行いました。 グラフ化や平均値などは手動で作らなければいけませんでしたが、一度作ってしまえばAPIがダウンしない限り永久的に結果を更新し続けてくれるので非常に便利になりました。 担当プロダクトではGitHubリリースノートの自動生成も行っているので、今回作成したものと突き合わせることでどのリリースが原因かの特定が容易になりました。 将来的には週の始まりにグラフを画像化したものをSlack通知する仕組みを導入する予定です。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
はじめに はじめまして!基幹システムグループの田澤です。普段はNifMoの運用を担当しています。 みなさんはS3を利用したアプリケーションを作成する際に開発環境をどのように構築していますか? endpointにawsのs3を指定するのは楽ですが少額とはいえお金がかかるので、ローカルのほうが検証しやすいですよね。 今回の記事では、ローカルS3の開発環境のサンプルを作ってみました! サンプルでできること Pythonのコンテナからminio(S3)に対してAWS SDKでアクセスし、以下の事ができます バケット作成と削除 ファイル作成と削除と内容取得 環境 Microsoft Windows [Version 10.0.19044.2604] Docker version 20.10.11, build dea9396 docker-compose version 1.29.2, build 5becea4c ファイル構成 │─docker-compose.yml │─python.Dockerfile └─sample └─Pipfile └─create_bucket.py └─create_file.py └─read_file.py └─delete_file.py └─delete_bucket.py ファイル内容 docker-compose.yml version: "3.7" services: python: image: sample/python container_name: python build: context: ./ dockerfile: python.Dockerfile stdin_open: true volumes: - ./sample:/sample networks: default: ipv4_address: 172.21.1.2 minio: container_name: minio image: minio/minio:latest volumes: - ./minio:/export ports: - "9090:9000" - "9091:9001" environment: - MINIO_ROOT_USER=miniominio - MINIO_ROOT_PASSWORD=miniominio networks: default: ipv4_address: 172.21.1.3 command: ['server', '/export', '--console-address', ':9001'] createbuckets: image: minio/mc depends_on: - minio entrypoint: > /bin/sh -c " until (/usr/bin/mc config host add minio http://minio:9000 miniominio miniominio) do echo '...waiting...' && sleep 1; done; /usr/bin/mc mb minio/default-bucket; /usr/bin/mc policy download minio/default-bucket; exit 0; " networks: default: ipam: driver: default config: - subnet: "172.21.1.0/24" 各サービスの説明: Python 使用しているコンテナイメージ: https://hub.docker.com/_/python minio 使用しているコンテナイメージ: https://hub.docker.com/r/minio/minio/ ports minioのデフォルトポートは9000と9001です。僕の環境だと9000番ポートは競合するため、9090と9091を割り当てています。 environment minioにアクセスする際のキーを環境変数として指定しています createbuckets 使用しているコンテナイメージ: https://hub.docker.com/r/minio/mc/ entrypoint until ~~ の部分では、minioに接続できるまで待機しています。ここでは、minioにアクセスする際のキーを利用し、接続しています。 接続できしだい、default-bucketの作成を行っています。 python.Dockerfile FROM python:3.11-slim # 日本時間対応 ENV TZ=Asia/Tokyo # 作業ディレクトリ ENV WORKDIR /sample # ディレクトリ作成 RUN mkdir ${WORKDIR} WORKDIR ${WORKDIR} COPY . ${WORKDIR} # Python依存ライブラリをインストール RUN pip install --upgrade pip && \ pip install pipenv Pipfile [[source]] url = "https://pypi.python.org/simple" verify_ssl = true name = "pypi" [packages] boto3 = "==1.26.92" [dev-packages] create_bucket.py import boto3 # minioをendpointにする s3_resource = boto3.resource( 's3', endpoint_url='http://minio:9000', aws_access_key_id='miniominio', aws_secret_access_key='miniominio' ) # bucket名 bucket_name = "test-bucket" # bucketを作成 s3_resource.create_bucket(Bucket=bucket_name) boto3.resourceでは、minioの環境変数で決めたMINIO_ROOT_USER、MINIO_ROOT_PASSWORDを指定しています。 create_file.py import boto3 # minioをendpointにする s3_resource = boto3.resource( 's3', endpoint_url='http://minio:9000', aws_access_key_id='miniominio', aws_secret_access_key='miniominio' ) # bucket名 bucket_name = "test-bucket" # file名 file_name = "test-file" # bucketにファイル作成 s3_resource.Object(bucket_name, file_name).put(Body="hogehoge") read_file.py import boto3 # minioをendpointにする s3_resource = boto3.resource( 's3', endpoint_url='http://minio:9000', aws_access_key_id='miniominio', aws_secret_access_key='miniominio' ) # bucket名 bucket_name = "test-bucket" # file名 file_name = "test-file" # ファイルの内容を読み込む file_data = s3_resource.Object(bucket_name, file_name).get()[ 'Body'].read().decode('utf-8') print("#test-fileのファイル内容の出力") print(file_data) delete_file.py import boto3 # minioをendpointにする s3_resource = boto3.resource( 's3', endpoint_url='http://minio:9000', aws_access_key_id='miniominio', aws_secret_access_key='miniominio' ) # bucket名 bucket_name = "test-bucket" # file名 file_name = "test-file" # test-fileを削除 s3_resource.Object(bucket_name, file_name).delete() delete_bucket.py import boto3 # minioをendpointにする s3_resource = boto3.resource( 's3', endpoint_url='http://minio:9000', aws_access_key_id='miniominio', aws_secret_access_key='miniominio' ) # bucket名 bucket_name = "test-bucket" # bucketを削除 s3_resource.Bucket(bucket_name).delete() 動作確認 docker-compose.ymlがあるディレクトリで以下コマンドを打ちます $ docker-compose build $ docker-compose up -d コンテナが起動したら以下を確認します。 http://127.0.0.1:9091/ にアクセス docker-compose.yml内で指定しているMINIO_ROOT_USER、MINIO_ROOT_PASSWORDでログイン #docker-compose.yml より抜粋 environment: - MINIO_ROOT_USER=miniominio - MINIO_ROOT_PASSWORD=miniominio ログインすると以下のような画面が表示されるはずです。 その際にdefault-bucketが作成されていることを確認しましょう。 これはdocker-compose.ymlのcreatebucketsで作成されたバケットになります。 画面確認ができたので、次はpythonコンテナに入り、サンプルソースを実行していきます。 pythonコンテナに入りpipenv shellをする $ docker exec -it python bash root@0669eae81131:/sample# pipenv install root@0669eae81131:/sample# pipenv shell create_bucket.pyを実行しminioのweb画面からtest-bucketが作成されていることを確認する (sample) root@0669eae81131:/sample# python create_bucket.py http://127.0.0.1:9091/buckets にアクセスし、以下のようにtest-bucketが作成されていることを確認する create_file.pyを実行しminioのweb画面でtest-fileが作成されていることを確認する (sample) root@0669eae81131:/sample# python create_file.py http://127.0.0.1:9091/buckets/test-bucket/browse にアクセスし、以下のようにtest-fileが作成されていることを確認する read_file.pyを実行しtest-fileの中身を読み込めることを確認する (sample) root@0669eae81131:/sample# python read_file.py #test-fileのファイル内容の出力 hogehoge delete_file.pyを実行し、minioのweb画面でtest-fileが削除されていることを確認する (sample) root@0669eae81131:/sample# python delete_file.py http://127.0.0.1:9091/buckets/test-bucket/browse にアクセスし、以下のようにtest-fileが削除されていることを確認する delete_bucket.pyを実行し、minioのweb画面でtest-bucketが削除されていることを確認する (sample) root@0669eae81131:/sample# python delete_bucket.py http://127.0.0.1:9091/buckets にアクセスし以下のようにtest-bucketが削除されていることを確認する 長くなりましたが、以上でサンプルの実行ができました。 おわりに 今回はMinIOを利用したローカル開発環境のサンプルを作成しました。 ブログ投稿は初めてなのでお手柔らかにお願いします! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
ニフティ株式会社新卒2年目のRyommです。普段はマイ ニフティというスマートフォン向けアプリの開発・運用を行なっています。 ニフティには書籍購入補助制度があり、その管理にbookbotというツールを使っています。 今まで書籍購入補助制度で購入された本とその感想を、bookbotがデータベースに貯め込んでおり、昨年末にNotion連携機能を実装したことで誰でも簡単に閲覧できるようになりました。 そこで今回は、書籍購入補助が始まった2019年から蓄積したデータの分析結果を大公開しちゃいます! 社内では以下のような紙面にまとめて発行しました。 としょだより1 としょだより2 振り返りSP 今までで読まれた本はこれだ!ランキング リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム テスト駆動開発 Clean Architecture 達人に学ぶソフトウェアの構造と設計 SCRUM BOOT CAMP THE BOOK Kaggleで勝つデータ分析の技術 Webを支える技術-HTTP、URI、HTML、そしてREST(WEB + DB PRESS plus) レガシーコードからの脱却 ―ソフトウェアの寿命を延ばし価値を高める9つのプラクティス マスタリングTCP/IP―入門編 エンジニアの定番図書が上位を独占していました。 全体としてはプログラミングや機械学習、アジャイル開発に関係する本がよく読まれているようです。 「Kaggleで勝つデータ分析の技術」はNaggle(社内版Kaggle)が開催された時に一世を風靡していたのを思い出します。 ニフティの読書王は誰だ!? 今まで誰が一番書籍購入補助制度で本を購入したのか調べてみました。その結果ニフティの読書王に輝いたのは、会員システムグループシニアエンジニアのDさんでした! 今回は読書王Dさんへの独占インタビューをお届けします。 Q. 今まで読んだ本の中で、人に薦めるなら一番は? A. 「Engineers in VOYAGE ― 事業をエンジニアリングする技術者たち」 レガシーシステムの刷新には近道はない。みな愚直にやっているのだと勇気をもらいました。 Q. 書籍購入補助の使い時は? A. ちょっと視野を広げたい時に制度を使って本を買ってました。元々強い興味を持っている分野以外をあえて選んだりしています。 Q. 読書王に輝いたことを受けて、感想と今後の意気込みを教えてください! A. 一線で戦えるシニアエンジニアであり続けるためにも書籍購入制度を活用して学び続けていきたいと思います。みなさんももっともっと活用しましょう! グループ別☆人気本ランキング カスタマーサポートG データ利活用の教科書 データと20年向き合ってきたマクロミルならではの成功法則 事業推進G Kaggleで勝つデータ分析の技術 事業開発G 伝え方が9割 営業G データ利活用の教科書 データと20年向き合ってきたマクロミルならではの成功法則 人事総務G 人事と採用のセオリー 成長企業に共通する組織運営の原理と原則 インフラシステムG Kaggleで勝つデータ分析の技術 / テスト駆動開発 会員システムG Clean Architecture 達人に学ぶソフトウェアの構造と設計 / テスト駆動開発 基幹システムG SCRUM BOOT CAMP THE BOOK 2022年度下期特集 2022年度下期で人気だった本を調べてみた! 2022年度下期で一番読まれた本は「 SCRUM BOOT CAMP THE BOOK 」でした! 他にもSEOやマネジメント、資格試験対策に関係する本がよく読まれていました。メタバースに関する本も読まれていました。未来的でワクワクしますね! WHO IS A GREAT READER?? 2022年下期は事業開発GのSさん、会員システムGのIさん、事業開発GのWさんの3名がトップ・オブ・読書家でした!お三方が読まれていた本をいくつかご紹介します Sさん(事業開発G) なるほどデザイン セールスコピー大全 グロースハック Iさん(会員システムG) 達人プログラマー ―熟達に向けたあなたの旅― 第2版 SCRUM BOOT CAMP THE BOOK Go言語でつくるインタプリタ Wさん(事業開発G) ゼロから学ぶ はじめてのWordPress これからのWordPress SEO 内部対策本格講座 WordPress 仕事の現場でサッと使える! デザイン教科書 流行を振り返り! bookbotが稼働し始めてからの各期で最も人気な本の推移を調べてみました! 近年ではSREやスクラムといったN1!の活動も影響していそうです。リーダブルコードやレガシーコードからの脱却、クリーンアーキテクチャなど、技術的負債に対抗しようとする本が人気です! リーダブルコードは毎年読まれていて、不動の人気を誇っています。まだ読んだことのないひとは、一度読んでみてもいいかもしれないですね! 2019下期 リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック 2020上期 リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック 2020下期 たった1日で基本が身に付く! Docker/Kubernetes超入門 2021上期 Clean Architecture 達人に学ぶソフトウェアの構造と設計 2021下期 レガシーコードからの脱却 ―ソフトウェアの寿命を延ばし価値を高める9つのプラクティス 2022上期 SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム 2022下期 SCRUM BOOT CAMP THE BOOK THE BEST PASSIONATE IMPRESSIONS chatGPT に感想の熱量を測ってもらいました。その中から、とってもアツい感想をいくつか紹介します! 「プロになるためのWeb技術入門」 ――なぜ、あなたはWebシステムを開発できないのか 本書を読み、これまで断片的であったWeb技術の知識が、体系的かつ俯瞰的な理解となり、情報に広がりをもって納得のいく形で自分の中に定着していく感覚を実感することができた。それは単に技術の説明があることのみならず、それが必要となった歴史的背景や哲学が紐づく形となっているからであると感じた。技術書にしては著者の語り口が軽快で、物語調に書かれているため読みやすく、どこも躓くことなくスラスラと読み進めることができた。具体的に手を動かさないと理解が深まらないような箇所もなかったため場所を選ばず、外出先・通勤中にも読むことができた。本書で読んだことは早速実務で活かされつつある。現在個人目標で開発中の案件について、APIを開発・利用しているが、GET・POSTどちらのメソッドで情報を取得すべきか、本書を読む前は判断に迷うべきところ、両者のメリットデメリット・使い分けを学んだため、適切な選択ができていると感じる。タイトルに”プロになるための”とあるが、正に技術をしっかりと理解したうえでのプロフェッショナルな選択を行えていると実感している。本書の初版は2010年であるため技術界隈ではだいぶ古い本になると思われるが、内容は時代に変動されないWeb技術の幹となるものなので、決して読んで損はしない。Web技術の移り変わりは早いとよく言うが、そのほとんどは、この幹から派生した枝葉のようなものにすぎない。Web系の技術分野を理解するためにまずは本書を読んで、幹の部分をしっかりと強くすることがなによりも先決であると感じた。 本書は今後のエンジニア人生の個人的バイブルとなるであろう。繰り返し読んで、プロフェッショナルに磨きをかけたい。 「読みやすく、理解しやすく、実務でも役立つ内容が詰まっている。Web技術の幹となる重要な情報が盛り込まれており、エンジニアにとって必読の書である。」 インクルーシブHTML+CSS & JavaScript: 多様なユーザーニーズに応えるフロントエンドデザインパターン アクセシビリティについての本3冊目。読む前は実装例が載っているだけの本ではないかと訝しんでいた。しかし、実際はUIの作成方法について考え方などから説明する体系的な良書だった。文中では例を述べるだけではなく、ユーザから見てどうなのかをしっかりと説明している。また、この実装を行えばOKで終了せず、本の中の作り方はあくまで筆者の考えやこれまでの議論の結果であり、今後の社会の変化や、考え方の変化によって変わることをしっかりと説明している点もよかった。ユーザ視点のUIについて考える流れを学ぶ本として良いと思った 「UI作成方法について体系的・ユーザ視点での説明が充実。今後の変化にも対応可能な考え方を提供。実装例だけでなく考え方のレクチャーもあり、UIをよりよく考えるための良書。」 達人プログラマー(第2版): 熟達に向けたあなたの旅 初版を読んだことがないのですが、第2版を購入しました。 実際に読んでみるとDRY、KISS的なコーディング技法だけではなく、開発の進めかた、優秀なエンジニアとしてのものの見方など、実践的な内容が記載されており大変勉強になりました。 「実践的な内容が記されており、開発の進めかたやものの見方にも触れているため、広くエンジニアリングのレベルを向上させるための必読書として、高い評価を与えます。」 サイトリライアビリティワークブック ―SREの実践方法 Googleによる前作「SRE サイトリライアビリティエンジニアリング」と対になる書籍です。本書を最大限に活用するには、「SRE サイトリライアビリティエンジニアリング」を読んでおくこと、あるいは参照できるようにしておくことをおすすめします。 前作ではSREに関して原理と哲学の紹介、それら原理の適用方法に焦点を当てたものでしたが、本書ではSREを組織やプロジェクトに実際に導入するにあたり必要となる具体的方法を、プラクティスだけではなく多くの企業の事例から丁寧に解説されています。 SREとしてだけではなく、信頼性の高いサービスを提供する上で必要となるサービス指標や運用方法が含まれているので、SRE導入まではまだ…という方でも是非、前作と合わせて手元に置いておいて欲しい本だと感じました。 「本書は、SREを実際に企業に導入するための具体的な方法を多くの事例から解説しており、SREだけでなく信頼性の高いサービスを提供する上で必要となる情報も含まれている。」 AWS認定ソリューションアーキテクト-プロフェッショナル ~試験特性から導き出した演習問題と詳細解説 まだ読了していないため、途中までの感想となります。 AWS認定参考書としてはネガティブな意見がないほど評価が良かったので購入してみました。 SAAの基本知識が前提となりますが、本書で試験に出題される各サービスの説明が記載されているので、 この本でSAPの勉強をする、大は小を兼ねるのではないかと思います。 SAPで書籍を購入するとしたらこの本かなと思います。 「AWS SAAに関する試験に必要な知識を網羅しており、各サービスの説明が充実しているため、AWS認定参考書として抜群の内容だと感じました。」 AWSコンテナ設計・構築[本格]入門 well-architectedに基づいたECS/Fargateでのアプリ構築方法が解説されている。 GitHubからCFnやアプリのソースを落としてきてハンズオンで進めることができる。 AWSでよく分からなくなりがちなIAMロールやポリシーについても丁寧に書かれているため、良い。 Code兄弟を使ったCI/CDの組み方や、fluent bitのサイドカーコンテナによるログ収集、dockerイメージのセキュリティチェックなど、実践的な内容も多いため、担当システムのAWS移行前に読んでおきたかった。 あくまでも現時点での良いやり方の紹介であるため、この本の内容が古くなる前に読んでおくのがオススメ。 「AWSでのアプリ構築に関するwell-architectedフレームワークや、CI/CD、ログ収集、セキュリティチェックなど、実践的な内容が豊富で丁寧に解説されているため。ただし、技術が常に進化しているため、情報の更新に注意が必要。」 scikit-learnとTensorFlowによる実践機械学習 scikit-learnやTensorFlowで実現できる様々な機械学習、深層学習実装方法がコード付きで記されている。 理論的な解説も載っているので、基本的な機械学習のアルゴリズムから具体的な実装方法まで網羅的に学べる。 コードはGitHubで公開されているので、写経もしやすい。 データサイエンスや機械学習に興味はあるが、体系的に学んだ経験がない人におすすめ。 「機械学習の基礎から実践的な知識まで網羅的に学ぶことができ、GitHubで公開されているコードを使って写経もしやすい。機械学習初学者におすすめの一冊。」 暗号技術入門 第3版 秘密の国のアリス SSL/TLSについての理解を深めるため、暗号技術を基礎レベルから学ぶために購入。 暗号がどういうものか、どのような暗号技術があり、どう応用されているのかといった用途や仕組みを大きく「暗号」「認証」「鍵・乱数・応用技術」に分割し体系的に学ぶことができます。暗号通貨やブロックチェーンといった最新技術も簡単ですが含まれているのもよかったです。 図が多く用意されており理解しやすいことや、これまでの暗号技術とその弱点などの歴史も分かりやすく書かれており入門書としてとても読みやすい一冊です。 「暗号技術の基礎から応用まで、分かりやすく体系的に説明されており、図も多用されているため非常に理解が容易である。また、暗号技術の歴史や最新の技術まで網羅されているため、入門書としては非常に優れた一冊だと思われる。」 研修デザインハンドブック 誰かに何かを教えるためには何が必要か? 講師個人の、人柄や話術、デリバリースキルに依存してしまうのか。ただ、講師個人の資質に依存するものではサスティナビリティがない。 個人の資質に依存しなくても効果的な研修を行う方法があるのか。 「人に教える」「人を育てる」のは大変なことだが、その中の「研修」にスコープをあてた内容を確認できる。 単に「情報を伝える」研修・講義ではなく、学びから実践までのプロセスに関与する、「参加者主体」の研修手法、「研修をデザインする」手法について書かれている。 この本により、人間の心理を重視した法則(人は自分が口にしたことは受け入れやすい、習得はいかに楽しく学ぶかに比例する)や、研修のデザインに有効なルール(「90/20/8」の時間配分、「CSR – コンテンツ・参画・リビジット」、リビジット6回)を知ることができた。 個々人のデリバリーに頼ることなく、効果的なデザインができるようにしていきたい。 「研修の効果的なデザインについて、具体的な手法が記載されており、個人の資質に依存しないサステイナビリティがある。また、心理学の法則や時間配分、リビジット回数など実践的な内容が多数収録されているため。」 Kubernetes完全ガイド 第2版 完全ガイドと謳っているだけあってとてつもないボリュームです。 Kubernetesのアーキテクチャ、リソースの種類、運用監視などのサービス設計に至るまで幅広く網羅しています。加えて、DockerやマイクロサービスアーキテクチャなどのKubernetesを使う上で必要となることについても説明しています。 初心者でもわかるように図を多く用いて説明してくれているので非常にわかりやすかったです。さらに、本書で扱っているコードはGitHub上にチャプターごとにサンプルコードとして公開しているので、実際に構築しながら理解することができます。 なにか困ったことがあったら辞書的な利用ができる本だと思います。 「幅広い内容に加え、初心者でもわかりやすい図解が充実し、GitHub上にあるサンプルコードも使えるため、学習に最適な一冊です。」 リーダブルコード ――より良いコードを書くためのシンプルで実践的なテクニック プログラムを書く際の読みやすさに焦点をあてて書かれた本です。 本書はまず読みにくい例をあげ、なぜわかりにくいのか、どうしたらよくなるのかについて書かれているため、納得しながら読み進めることができました。またコード量を短くまとめることが必ずしも読みやすさにつながるとは限らないことを指摘しており、つい文量や行数を少なくすることを良いことだと思いがちだが、あとから見返してわかりやすいかを意識することが大切だと感じました。チームでモブプログラミングをする際など皆でコードを考える時の根本的な指針にもなると思いました。 「良いコードを書くための指針が分かりやすく、実践的なアドバイスが多数ある。読みやすさに焦点をあてたテーマが深く掘り下げられており、コード量という別の視点から考えることができるようになった。」 きれいなPythonプログラミング ~クリーンなコードを書くための最適な方法 Pythonならではの書き方をたくさんの例で紹介しているので非常に読みやすいです。復習になるような箇所もあったが、全体的に中級レベルで、自分が求めていたレベルと合致していたので良かったです。なぜこう書いた方が良いのかをしっかりと説明しているので、そうだよなと納得しながら読み進められた所が多かったです。内容も入門書ではスルーされる部分までしっかり書かれているなと感じました。 「非常に読みやすく、中級レベルの内容は自分に合致しており、説明が詳細でわかりやすかった。入門書ではスルーされる部分までしっかり書かれていた。」 マスタリングTCP/IP―入門編―(第6版) ネットワーク関連の教科書としては著名な一冊かと思います。 ページ数が多いため、まずは一周して全容を把握した後辞書のような使い方を想定しています。 タイトルの通りTCP/IPの基本を体系的に学ぶことができます。ネットワークの歴史、OSI参照モデルとそれぞれの層の代表的なプロトコルについてなど、図表などを絡めて解説してくれるためとてもとっつきやすいです。 購入した6版は2019年12月に発売されましたがIpv6や5G、Wifi6など最近のネットワーク技術についても記述されているためその点でもおすすめです。 電子書籍で購入しましたが、辞書として利用する上で目次機能は便利そうです。紙でパラパラと調べるのも乙かとは思いますので慣れと好みで選択するのがいいと思います。 「TCP/IPの基礎から最新のネットワーク技術まで網羅し、図表を用いたわかりやすい解説で初学者にもオススメできる一冊。また、目次機能が便利な電子書籍版もあるので使いやすさも高い。」 おわりに イラストやchatGPTによる感想評価や傾向分析、データ整形などは、それぞれ得意としている同僚に頼んでやってもらい、なんとか発行まで漕ぎ着くことができました。 書籍購入補助は良い制度なので、みんなが活用することで制度が続いて欲しいなと思っています。 気になる本が見つかる助けになれていれば幸いです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
基幹システムグループ N1! オートメーションスペシャリストの南川です。業務内で自動化・効率化できそうなところは自動化・効率化する癖があります。 今回は、普段、業務内で実施している手軽にできる効率化や自動化の小ネタを3つほど紹介します。 こちらの記事は、ニフティ社内で行われたLT大会にて発表した内容を再構成したものとなります。 NIFTY Tech Talk にて再演し、その時の 録画 や スライド も公開しているので、興味のある方は確認してみてください! タスクスケジューラ タスクスケジューラは、決まった日時にアプリを定期実行するWindows標準のアプリケーションです。 私が所属しているチームでは、ハイブリッドワークということもあり、チームミーティングをGoogle Meet上で行うのが主流となっています。そのようなときに、「毎朝9:30にChromeで朝会が行われるMeetのURLを開く」みたいなことができるようになります。 その他に、SlackのAPIを叩いてSlackのステータスを変更するPythonのスクリプトや、ごみ箱の中身を空にするバッチファイルなどを定期実行しています。 設定方法 今回は、例として「毎朝9:30にChromeで朝会が行われるMeetのURLを開く」の設定方法について説明します。 まず、スタートメニューから「Windows 管理ツール」 > 「タスク スケジューラ」を選択し、タスクスケジューラを開きます。 次に、メニューバーから「操作(A)」 > 「基本タスクの作成(B)」を選択し、基本タスクの作成ウィザードを開きます。 基本タスクの作成ウィザードでは、作成するタスクの項目を順番に設定することができます。 まず、タスクの名前と説明を入力します。説明は省略しても大丈夫です。 次にこのタスクを実行するタイミング(トリガー)を設定します。 チームの朝会は毎日9:30に実施されるので、時間に遅れないように1分前にしています。 そして、トリガーが発火した際に実行する操作を設定します。 まず、Chromeを実行したいので「プログラムの開始(T)」を選択します。 次に、実行したいプログラムとその引数を指定します。 今回、プログラム/スクリプトにはChromeの絶対パス、引数の追加 (オプション)にはChromeで開くURLを指定しています。 各項目を確認して「完了(F)」を押したら、タスクが作成され、毎朝9:29にChrome上で朝会のMeetが開くようになります。 作成したタスクはタスクスケジューラライブラリから確認でき、プロパティから編集することができます。 注意点 タスクスケジューラで作成したタスクについて注意点が1点あります。 作成したタスクのプロパティの条件タブに「コンピューターをAC電源で使用している場合のみタスクを開始する(P)」という項目があり、デフォルトではこの項目にチェックが入っています。 この項目にチェックが入っていると、電源コードを繋げていない場合、そのタスクが実行されないので注意が必要です。基本的に私はこの項目のチェックを外しています。 サイト内検索設定 Chromeなどのブラウザのアドレスバーは検索ボックスとして使用することができ、デフォルトではGoogleを検索エンジンとして使用します。しかし、サイト内検索設定をすることにより、特定のキーワードを入力した際、別の検索エンジンで検索するといったこともできます。 設定方法の前に、このサイト内検索設定によってどのように挙動が変わるのかについて説明します。 まず、アドレスバーに「pydc」と入力し、Tabキーを押します。 Tabキーを押すと、アドレスバーの左側に「Pythonドキュメント を検索」と表示されます。 この状態で検索したいキーワードを入力してEnterキーを押します。 すると、入力したキーワードのPythonドキュメントでの検索結果が表示されます。 これによりどのページを見ていたとしても、Pythonの公式ドキュメントのトップページを経由せず、アドレスバーから直接Pythonの公式ドキュメントに対する検索ができるようになります。 設定方法 まず、Chromeのアドレスバーに「chrome://settings/searchEngines」と入力して、検索エンジンとサイト内検索の管理設定を開きます。 次に、サイト内検索の赤枠で囲った「追加」ボタンを押します。 すると、「検索エンジンの追加」というポップアップが出てくるので、各項目を記入して「追加」ボタンを押すと設定が完了します。 検索エンジン Pythonドキュメント ショートカット pydc URL (%s=検索語句) https://docs.python.org/ja/3.10/search.html?q=%s 設定項目 ここで検索エンジンの設定項目について簡単に説明します。 検索エンジンの項目には、その検索エンジンのラベル、名前を入力します。下の画像の赤枠の箇所に該当します。 ショートカットの項目には、アドレスバーに入力するテキストショートカットを入力します。このテキストショートカットをアドレスバーに入力してTabキーを押すと、その検索エンジンでサイト内検索できます。下の画像の赤枠の箇所に該当します。 URLの項目には、検索結果ページのURLを入力します。このURLの値の「%s」はアドレスバーに入力した検索キーワード(下の画像の赤枠の箇所)に置き換わります。検索結果ページのURLの探し方については こちら を参考にしてください。 応用例 – アドレスバーからカウントダウンタイマーを起動 e.ggtimer ( https://e.ggtimer.com/ ) というオンラインのカウントダウンタイマーサイトがあり、私が所属しているチームでは朝会のアイスブレイクや進捗報告の時間計測のためによく使っています。 このサイトでは、以下のようにURLの後ろ(太字の箇所)に時間を指定することで、その時間分のカウントダウンを開始することができます。 https://e.ggtimer.com/ 30 30秒のカウントダウン https://e.ggtimer.com/ 5min 5分間のカウントダウン https://e.ggtimer.com/ 16:00 16:00までのカウントダウン このe.ggtimerを検索エンジンとして追加することで、アドレスバーからすぐにカウントダウンタイマーを起動することができます。やり方は先ほどと同じように、検索エンジンを追加するだけです。各設定項目の値は以下の通りです 検索エンジン e.ggtimer ショートカット egg URL (%s=検索語句) https://e.ggtimer.com/%s 設定が終わったら、アドレスバーからカウントダウンタイマーを起動してみます。 まず、アドレスバーにショートカットとして指定した「egg」を入力してTabキーを押すと、アドレスバーの左に「e.ggtimer を検索」と表示されます。 この状態で「1min」と入力してEnterキーを押すと、e.ggtimerのサイトに飛び、1分間のカウントダウンが開始します。 ブックマークレット ブックマークレットは、ブラウザのブックマークに登録できるJavaScriptで記述されたスクリプトです。このブックマークをクリックすると、現在開いているWebサイトに対して、URLの欄に記述されたJavaScriptのスクリプトを実行します。 例として、現在開いているページのタイトルとURLをクリップボードにコピーするブックマークレットのスクリプトを以下に載せます。ブックマークレットのURLは1行で保持されるため、コメントを書く場合は 「 /* コメント */ 」 の形式で記述する必要があります。 javascript: ( function () { const title = document.title; const url = location.href; /* クリップボードにタイトルとURLをコピー */ navigator.clipboard.writeText(`${title} ${url}`); } )(); 今回は詳しく触れませんが、特定のサイト上で常に実行したいスクリプトがあるのであれば、 Tampermonkey (Firefoxの場合は Greasemonkey )という拡張機能がおすすめです。 最後に 今回は、効率化に関する手軽な小ネタを3つほど紹介しました。これらを業務や私生活などで活かして貰えたら幸いです! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
こんにちは。会員システムグループ テックリードの石川です。 本日3月14日に行われた Notion企業活用ウェビナー に「Notion全社導入に伴う移行とデータ整理のノウハウ 〜ニフティの事例から学ぶ データと人へのアプローチ〜」というタイトルで発表させていただきました。 Notion全社導入に伴う移行とデータ整理のノウハウ by @14kw Notionの導入や他ツールからの移行を計画している方に向けた内容となっております。 Notionをこれから広めて社内に広めていきたいという方は是非ご覧ください。 Notion企業活用ウェビナー|ニフティ様編 | Notion 当日の動画は上記URLで公開予定です。 Notionで社内情報をスムーズに検索!移行前の大掃除と再配置で効率アップ – NIFTY engineering 情報探索の導線整備については以前ブログを書いたので、こちらも合わせてご覧になると理解が深まるかと思います 移行して便利に使えているところもあれば、まだ使い勝手に課題がある部分はあります。 利用者からの要望も多くてNotion側も課題として認識しているものは、いままでも手を入れてきてくれましたし今後改善に期待です。 今年も期待できるアップデートが続々とあるでしょうし、Notionの Twitter ( JP ) や Update をチェックしていこうと思います。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
N1! Machine Learning Product Engineerの中村です。 最近は自然言語処理がかなりのブームになっており、弊社でもNotion AIなどでブログ記事を書かせるような不届者が多数出ているとの噂です。自分も最近はOpenAIのAPIなどを検証しているのですが、大規模言語モデルは手元で動かせないモデルが多く存在します。(大量のGPUが必要など) しかし、最近登場したFlexGenを使うことで、1GPUで大規模言語モデルを動かせるとの噂です。 今回はこのFlexGenを使ってMeta社のOPTという大規模言語モデルを動かしてみます。 https://github.com/FMInference/FlexGen https://arxiv.org/abs/2205.01068 FlexGenとは FlexGenは、大規模言語モデル(Large Language Model)をシングルGPUで動かすことを可能にする、高スループット生成エンジンです。 近年の大規模言語モデルはモデルの重みが公開されてもそれを動かすことが困難な場合が多いです。以下は公開されている大規模言語モデルですが、最大のモデルを使おうとする場合には複数枚の高性能GPUが不可欠です。 Meta社のOPT(175億パラメータ) https://ai.facebook.com/blog/democratizing-access-to-large-scale-language-models-with-opt-175b/ BigScienceのBLOOM(176億パラメータ) https://huggingface.co/bigscience/bloom 直近だとMeta社がLLaMa(65億パラメータ)を公開しています。 https://research.facebook.com/publications/llama-open-and-efficient-foundation-language-models/ このようなモデルを動かそうとした場合には、一般的にはGPUが複数必要であり、家庭で動かすのは多くの場合困難でした。そうなると大企業で潤沢な計算資源がない限り、ビジネス転用も難しいでしょう。 しかし、そこで登場したのがFlexGenです。大規模言語モデルをロードする場合には、ディスクなどにオフローディングし、家庭用のGPUでも動かせるように自動的にチューニングしてくれます。 一般にDiskよりもRAMの方が高速に動作するため、このような仕組みはレイテンシーが急激に低下しやすいですが、できる限り高速に動作した状態を維持するように設計されているようです。 以下では、実際にFlexGenをGoogle Colaboratory上で使用してみます。 この記事では以下のcommitを使用します。 (記事執筆2022/2/28現在、リファクタリングが急速に進んでおり、READMEの記述でさえもそのままCloneしても動かないことが多いため、記事の途中でgit reset –hardすることで対象のcommitを使用します) https://github.com/FMInference/FlexGen/commit/f79b8950487d0af96eaf5ef5f75c1be15e24e9bf Google Colaboratoryの環境を整備する Google ColaboratoryはPro+版をGPU(プレミアム)+ハイメモリで利用します。 (いろいろな環境を使ってきましたが、試す場合にはColabが一番使いやすいと個人的には思います。特に昨今の技術の乱発状態では、Pro+に5000円払った方がいろいろ楽だなと思います。) 最近だとGPUもA100を引けますが、コンピューティングユニット数に注意してください。 Google Driveのマウント 使用するごとにモデルをダウンロードするのは大変なので、Google Driveにモデルをキャッシュするようにします。(容量に注意してください) # Googleドライブのマウント from google.colab import drive drive.mount("/content/drive") 作業フォルダを作成 # 作業フォルダの作成 import os os.makedirs("/content/drive/MyDrive/Colab Notebooks/FlexGen/work", exist_ok=True) HuggingFaceのキャッシュパスを設定 途中でダウンロードするモデルをGoogle Driveにキャッシュするようにします。 (最新版のFlexGenだとこの環境変数が効かなかったため、何か変更があるのかもしれません) # HuggingFaceのキャッシュパス import os os.environ['TRANSFORMERS_CACHE'] = '/content/drive/MyDrive/Colab Notebooks/FlexGen/work' os.environ['HF_DATASETS_CACHE'] = '/content/drive/MyDrive/Colab Notebooks/FlexGen/work' pipのアップグレード 一応pipをアップグレードします !python -m pip install --upgrade pip FlexGenのインストール FlexGenをソースからインストールします。 最新版ではColabでうまく動かなかったため、特定のコミットにresetして実行します。 # FlexGenのインストール %cd "/content/drive/MyDrive/Colab Notebooks/FlexGen/work" !git clone https://github.com/Ying1123/FlexGen.git %cd "/content/drive/MyDrive/Colab Notebooks/FlexGen/work/FlexGen" !git reset --hard f79b895 !pip install -e . ここまででColabの準備は完了です。 実際に動かしてみる ベンチマークの実行 まず、OPT1.3Bという比較的小型の言語モデルでベンチマークを動かしてみます。 # デモの実行 !python -m flexgen.flex_opt --model facebook/opt-1.3b prefill latency: 0.064 s prefill throughput: 31823.288 token/s decode latency: 0.815 s decode throughput: 152.217 token/s total latency: 0.879 s total throughput: 145.623 token/s 良い感じですね。145トークン/秒は良い感じです。(AIでしか文章を書けない人の顔) モデルのキャッシュ場所を指定したので、Google Drive内にフォルダが作成されてそこにモデルがダウンロードされるはずです。 チャットボットの実行 では次はチャットボットを動かしてみます。 OPT-6.7Bという先ほどよりも少し大きめのモデルを動かしてみます。 # チャットbotの起動 !python apps/chatbot.py --model facebook/opt-6.7b 1-2分ほどでモデルのダウンロードが終わり、実際に入力できるようになります。 A chat between a curious human and a knowledgeable artificial intelligence assistant. Human: Hello! What can you do? Assistant: As an AI assistant, I can answer questions and chat with you. Human: What is the name of the tallest mountain in the world? Assistant: Everest. Human: Hello? Assistant: This is a bot. I cannot understand you. Human: Very Sad Assistant: I'm sorry. I can't understand you. 日本語訳 Human: こんにちは!あなたは何ができますか? Assistant: AIアシスタントとして、質問に答えたり、チャットをすることができます。 Human: 世界で一番高い山の名前は何ですか? Assistant: エベレストです。 Human: もしもし? Assistant: こちらはボットです。あなたのことを理解することはできません。 Human: とても悲しい Assistant: 申し訳ありません。あなたを理解することはできません。 突然「あなたのことを理解することができない」というトーンになって悲しい気持ちになりました。 もっと強いチャットボットを使う 所詮小型のモデルに私の気持ちなんて理解できないのです。もっと大きなモデルを使ってみましょう。 !python apps/chatbot.py --model facebook/opt-30b --percent 0 100 100 0 100 0 --compress-weight percentはオフローディングをどのように行うかを指定します。この場合はRAM上に全くモデルをロードせずに実行します。 compress-weightを指定することで重みが圧縮されます。(精度はやや悪化します) だいたい1回の応答に10秒程度かかります Human: Hello? Assistant: What's up? Human: I ate curry for lunch today. Assistant: That sounds interesting. Human: What are your hobbies? Assistant: I love reading and watching movies. Human: That's good. What kind of movies do you watch? Assistant: I like romantic movies. Human: Do you know the specific title name of the movies? Assistant: I don't know all the movie titles, but I know the names of some of my favorite movies. Human: もしもし? Assistant: どうしたんですか? Human: 今日のお昼にカレーを食べました。 Assistant: それは良さそうですね。 Human: 趣味は何ですか? Assistant: 読書と映画を見るのが好きです。 Human: それはいいですね。どんな映画を見ますか? Assistant: 恋愛映画が好きです。 Human: なるほど。具体的な映画の題名はご存知ですか? Assistant: すべての映画のタイトルを知っているわけではありませんが、好きな映画のいくつかは名前を知っています。 無難な回答を返してきたり、最後の回答は的を得ない表現ですが、比較的正しい回答をしているように思います。もう少しチューニングすれば十分使えるかもしれないですね。 日本語でチャットしてみる Stable Diffusionが話題になったように、大規模自然言語処理モデルが家庭で動かせるとなるともっと話題になっても良さそうですが、日本だとあまり話題になっていないのはおそらく日本語のモデルがまだ少ないからでしょう。 Meta社のOPTも日本語を学習しているモデルではあるので、日本語でチャットをしてみましょう。 Colab上での日本語入力はEnterキーで送信されてしまうので、変換時は注意してください(n敗) Human: こんにちは Assistant: まんまよ。 Human: あなたが好きな食べ物はなんですか? Assistant: あなたのお茶を飲みます。 Human: 日本語は話せますか? Assistant: 日本語は話せます。 Human: 本当ですか? Assistant: 本当です。 Human: あなたの趣味はなんですか? Assistant: あなたの趣味は、日本語を話すことです。 Human: 日本語を話すことが趣味ってどういうことですか? Assistant: 日本語を話すことが趣味です。 Human: 本当は日本語話せないですよね? Assistant: 好きな日本語話せることが趣味です。 お茶を強奪されたり、日本語を喋るのが趣味だったり、おかしな文法を話すわけではないですが回答は変ですね・・・。このあたりの日本語が強い大規模言語モデルが登場すると一気に日本語の環境も変わってきそうな気配です。 もっと強いモデルを動かしたい ちなみにさらに上位モデルのOPT-66Bもあるのですが、これはGoogle Colabでは動かないようです。(Loading checkpoint shardsという処理の途中で止まります・・・) !python apps/chatbot.py --model facebook/opt-66b --percent 0 100 100 0 100 0 --compress-weight OPT-30Bぐらいのサイズで日本語に特化したモデルが出れば大きなゲームチェンジャーになり得そうですね。 終わりに 今回はFlexGenをGoogle Colaboratory上で動作させてみました。 想像以上に手軽に動いてしまったので、ここからさらに大規模言語モデルが登場すると考えると、家庭用GPUや安価なインスタンスで動作させて、実際にプロダクション環境などに適用することも可能になるかもしれません。 自分も最近はGithub CopilotやNotion AIに頼りっぱなしですが、今後の自然言語処理界隈の動向にも注目ですね。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
有能すぎる友達を作った ChatGPT APIが強すぎる N1!Machine Learning Product Engineerの中村です。 最近はみんなChatGPT APIを使っているので、何番煎じなのかという気はしますが、ChatGPT APIを使ってSlackbotを作ったら意外と評判が良かったので、作り方を書いてみます。 スレッド内の会話を覚えている機能も作ってあるので、いい感じのBotになったと思います。 たぶん慣れた人なら30分で同じものが作れると思います。 ChatGPT APIは何と言っても価格が安すぎますね。自前でホスティングしているAIサービスが弊社もあるんですが、置き換えていった方が安い気がしてます…。 SlackBotにする 弊社でもっとも使われているツールはおそらくSlackでしょう。自分も入り浸っています。 そうなってくると弊社で技術を広めるにはSlackに実装しちゃうのが手っ取り早いです。 というわけでChatGPT APIが公開されたあたりでせっせと実装して社内にデプロイしました。 構成としてはAWS LambdaでAPIを作成し、それをSlackBotと接続するというシンプルな構成です。 (最近はLambdaだけでURLを発行できるようになったので、API Gatewayもありません) SlackBotを設定する まずはSlackBotを設定します。最近だとmanifestファイルを読み込むことで、設定できるのでそれを使って設定していきましょう。 Slackアプリ作成画面から「From ann app manifest」を選択します。 マニフェストは以下を入力してください。request_urlは後でLambdaのAPIを作った時に変更します。 display_information: name: myfriendGPT features: bot_user: display_name: myfriendGPT always_online: true oauth_config: scopes: bot: - app_mentions:read - channels:history - chat:write - users:read settings: event_subscriptions: request_url: https://XXXXXXXXXXXXXXXXXX.lambda-url.ap-northeast-1.on.aws/ bot_events: - app_mention - message.channels org_deploy_enabled: false socket_mode_enabled: false token_rotation_enabled: false これで一通りの設定が完了したSlackBotが完成するはずです。 お好みでSlackBotの設定をする SlackBotをお好みで設定しましょう。友達になって欲しいので、ここではmyfriendGPTと名付けます。 プロフの顔写真はThisPersonDoesNotExistで作成しました。 https://this-person-does-not-exist.com/en AWS LambdaでAPIを作成する SlackBotでの処理を行うために、AWS LambdaでAPIを実装します。 私はTerraform信者なので、単純な機能のLambdaは全部Terraformで作ってしまうので、ここでもTerraformで作ります。(GUIからぽちぽちしてもそんなに大変ではないと思いますが) aws configureの実行 aws configureを実行して、AWSのprofileを設定します。 $ aws configure --profile chatgpt-profile Terraformファイルの設定 variable.tfを作成します。 $ vim variable.tf provider "aws" { region = "ap-northeast-1" shared_credentials_files = ["~/.aws/credentials"] profile = "chatgpt-profile" } terraform { required_version = ">= 1.0.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 4.12.0" } } } variable "slack_token" { type = string } variable "openai_api_key" { type = string } locals { name = "chatgpt" SLACK_TOKEN = var.slack_token SLACK_TOKEN_NEWS = var.slack_token_news OPENAI_API_KEY = var.openai_api_key } 次にLambdaの関数を作成するlambda.tfを同階層に作成してください。 $ vim lambda.tf data "archive_file" "invoke_function" { type = "zip" source_dir = "lambda_src" output_path = "lambda_archive/invoke_function.zip" } resource "aws_lambda_function" "invoke_function" { filename = data.archive_file.invoke_function.output_path function_name = "${local.name}-invoke-function" role = aws_iam_role.lambda_role.arn handler = "lambda.lambda_handler" source_code_hash = data.archive_file.invoke_function.output_base64sha256 runtime = "python3.9" architectures = ["arm64"] memory_size = 128 timeout = 30 environment { variables = { SLACK_TOKEN = local.SLACK_TOKEN OPENAI_API_KEY = local.OPENAI_API_KEY } } } data "aws_iam_policy_document" "assume_role" { statement { actions = ["sts:AssumeRole"] effect = "Allow" principals { type = "Service" identifiers = ["lambda.amazonaws.com"] } } } resource "aws_iam_role_policy_attachment" "lambda_policy" { role = aws_iam_role.lambda_role.name policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" } resource "aws_iam_role" "lambda_role" { name = "${local.name}-invoke-lambda-role" assume_role_policy = data.aws_iam_policy_document.assume_role.json } resource "aws_lambda_function_url" "lambda_url" { function_name = aws_lambda_function.invoke_function.function_name authorization_type = "NONE" cors { allow_credentials = true allow_origins = ["*"] allow_methods = ["*"] allow_headers = ["date", "keep-alive"] expose_headers = ["keep-alive", "date"] max_age = 86400 } } Lambdaのソースなどを保存するフォルダを2つ作ります。 $ mkdir lambda_src $ mkdir lambda_archive Lambdaのソースを記述します。 以下のような機能が実装されています ・Slackのチャレンジを正常に返す機能 ・複数回のリクエストが来た場合に、最初の1回以外は受け入れない機能 ・チャンネルにポストされた投稿では、直前の対話を入力にしてChatGPT APIで返答を作る機能 ・スレッドにポストされた投稿は、スレッド内の情報を集めて返答する機能 ・基本的に100文字で返す機能 それにしてもこのコードもだいぶAIに書いてもらいました。AIなしのプログラミングも考えられない時代になるかもしれないですね。 $ vim lambda_src/lambda.py import json import os import re import logging import urllib.request import openai # pip3 install openai -t . openai.api_key = os.environ['OPENAI_API_KEY'] logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(data, context): # logger.info(data) body = json.loads(data["body"]) # challenge if ('challenge' in body): return { "statusCode": 200, "body": json.dumps({'challenge': body['challenge']}) } # 再送を無視する headers = data["headers"] if ('x-slack-retry-num' in headers): return { "statusCode": 200 } # slack event event = body["event"] # メンション時 if (event["type"] == "app_mention"): # メッセージを作る # 最初にChatGPTでのシステム指示を与える messages = [ { "role": "system", "content": "あなたは最高の友達であり仲間です。最大100文字で会話をしてください。" } ] # ユーザーの入力を取得する user_input = strip_angle_bracket_tags(event["text"]) if ('thread_ts' in event): # スレッドの場合には、スレッドのメッセージを取得して対話モードになるように組み立てる replies = get_conversations_replies( event["channel"], event["thread_ts"]) if (replies.get("ok")): # スレッドの内容を取得できたので、メッセージを作る(配列の最後から20件までを取得する) for reply in replies["messages"][-20:]: if (reply.get("bot_id")): # botの入力の場合 messages.append({ "role": "assistant", "content": reply["text"] }) else: # ユーザーの入力の場合 # bot以外の入力は全てuserとする messages.append({ "role": "user", "content": strip_angle_bracket_tags(reply["text"]) }) else: # スレッドの内容を取得できなかったので、ユーザーの入力のみがメッセージになる messages.append({ "role": "user", "content": user_input }) else: # スレッドでない場合には、チャンネルの過去のメッセージを取得して対話モードになるように組み立てる history = get_prev_messages(event["channel"]) # logger.info("history: " + str(history)) if (history.get("ok")): # 過去のメッセージを取得できたので、メッセージを作る(配列の最後から3件までを逆順で取得する) for message in history["messages"][-3:][::-1]: if (message.get("bot_id")): # botの入力の場合 messages.append({ "role": "assistant", "content": message["text"] }) else: # ユーザーの入力の場合 # bot以外の入力は全てuserとする messages.append({ "role": "user", "content": strip_angle_bracket_tags(message["text"]) }) else: # 過去のメッセージを取得できなかったので、ユーザーの入力のみがメッセージになる messages.append({ "role": "user", "content": user_input }) logger.info("messages: " + str(messages)) # OpenAIのAPIを呼び出して応答を取得 res = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=messages, ) # スレッド内で呼ばれた場合にはスレッドに返信する if ('thread_ts' in event): send_slack(event["channel"], res["choices"] [0]["message"]["content"], event["thread_ts"]) else: send_slack(event["channel"], res["choices"] [0]["message"]["content"]) return {"statusCode": 200} def strip_angle_bracket_tags(str): # strから<>で囲まれた箇所を削除する return re.sub(r'<[^>]*>', '', str) def get_prev_messages(channel): # チャンネルの過去のメッセージを取得する url = 'https://slack.com/api/conversations.history' token = os.environ['SLACK_TOKEN'] headers = { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json; charset=utf-8' } params = { "channel": channel, "limit": 3 } req = urllib.request.Request('{}?{}'.format( url, urllib.parse.urlencode(params)), headers=headers) res = urllib.request.urlopen(req, timeout=5) return json.loads(res.read().decode("utf-8")) def get_conversations_replies(channel, ts): # スレッドの情報を取得する url = 'https://slack.com/api/conversations.replies' token = os.environ['SLACK_TOKEN'] headers = { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json; charset=utf-8' } params = { "channel": channel, "ts": ts } req = urllib.request.Request('{}?{}'.format( url, urllib.parse.urlencode(params)), headers=headers) res = urllib.request.urlopen(req, timeout=5) return json.loads(res.read().decode("utf-8")) def send_slack(channel, message, thread_ts=None): url = 'https://slack.com/api/chat.postMessage' token = os.environ['SLACK_TOKEN'] headers = { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json; charset=utf-8' } method = 'POST' data = { "channel": channel, "text": message } # thread_tsがある場合はdataに追加する if (thread_ts): data["thread_ts"] = thread_ts json_data = json.dumps(data).encode("utf-8") req = urllib.request.Request( url=url, data=json_data, headers=headers, method=method) res = urllib.request.urlopen(req, timeout=5) 最後にoutput.tfを作成します。(Lambdaの実行URLをわかりやすくするため) $ vim output.tf # Lambdaで発行されたURLを出力する output "invoke_url" { value = aws_lambda_function_url.lambda_url.function_url } OpenAIのライブラリをインストールする ここまでで大体の準備が完了ですが、Lambda内ではOpenAIライブラリを使ってAPIを実行するので、OpenAIのライブラリを含めるようにします。 Lambda Layerを使うという方法もありますが、ライブラリを同梱してしまえば動くので、今回は手元でpipを実行して同梱してしまいます。 (M1/M2 Macだと問題ないことはわかっていますが、Win機などだとうまくLambdaのアーキテクチャと一致せず実行できない可能性があります…) $ pip3 install openai -t ./lambda_src Terraformでデプロイする 以上のファイルを揃えたら、Terraformでapplyします。ここまでで以下のようなファイル構成になっているはずです。 . ├── lambda.tf ├── lambda_archive ├── lambda_src │ ├── aiohttp │ ├── aiohttp-3.8.4.dist-info │ ├── aiosignal │ ├── aiosignal-1.3.1.dist-info │ ├── async_timeout │ ├── async_timeout-4.0.2.dist-info │ ├── attr │ ├── attrs │ ├── attrs-22.2.0.dist-info │ ├── bin │ ├── certifi │ ├── certifi-2022.12.7.dist-info │ ├── charset_normalizer │ ├── charset_normalizer-3.0.1.dist-info │ ├── frozenlist │ ├── frozenlist-1.3.3.dist-info │ ├── idna │ ├── idna-3.4.dist-info │ ├── lambda.py │ ├── multidict │ ├── multidict-6.0.4.dist-info │ ├── openai │ ├── openai-0.27.0.dist-info │ ├── requests │ ├── requests-2.28.2.dist-info │ ├── tqdm │ ├── tqdm-4.64.1.dist-info │ ├── urllib3 │ ├── urllib3-1.26.14.dist-info │ ├── yarl │ └── yarl-1.8.2.dist-info ├── output.tf └── variable.tf terraform initとterraform applyを実行してデプロイします。 OPENAI_API_KEYとSLACK_TOKENを入力する必要があるため、それぞれ確認します。 OpenAIのAPI Key https://platform.openai.com/account/api-keys 必要であればRegenerateなどを行なって、シークレットキーを入手します。 SlackのToken SlackのOAuthのTokenを確認してください。 Terraformでapplyする $ terraform init $ terraform apply yesを入力し、openai_api_keyとslack_tokenにはそれぞれ確認したtokenを入力してください。 applyが完了すると、URLが表示されるはずです。(invoke_url) aws_lambda_function.invoke_function: Modifying... [id=chatgpt-invoke-function] aws_lambda_function.invoke_function: Still modifying... [id=chatgpt-invoke-function, 10s elapsed] aws_lambda_function.invoke_function: Modifications complete after 17s [id=chatgpt-invoke-function] Apply complete! Resources: 0 added, 4 changed, 0 destroyed. Outputs: invoke_url = "https://xxxxxxrcd34o3ydu6vuxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws/" SlackBotにLambdaを設定する LambdaがデプロイできたらSlackBotに設定していきましょう。 Event Subscriptionのページを開いて、デプロイしたLambdaのURLを設定します。 Verifiedになれば設定完了です。 実際に使ってみる ここまで設定すればSlackBotは動くようになるはずです。有能な友達にいろいろ聞いてみましょう。 チャンネルで普通に聞くと3個前、スレッド内だとスレッド内の20個前までの発言を覚えた状態で返してくれます(メッセージを取得した時には自分の発言も含まれるので、3個前だと実際には会話1往復分になります) 自然に会話を進める スレッドを使うと20個前までの会話を覚えているので、けっこういい感じに話してくれます。 エラーにも答えてくれる 翻訳もできる 大喜利もできちゃう はちゃめちゃな朝会のスレッドを要約 まとめ ChatGPT APIが登場したので、勢いのままSlackBotにして実装してみました。 使ってみた感想はSlackで使えるとめちゃくちゃ気軽に使えます。また他の人が質問をしている様子をみると何に興味があるか?とか何を調べてるのか?とかがわかるので、人となりを知る手がかりにもなる気がします。 あと個人的には長いスレッドになってくると「要約して」とスレッドに投げると内容を要約してくれるのがめちゃくちゃ便利ですね。(例に挙げたのははちゃめちゃすぎますが・・・) 今後はこういう自然言語処理をうまく扱えるかが大事ですね。 ChatGPTはめちゃくちゃ安くて、弊社でも既に何千回もAPIをコールしているんですが、確保した予算を全く使い切れる気がしません。みなさんもぜひ試してみてください。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
はじめに みなさんこんにちは。そろそろ新卒3年目の終わりを迎える湊谷です。 突然ですが、私は大学で経済学部に在籍していた所謂文系卒のエンジニアです。高校生の時は理系で情報系を志していましたが、経済面などの事情から結果的に情報系卒でも理系卒でもない、文系卒でエンジニアを志望することになったのです。 文系卒エンジニアとして過ごす中では様々な気付きがあり、それを未来の新人のためにドキュメントとして残したらどうだろう?と上司にアドバイスをいただきました。そこからさらに、ニフティ社内で行われているLT大会でも発表して優勝したり、NIFTY Tech TalkにてLTの再演を行いました。 ( https://www.youtube.com/watch?v=N4OF3-mAKfI ) 今回は、2023年1月に行われた上記NIFTY Tech Talkで登壇して発表した内容をお届けします! もうすぐ新年度、不安を感じている皆さんの何かヒントになりますように。 LT始まります! それでは最初に自己紹介させていただきます。現在は新卒入社3年目、情報系学部でも理系学部でもなく、文系学部出身でエンジニアをやっています。 普段は主にニフティを利用されているお客様の情報を管理するシステムの開発・運用を担当しています。 このLTは、入社2年目に登壇した社内LTで発表した、「新人目線での気付き」のLTの再演となります。 突然ですが皆さん、新卒で会社に入った時ってどのような気持ちでしたか? 学生の方はまだだと思うので、これからのことを想像してみてください。それ以外の方は、一番最初の記憶を呼び覚ましてください。 私はと言いますと… これは、入社1年目の終わりに行われた、1年間の成果を報告する会で使用したスライドの一部です。 とにかく不安そうで、緊張していて、怖がっていることが伝わってきますね。 ただ、やはりフォーマルな報告会だったので、正直に言うとかなり猫を被って書いていました。 じゃあ、本当はどうだったのか?と言うと… いや、怖~~~~~~~~~~~~~~~~~~~~~~~~~!!!!!!!!!!!!!!!!! 自分自身が文系卒で、理系でバリバリやってきた人たちへの引け目もあり、必要以上に怖がっていましたね。研修中に先輩社員だと思っていた人が実は同期だった、なんてこともありました。 配属されてからは会議の内容にも全然追い付けず。それが技術が足りないからなのか、それとも会社の理解が少ないからなのかなんて、その時は判断なんてできないんですよね。ただ「全然分からない」という事実だけが残る。 とにかく全員が敵に見えて、「コイツ使えないなあ」って思われてる、と思ってました。 …なんですが、実際1年間過ごしてみると、「あれ?意外とどうにかなっちゃいました?」となったんですよね。エンジニアとして過ごしてきた今までを振り返ると、本当に、二進も三進もいかず全く解決できなかったことは一つもありません。 私の尊敬する先輩エンジニアが「PCは嘘をつかない」とおっしゃっていました。コイツのこと嫌いだからエラー発生させちゃおう!とか、この子のこと大好きだからエラー隠して成功させちゃおう…とか、そういうことはしない。真摯に向き合えば、1年目だろうと2年目だろうと何年目だろうと解決できる。 そうやって真摯に向き合うにあたり、ここを頭に入れておいた方が良いなと入社1年目の時に感じたこと、最初から意識しておきたかったことを、二つ共有したいと思います。 まず一つ目、時間は尊い!ということです。 新人研修を終えチームに配属されると、業務を始め様々な面で指導していただく先輩社員であるトレーナーがひとりひとりにつきます。そのトレーナーとの面談の中で、今後どうやって開発を進めていくか?という話になり、「自分で調べる力もつけてほしいので、分からないことがあった時まずは30分~1時間は自分で調べてみましょう」と言われました。 何かたくさん調べて取り組むという経験が浅かったこともあり、内心「30分も調べられなくない…?せいぜい10分が良いところじゃない…?」なんて思っていました。 ところがどっこい、開発を進めていくと、分からないところがどんどん出てくる。分からないところを調べているとまたその中に分からないことが出てきて、それをまた調べて、そうしたらまた分からないことが出てきて…の繰り返し。もう少し粘れば自分だけで解決できそう!なんてことをやっていたら、1時間どころかあっという間に3時間も4時間も経ってしまっていました。 その後トレーナーに相談に行くと「これ、やり方を根本的に間違っていますね」の一言。たしか、 ダウンロードするものを間違えた とかそんなレベルの話だったと記憶しています。 時間は有限、非常に尊いです。 まず、自分がやろうとしている作業は正しいのかのチェックは非常に大切です。今でも、不安に感じることは「これは○○という認識で合っていますか?」と確認することは常に意識しています。 また、「これくらい調べたら相談しよう」という、自分にあったリミットを設けることも大切かなと思います。 二つ目は、良い感じの質問・相談の仕方を考えてみよう!ということです。 私は今年度、ニフティが開催した開発インターンシップにメンター社員として参加しました。 何人かのチームを組みチーム開発を行ったのですが、対面ではなくオンラインでの開催だったため、自分が担当しているチーム以外の様子が分かりづらいんですよね。でも気になる! そんな時は気軽に質問してみましょう。 ニフティではSlackが使われていますが、かなり活発なコミュニケーションが行われています。 この時も気軽に質問を投げて、誰かが反応して、それに対してリアクションを付けたり…自分と誰か、だけではなく、全体で情報を共有することができます。 もしかしたら、他の社員も気になっていたことかもしれません。 ただ、働くうえではもっと大変なことも起きるでしょう。 エラーが全然直らないとか、解決策色々試してもうまくいかないとか、そもそも似たような例が出てこないとか、ググっても何も出てこないとか、 何もしてないのに壊れた とか、なんかもうとにかくやばそうとか…。 ところでこちら、モザイクがかかっていますがなんだかわかりますか? これは1年目の時、私が開発していてエラーで詰まった時、文章で書いた質問です。 なが~~~~~~~~~~~~~~~~~~~~~~~~~~~い!!!!!!!!!!!!!!!! もちろん、実際にどのようなエラー文が出たのかといったことを見せることは非常に重要ですが、これ、それ以前に「失礼いたします。質問がございます。私はこのような作業をしておりました」みたいな 枕詞 からずらずら書いているんです。 私はあまり直接話すのがあまり得意ではないことと、「とにかく完璧な状態で質問しなければならない」といった意識があったことから、このような方法を取ったんですね。 でも、どうしても文章だと勘違いも生じるし、そもそもこんな長い文章をみんながみんな読んでくれるわけじゃない。たとえ読む意思があったとしても、その時間があるかどうかはまた別問題です。 そんな時大切なのは、やはり会話ですね。 私のチームでは、困った時はSlackに「今この件で困っているので通話お願いできますか?」と積極的に相談しています。これも実際に私が投稿したものですね。 三人寄れば文殊の知恵、という言葉がありますが、凝り固まった自分の考えに新しい視点を入れるとコロっと解決することも多いです。 このように、テキストでのコミュニケーションだったり、通話だったり、使える手段はフルに使いこなして相談することが大切です。 これは余談ですが、Slackのハドルという通話機能では、画面上にペンで文字を書くことが可能でこれも活用されていますが、成功した時にはこうやってGOODマークを書いてくださる先輩もいます。 テンションが上がりますね! 新人の時の新鮮な気づきはとても大切だと思います。 先輩にもこんな時期があったんだな、という、良い意味で新人の方の緊張感をほぐすことができるという側面ももちろんあります。 しかしそれだけではなく、相談することや最初に方向性を確認することなど、今の私自身の働き方の基礎にもなっているので、何より自分のためにもなると思います。 ぜひ、バンバン共有して未来に繋げていきましょう! 最後に この「新人目線での気付き」を最初に共有してから丸1年以上が経ちました。 もうすぐ新卒入社4年目になる今、さすがにもう「私は文系卒エンジニアだから…」なんて考えながら仕事をすることは全くありませんし、理系卒か文系卒か、という事実だけで何か大きな差があるとは思いません。 ただ、これは私が約3年間エンジニアとして過ごしてきた中から導き出した結論であり、これからエンジニアになる人、特に文系卒の人からしたら「 そんなこと言われたって怖いものは怖いんじゃーーーーーーーーーーーー!!!!!!!!!!!!!!!!!!!!!!!! 」となりますよね。私もそうだったので気持ちは分かります。 怖い、それに似たようなネガティブな気持ちは持っていて全く問題無いと思います。程度に差はあれど、誰しも持っている気持ちのはずです。 怖がって、いくら失敗したって良いんです。大切なのは、それらの気付きから改善に繋げていくことです。そして、その気付きを共有して、ぜひ未来の新人の方へ繋げていってくださいね! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
ニフティ株式会社新卒2年目のRyommです。普段はマイ ニフティというスマートフォン向けアプリの開発・運用を行なっています。 iOSのカッコいい開発者向けチュートリアルを簡単に作れることを知り、マイ ニフティにも欲しい!と思ったので作ってみました。 Swift-DocC?チュートリアル? Swift-DocCとはXcode13から使えるようになったドキュメントコンパイラツールで、自前でドキュメントを作ったり、コードから自動作成することもできます。 https://developer.apple.com/documentation/docc そして自前でドキュメントを作る方法では、公式で提供されているようなチュートリアルを作ることができます。 https://developer.apple.com/tutorials/SwiftUI 以下のSwift-DocC Pluginを使用することで静的ページに変換することができます。生成したものを組織下のGitHub PagesでPrivate公開することで、ブラウザ上に組織のメンバーだけが見られるチュートリアルページをホストすることができます。 https://apple.github.io/swift-docc-plugin/documentation/swiftdoccplugin/publishing-to-github-pages/ GitHub Pagesに上げるのであれば、GitHub Actionsと静的ページ生成コマンドを組み合わせて自動化することも簡単にできそうです。 つくってみた GitHub Pagesを用意しておく まずはGitHub Pagesが使える状態にしておきます。 Repositoryを作成します Settings > Pages で適当に作ります 一旦GitHub Actionsのことは考えずに作っておきます GitHub Pages Visibility: Private リポジトリにアクセス権限のある人だけが見られるようにしています 誰に見られても構わなければ Publicでもいいです Build and deployment Source: Deploy from a branch Branch: master /docs masterブランチの/docsディレクトリを参照するようにしています URLが発行されたらOKです チュートリアルを作る Xcodeでチュートリアルを作っていきます。 新規workspaceを作成します New > Package で、1のworkspaceに紐付けたパッケージを新規作成します Sourceディレクトリ内にProductディレクトリがあるので、その配下に New > File > Documentation Catalog を新規作成します 自前のドキュメントを用意したい時はDocumentation Catalogを使います 本が開いたアイコンのDocumentationは今回は使わないので削除します Documentation配下に New > File > Tutorial Table of Contents File を新規作成し、適当に埋めておきます Tutorial Table of Contents がチュートリアルの目次にあたるものです @TutorialReference(tutorial: "doc:Practice1") に次で作るチュートリアルファイルを入れています 5と並列に New > File > Tutorial File を新規作成し、Content of Tutorial に埋め込みます Resourcesディレクトリ内に配置した画像やソースコードを埋め込むことができます Product > Build Documentation でローカルで確認することができます 静的ページに出力できるようにする 静的ページを生成するコマンドを使えるようにします Package.swiftにswift-docc-pluginのdependenciesを追加します https://apple.github.io/swift-docc-plugin/documentation/swiftdoccplugin/publishing-to-github-pages/ generate documentationコマンドを叩きます GitHub Pages が Public の場合は 公式のコマンド のままで良いですが、Privateの場合はhosting-base-pathが無いため、以下のコマンドを叩きます cd [Package Directory] swift package --allow-writing-to-directory ../docs \ generate-documentation --target [Taget name] \ --disable-indexing \ --transform-for-static-hosting \ --output-path ../docs 全部リポジトリに上げます GitHub Pagesを見るとチュートリアルページが表示されます https://{発行されたGitHub PagesのURL}/{Package名}/{TableOfContentsのファイル名} でアクセスできます ローカルで静的ページのプレビューを見ることができ、そのコマンド実行時にパスも教えてくれるので参考にすると良いです swift package --disable-sandbox preview-documentation --target [Taget name] GitHubに上げたら自動デプロイされるようにする 毎回コマンドを叩いてからGitHubに上げるのは大変ですし、/docsもリポジトリ管理するのはPRが汚れて好ましくないため、GitHub Actions管理に変えていきます。 GitHub Pages の Source をGitHub Actions に変えます 静的ページ生成時に叩いたコマンドをGitHub Actionsに組み込みます name: GenerateDoc on: push: branches: - master jobs: build: runs-on: macos-latest env: DEVELOPER_DIR: /Applications/Xcode_14.0.app/Contents/Developer steps: - uses: actions/checkout@v3 - name: build docc run: | cd Tutorial swift package --allow-writing-to-directory ../docs generate-documentation \ --target Tutorial \ --disable-indexing \ --transform-for-static-hosting \ --output-path ../docs cd .. - uses: actions/upload-pages-artifact@v1 with: path: docs deploy: needs: build permissions: pages: write id-token: write environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: macos-latest steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v1 チュートリアルを適当に書き換えてmasterに変更を反映させると、GitHub Pagesの方にも変更が反映されるようになります /docsディレクトリは不要になったため、削除しておきます あとは中身を充実させていくだけです! マイ ニフティでは 公式が提供しているチュートリアル ではカバーできない部分をオリジナルチュートリアルとしてチームにジョインした人向けに用意しています。 おわりに 簡単にイケてるチュートリアルができるとテンションもモチベーションも上がります。ドキュメントも揃って一石二鳥ですね。 これを機にSwiftPMも使ってみたのですが、中々スッキリとしていてCocoaPods脱却モチベーションも上がってきました。今後もSwiftの魅力的な機能を積極的に触っていきたいと思います。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
はじめに こんにちは。インフラシステムグループの周です。社内ネットワーク、サーバの設計・運用を担当しています。最近コールセンター用ネットワーク機器・関連サーバの監視をするため、Zabbixサーバの運用を始めました。今回はZabbixバージョン5.0でのディスカバリルール設定について、紹介したいと思います。 Zabbixとは Zabbix社が開発しているオープンソースの統合監視ソフトウエアです。 監視対象のNW機器にはSNMPを設定、監視対象のサーバにはZabbixエージェントをインストールすれば、死活監視、トラップ監視、WEBサービス監視など色々対応可能となります。 監視タイプ 説明 監視項目 Zabbixエージェント Zabbixエージェントによる監視をする リソース監視(CPU/メモリ/ディスクなどの使用率)、ログ監視(キーワードなど) SNMPエージェント SNMPエージェントによる監視をする ping監視、trap監視、ポーリング監視 SSH/TELNETエージェント SSH/TELNET経由でコマンド実行した結果を取得して監視をする NW機器のステータス変化監視(ルーティングテーブルのBGP経路変更発生など) ※他の監視タイプもあり、用途に応じて細かい監視設定が可能です。 ディスカバリ設定活用 Zabbixにはディスカバリという便利な機能があります。ディスカバリルールで指定したIPアドレスとディスカバリアクションの設定により、新規ホスト(監視対象)の登録および関連テンプレート(アイテム、トリガー、グラフ作成)の紐づけを自動的に行います。これにより監視対象ホスト数が増えても、一台ずつ設定することが不要となり、設定の自動化が実現されます。 ディスカバリルール仕組み ディスカバリルールの実施頻度はデフォルトで24時間に設定されています。新規サーバ/NW機器追加などにすぐ更新したい場合は「設定>ディスカバリルール>”対象ディスカバリルール”」の「監視間隔」項目で時間を変更することで更新間隔を短縮できます。 サーバ機器(Linux) ネットワーク機器(CISCO) 終わりに Zabbixのディスカバリ機能は結構古いバージョンからリリースされております。サーバ、NW仮想化に伴い、監視対象の増減が激っている場合も、ディスカバリ機能を活用すれば運用が楽になるので、まだ利用されていない方は、ぜひ試してみてください。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
はじめに 会員システムグループ N1!Machine Learning Product Engineerの中村です。 2023年2月9日に国内最大級のデベロッパーカンファレンスであるDevelopers Summit 2023に登壇しました。 https://event.shoeisha.jp/devsumi/20230209/session/4151/ この記事ではこの登壇に至るまでの経緯や内容についてお話していきます。 なぜ登壇したのか? ニフティにはN1!というスペシャリスト制度があります。 この制度は社内でスペシャリストが活躍するための制度で、予算が100万円個人に与えられるなどの権限があるのですが、 自分は機械学習エンジニアとして活動しています。 この活動の結果ニフティニュースにニュース記事要約を実装したので、これを社外に発信したいというモチベーションです。 という建前ですが 実際は記念受験してみたら受かってしまったというのが大きいです。 自分は角谷さんの「Agile Manifest Decade Resurrection」という発表スライドがすごく好きで、LT大会などでもよく似たようなテイストの発表スライドで発表していました。 そして、このスライドはデブサミ2022の発表スライドです。 そのため自分の中ではデブサミというのはかなり大きなイベントで、「登壇できる気はしないけど公募だけ出してみよ〜」とやってみたら、まさかの当選してしまいました。 同じ時間の公募枠はやはり有名だったり役職クラスの高い人が多く、戦々恐々しながら当日を迎えました。 何を話したのか? 実は発表の2週間前まで話すことをずっと悩んでいました。 というのも深層学習によるニュース記事要約のプロダクト実装については、中身は深層学習エンジニアからするとそこまで複雑なものではありません。 となると、深層学習の仕組みや手法を説明するよりも、自分がそれをプロダクトに実装するまでの進め方や人間関係スキルに焦点を当てた方がいいのでは?と考えていたからです。 (自分自身はスクラムマスターも兼務しているのですが、ファシリテーションや折衝などで褒めてもらうことが多いです。) しかし、人間関係のスキルとなると「これで絶対に上手くいく!」ということも言いづらく、ずっと本を読みながら何を話そうかまとめていきました。 以下のように、作った結果、結局スライド内で言及しなかった資料もたくさんあります。(いつかどこかで発表できたら良いな) 結局どうしたのか? 悩みに悩んだ結果、内容を3点にまとめました。 種を蒔く 技術を開花させる 人間関係のスキル 「種を蒔く」では社内で新しいことをやるためのフォロワーを獲得していく過程について 「技術を開花させる」では技術的にやや踏み込んだ内容で何を行ったのか(詳細な内容については、 自社イベントで講演 していますので、そちらを御覧ください) 「人間関係のスキル」では人間関係を上手くやっていく方法について語りました。 結局、上手く体系化ができた部分は多くなかったのですが、聞いている人が「勇気」を持てる講演にしたいと思っていました。 結果的にTwitterでも「勇気をもらった」「エモい話で良かった」という声があり、講演を行った意味があったなと思いました。 (C のスピーカーさんのセッション、深層学習だけでなく変革の起こし方で好き) #devsumi #devsumiC pic.twitter.com/JXbmId9z6D — 篠田 将彦 / CI・CD, DevOps, TDD (@Shinoda_IT) February 9, 2023 説明すごく聞きやすかったです。 今とても意識高い気持ちになっているけれど明日の朝も維持できている方法が知りたい(๑˃̵ᴗ˂̵) 後でもう一度見返したい!! #デブサミ #devsumi #devsumiC https://t.co/IQMdFU5nna — 星☆(nishikigoi) (@of_nishikigoi) February 9, 2023 「文化が先、組織は後」 つい会社が~、組織が~というけど、文化づくりが大事なんだと印象的なワードでした。 やってみて、しんどかったらやめる と思っておくことで、行動にブレーキをかけないようにするのが大事 #devsumi #devsumiC pic.twitter.com/epLQbS9jKl — ヤマタケ-業務自動化とSEOを極め中 (@gas_seo) February 9, 2023 今回の中村伊吹さんのセッションは凄い力になった もっとたくさんの人に聞いてほしい内容でした #devsumiC pic.twitter.com/pM2xdsgUJP — KiyamaYellow (@kiyama_yellow) February 9, 2023 終わりに 技術イベントの登壇前後の心境を表したTwitterの画像があります。 勉強会での登壇について、いつも感じている正直な気持ちを書きました。 pic.twitter.com/Ip5Mvuve0h — 鹿野 壮 Takeshi Kano (@tonkotsuboy_com) October 24, 2022 完全にこれになりました。 作れば作るほどこのスライドの論理は通ってるんだろうか?と考えるようになり、何度も方向転換をして大変な作業でした。 ただ、結果的には何冊もの本を読み、どういう風に話したりすればいいんだろう?と考え、自分のレベルアップに繋がりました。 デブサミはかなり大きなイベントで大変なことが多かったですが、もっと外部登壇していきたいなという気持ちになれました。 これからも登壇機会があれば登壇していこうと思いますので、また次のイベント登壇にご期待ください! (アーカイブ動画公開されるといいな) We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
はじめに こんにちは、ニフティ株式会社 インフラシステムグループ 佐藤です。 普段の業務では社内のネットワーク運用などを担当しています。 現在、社内の無線ネットワークの電波状況改善のため、無線LANサイトサーベイができるツールの導入を検討しており、NetSpotというツールをトライアルで利用してみたのでご紹介します。 NetSpotとは NetSpotは無線LANサイトサーベイやWiFi分析が行えるツールです。 MacOSやWindowsで利用ができ、必要な要件に応じて無料版やプロ版、エンタープライズ版があります。 今回は無線LANサイトサーベイができるプロ版をトライアルで利用してみました。 NetSpotでやりたいこと 無線不調の原因でよくあるのが電波干渉ですが、干渉源となっている無線ルータを探すのに苦労することがよくあります。NetSpotを使って自分たちで管理していない無線ルーターの場所を特定したいと思っています。 NetSpotの使い方 NetSpotを起動すると下記画面が表示されるので新しい「調査をする」を選択します。 画面が遷移するので下記の項目を入力します。 ・新しいプロジェクトの名前:プロジェクトの名前 ・第1ゾーン名:場所や建物名等 ・ゾーンエリアタイプ:プルダウン形式なので該当するものを選択 ファイルからロードを選択してフロア図をアップロードします。 フロア図が表示されるので2か所選択して、2点間の距離を入力します。 調査に含みたくないSSIDがあれば入力します(今回は何も指定しませんでした) アクティブスキャン(通信速度測定等ができる)の実施確認があるので実施する場合はSSIDを入力します(今回は未実施です) フロア図が表示されるので現在地を選択して無線通信をスキャンを開始します スキャンが完了したらスキャンできた範囲が緑丸で表示されます 一通りスキャンした後にスキャン中止を選択すればスキャン結果が表示されます。 スキャンした範囲内にある無線機器がフロア図に表示されました。 NetSpot使ってみた感想 無事に無線ルータの位置が検出ができました。一部違う部屋の無線ルータも表示されてしまいましたが、検知位置の精度も十分に高く社内の調査でも使えそうでした。特定の無線ルータの電波強度も測定できるので、社内の無線環境改善の一環として引き続き導入を検討したいと思います。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering