TECH PLAY

ニフティ株式会社

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

487

前回の記事で、ニフティでSREとして働く社員に、ニフティでのSREの取り組みと、仕事を進めるにあたっての工夫点などをインタビューを行いました。 今回はインタビューの後編をお届けします。前編はこちらの記事をご覧ください。 【インタビュー】ニフティのSREに聞く!インターネット黎明期から安心・安全を体現してきたニフティが2023年に取り組んでいるSREとは?【SRE前編】 入社5年目のネットワークエンジニアがSREに。 Kさんは自ら希望してSREチームに入ったそうですが、希望理由はなんですか。 Kさん SRE、DevOpsに魅力を感じて希望しました。 具体的にどんなことをやっているんですか。 Kさん 最近は開発チームの生産性を可視化しようとしています。GitHubのログを抽出して、それをLooker Studioを使ってグラフにしてビジュアライズすることで、週次の生産性を計ろうとしています。生産性が低い場合にできるアクションを今検討しています。 SREチーム内でのコミュニケーションについて。 チームで動く上で大事にしていることは何ですか。 Kさん ニフティはハイブリッドワークなので、日によってオフィスにいるメンバーが違います。出社しているメンバーは出来るだけ顔を合わせて会話できるようにしています。 Sさん やっぱりコミュニケーションは大事ですよね。 Aさん そうですね。チームの体制はスクラムなので、スクラムチームのアクティビティ(デイリースクラムやスクラムイベント、レビューなど)を通してメンバーと密にコミュニケーションを取り合っています。それと、施策に対してしっかりとリリースを行うことを意識して進めています。 リモートワークだと直接顔を合わせない日もありますが、コミュニケーションが取りづらかったりすることがありますか。 Aさん 自分はこの会社に勤めて長いのであまり感じないですね。Sさんは入社して1年経ってないですがどうでしょう。社員の顔がわからないとかはありますか。 Sさん 私は入社したばかりなので、顔がわからない人は多いですね(笑)。ただ、前職はフルリモートだったのでコミュニケーションが取りづらいとは感じませんでした。ただ、出社の機会があることで顔を合わせて雑談や会話できるのはとてもいいなと思います。 SREチームのワークライフバランスとは。 休みはとれていますか。 Aさん 有給休暇は自由にとれていて、旅行など長めの休暇もとることもできます。 Aさん アフタヌーンティーに出かけたり、ディズニーにいったり近場の温泉に旅行に出かけたりしています。今年は行動制限もなくなったので、旅行に行きたいですね。 Kさん ライブに行ったり、観劇したりしています。宝塚、劇団四季など歌って踊る系が好きです。あとは映画を観たりして過ごしています。 Sさん 子供がいるので、休みの日は子供と遊ぶことが趣味になっています。最近外を歩けるようになったのでお散歩したり、子供と一緒にあそべる施設などに出かけたりしています。 Aさん お子さんはそろそろディズニーデビューできそうですか。 Sさん まだ早いです(笑)。 ニフティのSREが求めるエンジニアとは。 これからどんなエンジニアの方と一緒に仕事がしたいですか。 Aさん いろんな人とコミュニケーションをとって、自発的に提案ができるエンジニアを望んでいます。色々なチームに対して提案や技術支援を行うのでそういったコミュニケーションが得意な方と一緒に働けると嬉しいです。 Kさん 文化を浸透させる立ち位置なので、Aさんと同じく、コミュニケーションをとって相手の同意を得て進められるような方がいいですね。 Aさん Sさんと私は社会人歴としては同じくらいですよね。チームの中でKさんは年次が若いので、年が近い人に来てほしいなどありますか。 Kさん そんなことはないです。そういうことを気にする会社ではないので。 Sさん SREはいろんなサービスに横断して関わっていくので、コミュニケーションスキルはもちろん、インフラだったりクラウド知識やプログラミングのスキルなど、幅広いスキルを持っている/持ちたいと思っている方に来てほしいです。特にこのスキル!というものはないのですが、様々なスキルの中でも自分の得意なスキル、尖ったスキルを持っていて、そのスキルも他のスキルも上げていきたいという意欲がある方があっているかなと思います。 今回はニフティのSREチームのインタビューの様子をお届けしました。ニフティでは、SREを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
ニフティで推進中の「SRE」とは。 簡単に自己紹介をお願いします Aさん ニフティでSREを推進したいと考え、2020年にSREチームを立ち上げてリーダーをやっています。SRE関連業務のほかに、Webサービスの開発と運用や、サーバーをAWSへマイグレーションなども行っています。 Kさん SREチームに入ってちょうど1年経った5年目社員です。2022年9月まではネットワークエンジニアとして社内のネットワークの刷新などを担当していました。その時の知識を生かしてNIFTY Tech Day、NIFTY Tech Talkなど、YouTubeの配信を伴うイベントのお手伝いをやったりもしつつSREを推進しています。 Sさん 2023年3月に入社したばかりのキャリア社員です。ニフティへ入社する前はSRE業務ではなく、お客様に向けたWebサービスの開発を行っていたのでフィードバックや反応が見えづらい環境でしたが、今は社内メンバーがお客様のような立場で、自身が作ったものに対して喜んでくれたり、良い反応を得られるので新鮮で楽しいです。 SRE、ニフティのSREについて教えてください。 Aさん SREでは信頼性も重要な機能の一部だと捉えます。具体的な仕組みに比べると機能として捉えられないと思いますが、5回に1回買い物が失敗したり、10回に1回違うものが届いちゃうショッピングサイトを使いますか、ということですよね。必ず購入出来て、必ず正しいものが届くということ。それが信頼性です。 Sさん 前職ではSREというポジションがなく、ニフティに来て初めてSREを知ったのですが、ニフティはサービスの品質を高めようとする動きが活発だということが分かって、それはとてもいい文化だと思いました。開発に比べるとないがしろにされがちですが、システムを安定して稼働させる、障害を少なくすることは開発と同じくらい重要です。その重要性を会社全体で認識できるように活動していきたいです。 Aさん SREのアプローチを全社に広めていきたいと思っていますが、十分に浸透しているとはいえないのでアプローチの方法を色々と模索しています。勉強会やワークショップを開いてみたり、社員にまず興味を持ってもらう取り組みを行っています。また、サービス品質を向上させることを目的とした部門横断的なプロジェクトが立ち上がっているのですが、そのプロジェクトにSREチームが関与することで認知を広げていっています。 チームとチームをつなぐのは、これまでに培った技術力と柔軟なコミュニケーション力。 他のチームに入り込んで進めるとおっしゃいましたが、具体的にどのように進めているんですか。 Kさん 自分たちからSREを提案しに行きます Aさん そのチームの一員となるような感じでやっています。タスクを整理するときにSREのタスクを組み込んでやってもらうような感じです。このスプリントではこの機能を修正する、というタスクがあると思いますが、SREのためのタスクも1つは組み込んでもらう。機能開発が8割だとしたら2割くらいはSREのためのアプローチのタスクを入れてもらっています。 SREを提案されたチームの反応はどんな感じですか。 Aさん 普段の業務に追加になるので、やりたいと思ってもできないこともありますね。目指しているのは全員がやっている状態ですが、できそうなチームからお話をしています。業務の多寡などをみて優先順を決めています。 スクラムチームであれば、プロダクトオーナーは企画の社員が多いと思うのですが、企画の社員にSREを理解してもらうためにどんなアプローチを行っていますか。 Aさん 企画へのアプローチはまだ十分にできておらず、今後どんどんやっていきたいですね。企画の部門長などに必要性の説明などもしたいと思っています。 最終的に目指しているのは、企画も開発も信頼性を担保しつつ自分のサービスの成長を判断できる状態です。極端に言うと、品質が悪ければ新機能のリリースよりも品質を高めることを優先するような判断を選択肢に入れていきたいです。 Kさん 僕も同じ意見です。 Aさん 組織がアジャイル組織になっているか、DevOpsを経営層までもが理解しながら進んでいる状態をゴールに描いています。 後編に続きます! 今回はニフティのSREチームのインタビューの様子をお届けしました。続きは後編の記事をご覧ください。 【インタビュー】ニフティのSREはどんな人?【SRE後編】 ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
はじめに ニフティ株式会社の白岩です。ニフティに新卒入社して約5ヶ月が経過しました。 今秋の情報処理安全確保支援士試験を受験することにしました。本記事では、試験制度の簡単な解説と、受験するに至った経緯と合格に向けた勉強法を記載します。 情報処理安全確保支援士試験とは IPA(独立行政法人 情報処理推進機構)が実施する情報処理技術者試験の1つで、情報セキュリティスペシャリスト試験の後継です。 午前Ⅰ試験 試験時間:9:30〜10:20 50分 出題形式:四肢択一 出題数:30問 概要:午前Ⅰ試験は全てのスペシャリスト試験に共通で、応用情報技術者試験の午前問題が出題されます。 午前Ⅱ試験 試験時間:10:50〜11:30 40分 出題形式:四肢択一 出題数:25問 概要:情報セキュリティやコンピュータネットワークに関する問題が重点的に出題されます。 午後試験 試験時間:12:30〜15:00 150分 出題形式:記述式 出題数:全4題から2題を選択 概要:情報セキュリティに関する10ページ程度の文章を読み、設問に回答します。令和4年以前は午後Ⅰと午後Ⅱに分かれていましたが、令和5年以降から纏められました。 合格率:15〜20% 合格基準:全ての試験区分で60%以上 登録制度について 情報処理安全確保支援士は、弁護士や公認会計士などと同列の「士業」にあたります。試験合格後、所定の手続きに従って登録することで情報処理安全確保支援士を名乗れるようになります。 また、少々ややこしいですが「情報処理安全確保支援士試験」は 国家試験 の名称、「情報処理安全確保支援士」は 国家資格 の名称です。 情報処理技術者試験 試験区分一覧(IPAより引用) 情報処理安全確保支援士に登録した場合、資格維持のためには定期講習の受講が必須で、その費用が高額です。初回登録時の費用が約2万円、1年に1回の講習が2万円、3年に1回の講習が8万円、合計すると3年間で約14万円の費用が発生します。 この金額を何の抵抗もなしに支払える財力は今の私にはないので、すぐには登録しない予定です。今後のキャリアで必要になったときに登録を検討したいです。 実は、情報処理安全確保支援士には登録期限がありません。試験合格から20年後、30年後でも登録可能となっています。 また、未登録であっても、試験合格の実績は履歴書などに記載することができます。 ただし、支援士でない状態(未登録または期限切れ)で支援士を名乗ると法に触れるので注意が必要です。 参考: 情報処理安全確保支援士 よくあるご質問(IPA) 受験理由 情報セキュリティに関する知見を深めたい 私は情報系学部出身ですが、情報セキュリティはほとんど学習しませんでした。実務経験もまだないので、正直なところ合格できる自信は全くないです。 しかしながら、情報セキュリティはそれなりに興味のある分野であり、今後の業務に活かせる可能性もあると思い、受験を決めました。 午前Ⅰ試験の免除ができた 令和4年度春期の応用情報技術者試験を受験し、無事に合格できたので午前Ⅰ試験の免除が可能でした。 社内の支援制度が充実していた ニフティには キャリアアップ支援制度 があります。情報処理安全確保支援士試験も資格取得支援制度の対象なので、合格時に報奨金が支給されます。また、書籍購入費用補助制度を利用して参考書の購入ができます。 合格に向けた勉強法 過去問を解いていくうちに、問題の特徴や形式は、難易度は違うものの応用情報技術者試験とあまり変わらないように感じました。そのため、当時と同じ勉強法を取っています。 今回は無関係ですが、スペシャリスト試験の中には論述が出題される区分もあります。その場合は勉強法も変わってくると思います。 過去問をたくさん解く 全ての情報処理技術者試験においてマストです。最低でも過去5年分は浚っておきたいです。 午後試験では、体系的な知識のほかに、10ページ程度の長文を理解する読解力や回答を言語化する力も必要なので、過去問を解いて身につける必要があります。 応用情報技術者試験でも記述問題には苦労しましたが、過去問を繰り返し解くうちにコツを掴みました。スペシャリスト試験は問題文が非常に長いので一題一題が重いですが、過去問を通して慣れていきたいです。 参考書 先述の書籍購入費用補助制度を利用して網羅系の参考書を1冊購入しました。試験日までに一通り読んでおく予定です。 情報セキュリティに関するニュースや時事ネタを知っておく 時事問題が出題される場合があるので、概要を知っておくだけでも有利になると思います。 最近では、令和4年度の試験で、Apache Log4jのゼロデイ脆弱性であるLog4Shell(CVE-2021-45105)が題材となっています。 試験当日の準備をしておく これは試験勉強ではありませんが非常に重要です。 当日までにやるべきこととして、起床時刻と電車の時刻を集合時刻から逆算する、試験当日の持参物をまとめる、試験会場へのアクセス方法を調べる、昼食をどうするか決めるなどが挙げられます。 「乗る電車を間違えた」「試験会場に到着してから受験票がないことに気付いた」など、試験を受けられないという事態だけは絶対に避けなければいけません。 今後について 試験まであと1ヶ月程度ですが、現状では午後試験はまだまだこれからの段階です。午前試験は既に仕上がっているので、午後試験の対策をどれだけできるかによって合否が決まります。 もし今回の試験で合格できた場合、次はネットワークスペシャリスト試験に挑戦したいと考えています。セキュリティとネットワークは関わりが深く、共通する内容が多いので今回の試験勉強も活きてきます。こちらは1年に1度の開催で、合格率が13〜15%程度なのでさらに厳しい試験です。 不合格だった場合は、合格に至らなかった原因をよく考えた上で、半年後に再挑戦したいです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass カジュアル面談も受け付けています! ニフティ株式会社 – Meety
アバター
はじめに こんにちは、会員システムグループの上原です。 本記事ではサービスアカウントを使ったGoogle Apps Script(GAS)とGoogle Cloud BigQueryの連携方法を紹介していきます。 やりたいこと 今回、BigQueryを叩いてとってきたデータをスプレッドシートにまとめる処理を行う、GASスクリプトを改修していきます。 GASでBigQueryサービスを使用すると簡単にBigQueryを叩けますが、その際に実行ユーザーの権限が使用されるため、もしもそのユーザーが退職した時にスクリプトを実行できなくなって困ります。これは特にインストーラブルトリガーで定期実行設定しているようなスクリプトで問題になります (参考: https://note.com/0375/n/n3929ccfca5fc )。 この問題の解決策として、GCPからサービスアカウント(アプリケーション向けのユーザー)を払い出し、GASにその認証情報を使用させます。 これによりサービスアカウントで実行されるようになるので、属人化を排除することができます。 ということで、GCPから払い出したサービスアカウントを使ってGASからBigQueryを叩けるようにしていきます。 やり方 [GCP] サービスアカウントを追加する GCPのIAMと管理でサービスアカウントを開きます サービスアカウントの作成をクリックし、名前や説明を入力します。 作成して続行をクリックします ロールを適用します 以下のロールがあればいいです BigQueryジョブユーザー(roles/bigquery.jobUser) BigQueryデータ閲覧者(roles/bigquery.dataViewer) 完了をクリックします [GCP] サービスアカウントの認証情報を払い出す 再びGCPのIAMと管理でサービスアカウントを開き、作成されたサービスアカウントをクリックします キータブに切り替え、鍵を追加をクリックし新しい鍵を作成をクリックします キーのタイプとしてjsonを選び作成をクリックします このタイミングでjsonが勝手にダウンロードされるはずです。中身を確認すると秘密鍵の内容を見ることができます。 { "type": "service_account", "project_id": "gcp_example_id", "private_key_id": "12345678", "private_key": "-----BEGIN PRIVATE KEY-----\n秘密鍵の中身\n-----END PRIVATE KEY-----\n", "client_email": "daily-gas-bigquery@gcp_example_id.iam.gserviceaccount.com", "client_id": "12345678", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/daily-gas-bigquery%40gcp_example_id.iam.gserviceaccount.com", "universe_domain": "googleapis.com" } この認証情報は再発行できない(作り直す必要がある)かつGASの設定で使うので大切に保管しておきましょう。 [GAS] OAuth用のライブラリを追加する GASでEditorの画面からLibrariesをクリックします。OAuth用のライブラリを追加します。 Librariesをクリックし、Script IDを入力します。 ScriptIDは以下のGitHubレポジトリに書いてあります。2023/09/08現在は1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDFです。 https://github.com/googleworkspace/apps-script-oauth2 Lookupをクリック後Addをクリックします。 VersionやIdentifierはそのままでokです。 [GAS] jsonに書いてある権限情報をScript Propertiesに設定する Project Settingsに移動しScript Propertiesに変数を追加します。 BIGQUERY_CLIENT_EMAILADDRESS サービスアカウントのメールアドレスダウンロードしたjsonのclient_emailに書いてあります BIGQUERY_CLIENT_PRIVATEKEY サービスアカウントの秘密鍵ダウンロードしたjsonのprivate_keyに書いてあります [GAS] BigQueryを叩くための関数を追加する editorに戻りbigquery.gsを作成します。 bigquery.gsに以下を貼り付け、gcp_example_idの箇所を自分のプロジェクトIDに直してください。 function get_bigquery_service() { // https://github.com/googleworkspace/apps-script-oauth2/issues/122#issuecomment-507436277 // BIGQUERY_CLIENT_PRIVATEKEYの\nが\\nとなって改行がうまく反映されないため、\\nを\nにreplaceします const PRIVATE_KEY = PropertiesService.getScriptProperties().getProperty("BIGQUERY_CLIENT_PRIVATEKEY").replace(/\\n/g, '\n'); return OAuth2.createService("bigquery") .setTokenUrl("https://accounts.google.com/o/oauth2/token") .setPrivateKey(PRIVATE_KEY) .setIssuer(PropertiesService.getScriptProperties().getProperty("BIGQUERY_CLIENT_EMAILADDRESS")) .setPropertyStore(PropertiesService.getScriptProperties()) .setScope("https://www.googleapis.com/auth/bigquery"); } function create_request_option(method, payload) { const service = get_bigquery_service(); if (service.hasAccess()) { return { "method": method, "muteHttpExceptions": true, "contentType": "application/json", "payload": JSON.stringify(payload), "headers": { Authorization: "Bearer " + service.getAccessToken() } }; } else { Logger.log(service.getLastError()); } } function create_query(query) { // https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query // TODO: gcp_example_idを書き直してください const url = "https://bigquery.googleapis.com/bigquery/v2/projects/{gcp_example_id}/queries" const payload = { query: query, useLegacySql: false }; const fetch_options = create_request_option("POST", payload) const response = UrlFetchApp.fetch(url, fetch_options) const response_json = JSON.parse(response) Logger.log(response_json) return response_json } function get_query_results(jobId, pageToken) { // https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/getQueryResults // TODO: gcp_example_idを書き直してください。 let url = `https://bigquery.googleapis.com/bigquery/v2/projects/{gcp_example_id}/queries/${jobId}` if (pageToken != null) { url = `${url}?pageToken=${pageToken}` } const payload = {} const fetch_options = create_request_option("POST") const response = UrlFetchApp(url, fetch_options) const response_json = JSON.parse(response) Logger.log(response_json) return response_json } [GAS] コードの修正 BigQueryサービスにアクセスする箇所で新規に作成した関数を呼び出すよう置き換えます。 BigQueryサービスから帰ってくる値とレスポンスは同じはずなので、他に修正は必要ないはずです // BigQueryサービスを使った場合の書き方 // var queryResults = BigQuery.Jobs.query(request, "example-id"); var queryResults = create_query(queryToBigQuery); // BigQueryサービスを使った場合の書き方 //queryResults = BigQuery.Jobs.getQueryResults('example-id', jobId, { // pageToken: queryResults.pageToken //}); queryResults = get_query_results(jobId, queryResults.pageToken); 典型的には以下のようなコードになるはずです // BigQueryへのクエリを書く const querytobigquery = "select * from ~~~~"; // BigQueryにリクエストを送る var queryresults = create_query(querytobigquery); var jobid = queryresults.jobreference.jobid; // クエリが完了するまで待たないとエラーになる可能性があるので完了を待つ var sleeptimems = 500; while (!queryresults.jobcomplete) { utilities.sleep(sleeptimems); sleeptimems *= 2; queryresults = get_query_results(jobid, null); } // クエリの結果からすべてのレコードを取得する var rows = queryresults.rows; while (queryresults.pagetoken) { queryresults = get_query_results(jobid, queryresults.pagetoken); rows = rows.concat(queryresults.rows); } // rowsを処理してスプシに入れる (もしあれば)ServicesからBigQueryを削除します [GAS] 実行してみよう 実行してみる これで自分のアカウントではなくサービスアカウントの権限でBigQueryが叩かれるようになります どういった権限で叩かれているかはGCPのログを確認してみてください これでうまく動くはずですが、うまく動かない箇所があれば、以下を確認してみてください サービスアカウントが作成されているかどうか、足りないロールがないか GASに設定した認証情報が正しいかどうか 最後に 以上、BigQueryをGASからサービスアカウントで叩く方法をまとめてみました。 ネット上にある情報を参考にしても動かなくて困っていたのですが、この記事通りにすれば動くはず…!というのをまとめてみたので、もしお役に立てれば幸いです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
イベント概要 NIFTY Tech Talkは、ニフティ株式会社の社員が主催するトークイベントです。 本イベントでは、ニフティグループの社員が業務を通じて学んだことを発信しています! 第12回目は「スクラム開発の真髄を探る!認定スクラムマスター研修参加者が語る成功のカギ」です。 ニフティの認定スクラムマスターの中から3名が語る回となります。 【6/27(火) 12:00~】スクラム開発の真髄を探る!認定スクラムマスター研修参加者が語る成功のカギを開催します! 【イントロダクション】認定スクラムマスターってなんですか? 発表に入る前に、まずは認定スクラムマスターについて説明いただきました。 資料 【LT1】認定スクラムマスター研修の概要と認定試験について 認定スクラムマスターになってまだ間もないところで、研修や試験を受けて思ったこと、感想など。 これから認定スクラムマスターを目指す方にとって参考になる内容かと思います。 資料 【LT2】スクラムに向かない情シスチームの スクラムマスターが CSMを取得して2年の間に思ったこと 講師からも困難と認定されたものに果敢に挑み、成果を出した猛者のお話し。 スクラム運営の参考になること間違いなし。 資料 【LT3】認定スクラムマスターになった後、A-CSMって取るべき? 認定スクラムマスターの次のステップ、アドバンスド認定スクラムマスターに興味のある方、取得を迷っている方にとくにみて欲しいと思います。 さらに先を目指す方必見の内容となっております。 資料 まとめ 認定スクラムマスターになってまだ間もない方や、スクラムにあまり向いていない業務に当てはめてやっている方、アドバンスドを持ってる熟練者まで幅広いお話しが聞けました。 また、発表後に長めの雑談タイムがありました。各発表での質問と違い、発表者全員から回答したりなどなど本編に劣らずためになる時間になったのではないかと思っております。 アーカイブ(YouTube) 発表資料(Speaker Deck) We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
ニフティ株式会社新卒3年目のRyommです。 ニフティ株式会社とニフティライフスタイル株式会社の合同で、毎週火曜日に CheesySwift / CheesyKotlin という名前でアプリの勉強会を主催しています。 今回は、CheesyKotlinで2回にわたった Compose Animation の勉強会の総仕上げとして行なった  Compose Animation 100本勝負  を特別に公開します! ぜひ、Compose Animationの腕試しにチャレンジしてみてください。 ↓Compose Animation 100本勝負 ↓ https://notion.engineering.nifty.co.jp/posts/cheesykotlin-compose-animation/ We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
はじめに こんにちは、IWSです。 少し前になりますが、5月に社内で行われたLT大会に登壇させていただきました。 実はこのLTにはVRで参加させていただいたのですが、せっかくなので、今回はこのVRでLTをしたときのことについて書いていこうかなと思います。 VR で LTって? こんなのです う〜ん、これはあまりにもかわいいですね…… バーチャルな空間でスライドぱらぱらめくってLTに登壇できたら絶対かわいくてたのしいよな〜と思ったので作りました。(せっかく買ったのにほこり被り気味なVR機材を使ってあげたかったというのもありますが……) 環境 Unityを使って作っていきます。VRChatやClusterにも発表ができるワールドはあるのでそれを使えば簡単なのですが、せっかくなので自分で作って遊んでみたいと思います。 ちなみに環境は以下のとおりです。 Windows10 Home Unity : 2019.4.40f1 SteamVR Plugin Final IK HMD:Vive Cosmos 機能 VRの部分の基本的な機能はSteamVR Pluginを使って作っています。 VRでの移動システムなどが入っているのでぶっちゃけこれを使えば簡単なVRのなにかはすぐ作れたりします。すごい。 なので、これをベースにしつつLTに必要そうな機能を追加して行けばよさそうですね。 やってみましょう。 移動 せっかくのVRなのに棒立ちというのは寂しいので移動は必須でしょう。 SteamVR Pluginを使えばテレポートによる移動なんかは簡単に実装ができます。ただ、そのままでは1人称視点向けの両手だけのモデルになっておりこれだとかわいくありませんし、別視点から見ても何をしているのか分かりづらいです。ですので、こちらで用意したかわいいモデルとテレポートを組み合わせてみましょう。 テレポート用のオブジェクトやスクリプトを読み込んでモデルと組み合わせて…… できました!テレポート移動です! ……あられもない姿になってますね? 現在地からテレポート先までモデルが一歩で移動しようとしてるみたいです。 本当はVRChatのテレポートのような、移動先に向かってモデルが移動→自分の視点をモデルの位置までテレポートさせる。みたいなことをしたかったのですがうまくいってません……。 Unityド初心者には少し難しかったみたいです…… 今は代わりにコントローラーのスティックでとことこ歩くようにしておきましょう。 スライド LTなので当然スライドなりの資料をどう表示して送るかを考える必要がありますね。 まず思いつくのはボタンを押すとスライドが切り替わるタイプでしょうか、これでもいいですがVRなのに普通のプレゼンとあまり変わらないものになってしまうのはつまらないですね……。なにか面白い要素を入れたいところです。 ……と、考えてできたのがこちらです。 豪快にめくります。 ここは紙芝居形式にしてみました。インパクト抜群で動きを取り入れることもできる個人的にお気に入りの部分です。めくったスライドがゴミとして右後ろに溜まっていますがこれはこれで味があるのでいいなと思っています。 かわいいとすべて許される。 カメラ Unityの映像をどうやって共有配信するかも考える必要がありますね。 UnityCaputureというのを使えばUnity内のカメラの映像を仮想カメラとして取れそうなのでこれを使っていきましょう。Unity内で配信用カメラを配置してスクリプトを設定します。 映像を取ることができるようになったらあとはOBSなどで受け取れば配信や画面共有なども簡単にできますね。 ついでに、実際の映像が見れると自分の動きも取りやすくなるのでUnity内で自分の位置から見えるように映像を表示しておきましょう。 正面にディスプレイを置いて先程の映像を出すようにしてみました。これで動きの確認や今どのスライドが見えているかも(ミラーになってるけど)わかりやすくなったと思います。 タイマー 移動やスライドの機能ができて最低限LTはできるようになりました。ここからはオマケ便利機能を作っていきます。 社内LTでは5~7分の登壇時間がありますが、HMDを被った状態だと今何分経ったのかというのが分かりません。なので、バーチャル空間の中にタイマーを出してみましょう。 確認モニターの上にタイマーを、手元にスタート/ストップのボタンを置いてみました。 青がタイマースタート/ストップ、赤がタイマーリセットになっています。 しっかり動きはするのですが、ちょっと触れただけで止まったりリセットされたりしてしまう繊細肌になってしまったのは内緒です……。 コメント LT中はSLackが実況チャンネルとして動いているのですが、HMDを被っているとSlackが見れず反応が全くわからないのが少し寂しく感じました。 なんとか反応を見れるようにしたいな〜と思ったのでコメント欄を作ってみました。   ……はい、にせコメント欄です。 Slackの実況チャンネルからコメントを持ってくるのは色々あって難しかったため、流れているのは自分で用意したテンション爆アゲコメントです。LT中に視界に入ると「ふふっ……w」となるので作ってよかったですね。 いつか本物のコメント欄に進化するときがくるかも……? 全体 色々作ってみましたが全体はこのような感じになっています。 スライドの左側を基本立ち位置としています。正面にはタイマーのボタンが、向かい側にはカメラやタイマー、コメント欄などが置いてあるといった感じですね。 そして床には……おもちゃが散らかってます。ときおり投げて遊んだり……。 使ってみてどうだったか VRを使ったLTをいままで2回やったのですが、どちらもとても楽しかったです。見ている人からも好評でした。 オンラインだと難しい身振り手振りもVRであればできますし、そもそもこんなにかわいい姿でLTができるのに楽しくないわけがないですね!! 今はまだスライドをめくるぐらいしかVR特有の動きがありませんが、他にもサービスアイコンをならべて動かしてリアルタイムで構成図を変えて説明するみたいな事もできたら面白そうですし、いろいろな可能性がありそうです。 最後に というわけでVRでLTをしたときのお話をさせていただきました。コード実装なんかの話はできませんでしたが、この記事でVR LTに興味を持っていただけたら幸いです。 ちなみにこのVRLTの今後ですが、実は「HaritoraX ワイヤレス」というフルトラッキング機材を購入しました。なので、次回またLTをするときはフルトラッキングで動けるようにした状態でやりたいですね!フルトラッキングで動くのも楽しみです! クレジット LT、およびブログの執筆においてこちらのモデルを使わせていただきました。 オリジナル3Dモデル「ミーシェ」 – ポンデロニウム研究所 オリジナル3Dモデル「桔梗」 – ポンデロニウム研究所 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
はじめに こんにちは。新卒4年目の大里です。 7/11に行われたレバレジーズ x ココナラ x ニフティ 合同フロントエンド勉強会に参加しましたので感想を書きます。外部の勉強会に初めての参加と発表だったため、勉強会に参加したことがない方、発表したことがない方の参考になれば幸いです。 レバレジーズ x ココナラ x ニフティ 合同フロントエンド勉強会とは この勉強会は名前の通りレバレジーズ株式会社様、株式会社ココナラ様、ニフティ株式会社の社員がフロントエンド開発について自由なテーマでLTをするオンラインの勉強会でした。詳細は connpass を参照してください。 なぜ勉強会に参加&発表しようと思ったか 社外のエンジニアの勉強会の雰囲気をつかみたかった 独学で本を読むなどをしてデザインを少し勉強してきたのですが、独学以外の勉強方法として社外の勉強会に参加することの効果や意義を知りたくて参加しました。同僚から社外の勉強会に参加した話を聞いてみて面白そうと思ったのですが、どの点がどう面白そうかが自分で腑に落ちておらず実際に体験してみて違いを感じ取ろうと思いました。 この勉強会に参加したのは、他の勉強会よりも気楽に参加できるように感じたためです。企画者が社内の勉強会と同じように気楽に発表ができる雰囲気になるよう工夫してくださりました。おかげさまで気分転換初めて社外勉強会に参加や発表するときにハードルが高くないように感じ、この勉強会に参加しました。 通常業務とは別の業務を並行で実行したかった 当時、事業案件や運用などの通常業務がうまくいかないことが多くモチベーションが下がっておりましたが、通常業務とは別の業務をしてみることでモチベーションが上がる可能性があると仮説を立てました。通常業務のみを遂行していた場合、通常業務がうまくいかなかった時にマイナスの気持ちになることが多く、このままの状態が続くとモチベーションの低下になりうると考えました。しかし、別の業務も行った場合にプラスのことが起きていればモチベーションが安定する可能性があると思いました。この仮説が成立するのであれば、今後の業務でモチベーションを保てるように、通常業務とは別の業務を遂行することを意識していきたいという意図がありました。 参加した感想 良かったこと 他企業の実際の業務で、どのように技術を使っているかを知ることができた 独学と社外の勉強会の違いを大きく感じられた点でした。担当業務ではバックエンドの業務が中心で、少しフロントエンド側でデザインの修正をする程度でした。勉強会ではフロントエンドのパフォーマンスの改善など、業務で触れたことのない分野で他社がどれだけ工夫をしてきたかを知ることができました。デザインのみを独学していた時よりも、フロントエンドに対する視野が広がったように思います。 事業案件や運用などの通常業務とは別軸の業務をして気分転換になった 勉強会の準備の際は自分の責任で自分の好きなように発表内容を考えられることや締め切りに追われているときなど、学生の時の文化祭の前準備や研究のデモの準備に近い状況があったため楽しかったです。通常業務の中でプレゼンテーションをする機会はあまりないため、普段はあまり使わないけれど社会人として必要なスキルについて考えるきっかけになりました。通常業務をする上であまり意識できていなかったため、新鮮な気持ちになりました。 社外勉強会の雰囲気が分かって安心した 勉強会の準備をする時間はどういった発表をすればよいか分からず不安な気持ちもありました。しかし、勉強会で発表したり他の人の発表を聞いてみたりすることで社外の勉強会の雰囲気が少し分かった気がします。そのため勉強会の雰囲気を知らなかった今回の発表準備の不安よりは、今後の発表を準備するときの不安は軽くなると思いました。 他企業のエンジニアの話すことが想定したよりも楽しかった 就活時代に様々な企業で働いている方とお話しましたが、自分が働きだしてから他の企業の方とお話をすると解像度が高くなることを実感できました。フロントエンドの勉強会でしたが、各企業のプロジェクトの進め方や使用する言語の選定方法など、各企業の業務の進め方をお伺いすることができて楽しかったです。社内で働いていて知ることができなかった他企業の働き方を知ることができたため、自分のキャリアを見つめ直すきっかけにもなりました。 反省点 勉強会の準備を計画的にできず体力的にきつかった 理想は業務時間内に勉強会の準備の時間を取って通常業務と進められることでしたが、計画性がなく残業時間を使って勉強会の準備をしてしまいました。残業して勉強会の準備をするのは体力的に厳しかったため、通常業務とのバランスのとり方が今後重要になってくると思いました。 まとめ 初めて社外の勉強会に参加してみましたが、他社の業務や開発で気を付けていることを知れたことが新卒からニフティに入ってきた身として、とても新鮮でした。想定していた社外勉強会のメリットより多くのメリットがあることが実感できてよかったです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
はじめに こんにちは。会員システムグループの渡邊です。 Google Analyticsのユニバーサル アナリティクス(UA)が2023年7月1日をもってサポート終了した影響で、Googleアナリティクス4(GA4)への移行とUAと連携していたBIツールの変更が必要になりました。 移行後のBIツールとして採用したLooker StudioとGA4の連携方法と、期間別にユニークユーザー(UU)を出しているときに発生したハマりポイントをまとめました。 やりたいこと GA4に蓄積しているUU数を期間別(月、週、日)に分けてグラフで見れるようにしたい 準備 Looker Studioでレポートを作成する データに接続でGoogle アナリティクスを選択 Googleアカウントに連携されているGAのアカウントが表示されるので、期間別に分けたい情報を持っているアカウントを選択する これで準備完了です。 グラフで見れるようにする 月別 グラフを追加 を押し、縦棒グラフを選択する 作成したグラフを選択し、設定を以下のように変更する 設定 ディメンション 月 指標 アクティブ ユーザー数 並び替え 月 デフォルトの日付範囲 カスタム(今年) 週別 ハマりポイント デフォルトの設定では集計対象の週の最大値を取るようになっているため、週単位の集計はGA4の値と合致しません。 実際には週の終わりの値を取るのが正しいので、週の集計期間を週の終わりである日曜日に指定するフィルターを追加することで対応しました。 下の画像のようにフィルターを設定しないと差が生じることがわかります。 設定 ディメンション ISO年のISO週 週 というディメンションでも同じ値になるが、1年における何周目という表示になるので分かりづらい 指標 7日間のアクティブ ユーザー数 並び替え ISO年のISO週 フィルター 一致条件→曜日→次に等しい→1 週の終わりである日曜日(1) 日別 設定 ディメンション 日付 指標 1日のアクティブ ユーザー 並び替え 日付 デフォルトの日付範囲 カスタム(今年) これで期間別のグラフは完成です。 まとめ GA4は具体的な集計方法が公開されていないので、GA4に表示されている値がどの項目を見ているかを探り当てるのに時間がかかりました。 GA4とLooker Studioを連携すると GA4で持っている細かいデータ を見ることができるので、分析の幅が広がりますが、多機能なので慣れるまでには時間がかかると思いました。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに インフラシステムグループ ISPオペレーションサブチームの藤川です。 ニフティが皆様の目に触れる際にISP(Internet Service Provider)と呼ばれる機会も減ってきて少し寂しいところもありますが、本業は回線提供であると主張します。 総務省のレポート “ https://www.soumu.go.jp/main_content/000861552.pdf ” でもあるとおり、インターネットのトラフィックは年々増え続け、それはインターネットで出来ることが年々広がってきた軌跡ですね。 私が所属するISPオペレーションの業務はそんなインターネット回線が日々快適に使えるよう関係各方面と調整を続ける仕事です。 高トラフィックイベントとは 回線運用で頭を悩ますのはリアル世界やインターネット界隈で発生するイベントがきっかけで発生する一時的な高トラフィックです。 たとえば台風・地震などの災害が発生したときの情報収集や安否確認、たとえばスポーツの世界大会やボクシングのタイトル戦など優秀な日本人選手が活躍する試合、たとえば参加者が多い覇権ゲームの大規模アップデート、たとえば皆さんがお使いのパソコンのOS定例アップデートなどにあたると一斉に通信をしますので全体の通信量は膨大な変化となります。 みなさまもインターネットを使っていて「今日は重いな」とか、「1秒でも早くダウンロード終わらせて新しいゲームを始めたいのになかなかDL出来ない」など、日によって回線が遅いことを感じたことは無いでしょうか?そういったことを私たちは高トラフィックイベントと呼んでいます。 これに備えるために国内では総務省の音頭でCONECTという協議会活動 “ https://www.soumu.go.jp/menu_seisaku/ictseisaku/conect/index.html ” があったり、弊社でもユーザーサポート・サービス企画・回線運用の各チームで情報のキャッチアップと事前の対策検討を進めています。 ゲームのアップデートを予測する 高トラフィックイベントの対応に忙殺させられる中で、ふと過去の履歴を振り返るとアップデートには規則性があるように感じました。 従来、定期的に高トラフィックが発生してしまう対象として有名なOSのアップデートは提供元が年間スケジュールを予告してくださるので助かっていますが、ゲームのアップデートは気づいたら提供が始まっていて当日になって慌てて対応する認識でした。 そういうことで、影響が大きいゲームをいくつかピックアップして日時を確認すると、だいたい3か月周期でメジャーアップデートと呼ばれる大容量ファイルのダウンロードがあり、その合間に繰り返しマイナーアップデートがありました。 詳細に見てみましょう、、、、 ゲーム1の場合 とあるゲームのバージョン番号を時系列にしたのが図です。すごく一直線ですね。時々ある段差も気になります。すべてのファイルサイズを記録できていればよかったのですが、直近数件のみです。全体の角度が一定と言うことは、メジャーアップデートは一定間隔で実施されていることになります。 グラフで確認するのは良くないようですので、諦めて表で確認します。 このように俯瞰すると3か月おきにメジャーアップデートがあり、その間はばらつきがあるものの、平均2週間おきにマイナーアップデートを提供しているようです。また、マイナーアップデートは火曜、メジャーアップデートは週末が多い様でした。 前後のファイルサイズから想像すると、ばらつきの原因はスケジュール遅延でしょうか。お疲れさまです。 こちらのゲームのマイナーアップデートはファイルサイズが小さい事が多く安心ですが、メジャーアップデートは数GBのサイズがあります。そのうえ、このゲームはお子様から大人まで幅広い年齢層に愛されていてトラフィックインパクトが大きいです。こういう時こそ快適に利用して頂きたいから非常に頑張りがいがあります。 ゲーム2の場合 また違うゲームを確認します。 とあるメジャータイトルのアップデート日時となりますが、年1回のメジャーアップデートに加え、マイナーアップデートが定期的にあります。日付はバラバラに見えますが、右欄を見ると6週間隔で水曜日にリリースしていることがわかります。 このゲームはファイルサイズが毎回10GB前後と大きいから大変です。 おわりに このように、世の中で大勢の方に愛されるOSやゲームは、ある程度各社のポリシーに従って提供されていることがわかってきました。 少し前にサスティナブルと言う言葉が流行っておりましたが、持続的にリリースをしてユーザーの期待を裏切らず、サービスを維持する実績には脱帽する限りです。きっとこのような開発を実行するためにアジャイル開発というものが重視されているのでしょう。 使う人のニーズが無ければ必要とされない通信インフラですのでアップデートで必要とされるのは本望ですが、提供側にはサイズ軽減を、ユーザーの方々には混雑していない時間帯にダウンロードして頂くと、中の私たちがちょっとだけ幸せになれます。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass カジュアル面談も受け付けています! ニフティ株式会社 – Meety
アバター
はじめに こんにちは。いかりがわです。 普段はニフティトップページの開発運用を行っています。 このプロダクトの裏側ではGoで記述されたLambda関数がいくつか動いています。 公式からLambda関数についてメールが届きました。どうやらLambda関数のGoランタイムサポートが2023/12/31にサポート終了するらしいです。 お客様の AWS アカウントに現在 Go 1.x ランタイムを使用する 1 つ以上の Lambda 関数があることを確認しましたので、ご連絡いたします。 Amazon Linux AMI のメンテナンスサポートが 2023 年 12 月 31 日に終了するのに合わせて、AWS Lambda での Go 1.x ランタイムのサポートを終了します [1]。 Lambda は、provided.al2 ランタイムを使用して Go プログラミング言語を引き続きサポートします。 provided.al2 ランタイムを使用すると、AWS Graviton2 プロセッサのサポートや、より小さなデプロイパッケージとより高速な関数呼び出しパスによる効率的な実装など、go1.x ランタイムに比べていくつかの利点があります。 詳細については、ブログ記事 [2] を参照してください。 Goのランタイムは Amazon Linux AMIに基づいています。Amazon Linux AMIのサポートが 2023/12/31に終了するに伴い、Goのランタイムもサポート終了となるようです。 Goのランタイムで動作しているLambda関数は、ランタイムを provided.al2 (Amazon Linux 2 AMIベースのカスタムランタイム)に移行する必要があります。 何故Amazon Linux 2 AMIでGoのランタイムをサポートしてくれなかったんだ。。。。 AWS公式からの見解としては以下です。 Go は、他のマネージドランタイムとは異なる方法で実装されています。Go はネイティブコードにコンパイルされるため、Lambda は Go をカスタムランタイムとして扱います。 provided.al2 ランタイムを使用して Go 関数を Lambda にデプロイすることをお勧めします。 Go による Lambda 関数の構築 – AWS Lambda つまり、「コンパイル後はネイティブコードになるんだからわざわざGoのランタイムとして用意する必要ないやろ」と言うことです。 なので今回は、サポート終了してしまう go1.x のランタイムから provided.al2 のカスタムランタイムに変更していく手順をまとめていきます。 前提 Lambda関数をTerraformで構築するためのディレクトリ構成は以下のようになっています。 . ├── lambda │ ├── archive // 圧縮後のファイルを保存するディレクトリ │ ├── build // バイナリを保存するディレクトリ │ └── cmd // goのワーキングディレクトリ │ ├── go.mod │ ├── go.sum │ └── main.go └── main.tf また、Lambda関数の中で動いているコードは以下のようになっています。 package main import ( "context" "fmt" "github.com/aws/aws-lambda-go/lambda" ) type MyEvent struct { Name string `json:"name"` } func HandleRequest(ctx context.Context, name MyEvent) (string, error) { return fmt.Sprintf("Hello %s!", name.Name), nil } func main() { lambda.Start(HandleRequest) } 変更してみる aws_lambda_functionのruntime ランタイムをgo1.xからprovided.al2に変更します。 前述の通り、コンパイル後はネイティブコードになるため、ランタイムはAmazon Linux 2 AMIベースのカスタムランタイムを指定します。 resource "aws_lambda_function" "lambda" { function_name = "go-lambda-sample" filename = "./lambda/archive/sample.zip" role = aws_iam_role.lambda_role.arn handler = "sample" - runtime = "go1.x" // 変更前 + runtime = "provided.al2" // 変更後 source_code_hash = data.archive_file.lambda.output_base64sha256 } ビルド後のファイル名 現状のビルド周りのコードは以下のようになっています。 おそらく、TerraformでGoのLambdaを構築する際の一般的な方法だと思います。 resource "null_resource" "default" { triggers = { always_run = timestamp() } provisioner "local-exec" { command = "cd ./lambda/cmd/ && GOOS=linux GOARCH=amd64 go build -o ../build/main main.go" } } data "archive_file" "lambda" { type = "zip" source_file = "./lambda/build/main" output_path = "./lambda/archive/sample.zip" depends_on = [null_resource.default] } 今回は、 go build の部分を変更します。また、変更後に圧縮するため、圧縮元ファイルも変更します。 カスタムランタイムでは、実行ファイル名は bootstrap である必要があります。なので、 go build は以下のようになります。 cd ./lambda/cmd/ && GOOS=linux GOARCH=amd64 go build -o ../build/main main.go ↓ cd ./lambda/cmd/ && GOOS=linux GOARCH=amd64 go build -o ../build/bootstrap main.go 圧縮元ファイルも bootstrap に変更します。 data "archive_file" "lambda" { type = "zip" source_file = "./lambda/build/bootstrap" output_path = "./lambda/archive/sample.zip" depends_on = [null_resource.default] } 確認 実際にコンソールから確認してみます! ランタイムがAmazon Linux 2 AMIベースのカスタムランタイムになっていることが確認できます! テストでお試し実行してみても問題なく動作することが確認できます! 意外と簡単にGoランタイムからAmazon Linux 2 AMIベースのカスタムランタイムに移行できることがわかりました。 急いで移行する必要はないですが、簡単に移行できるので早めに移行することをお勧めします! 注意:コールドスタートにかかる時間も請求に含まれる 冒頭のメールに以下のような内容が記述されています。 Lambda の請求には、go1.x ランタイムと provided.al2 ランタイムとの間に違いがあります。 go1.x ランタイムでは、Lambda は関数の初期化 (コールドスタート) に費やされた時間を請求しませんが、provided.al2 ランタイムでは、Lambda は請求される関数実行時間に関数の初期化時間を含めます。 Go 関数は通常非常に迅速に初期化され、Lambda は複数の関数呼び出しに関数実行環境を再利用することで初期化の回数を減らすため、実際には Lambda 請求額の違いはごくわずかです。 カスタムランタイムに変更すると、コールドスタートにかかる時間も請求に含まれるため多少請求額に変化があるかもしれません。 GitHub サンプルコードはこちらに公開しています。 https://github.com/k0825/go-lambda-al2-sample   We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も常時受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
はじめに こんにちは、ニフティの佐々木です。 みなさんは、 Notion は好きですか?NotionではUIベースで様々なことを実現できるので便利ですよね。 個人的にも最近はドキュメントを書くだけでなく個人的なタスク管理としてもガッツリ使っているので、無くてはならない存在だなと感じます。 今回はNotionの機能の一つである NotionDB を用いて、スクラム開発で使用するSBIとPBIのカンバンボードを作りながら、あれやこれやの欲しい機能を無理やり自動管理で実現してしまおう!という記事になります。 この記事の内容 NotionDBを用いたカンバンボード自動化方法 ※ なお、この記事はNotionとスクラム開発の基本的な知識を既に持っている読者を対象にしています。 準備 前提条件 スクラムのカンバンボードで使用するSBI・PBIの管理といっても色々あるので、ここでは以下の条件で考えてみます。 スプリント期間(2週間など一定の期間)ごとにPBI・SBIを取る SBIタスクは必ずPBIに紐づけられている必要がある SBIにはタスクの見積もりとしてポイントを振る スプリント期間中はSBIのタスクの進捗状況に合わせてステータスを変更する また、基本的なカンバンボード以外に、自動化で実現したいことを以下としてみます。 PBI側のDBからSBIの情報をまとめて集計したい 完了したSBIの消化ポイント数 着手中のPBIの達成率 スプリント期間が変わったり、進めているタスクが取り下げになったり、といった急な状況にも柔軟に対応したい SBIの情報を元にPBIのスプリント期間を自動連携 SBIの情報を元にPBIのステータスを自動連携 PBI・SBIの作成 まずは以下のようなNotionDBを3つ用意します PBI管理用DB SBI管理用DB スプリント期間管理用DB 日付プロパティを追加し期間を追加します。 次に、カンバンボードとして扱うためのSBIのステータスを、以下のように4種類定義してみます。 未着手 保留 進行中 完了 連携方法 NotionDBには「 リレーションとロールアップ 」というDB間の連携に便利な機能があるので、基本的にはこれを使っていきます。詳細はNotionの ドキュメント をご参考にしてください。 PBIとSBIのタスクを連携してみる まずは、スプリントごとに着手するSBIの情報を知りたいので「SBI」と「スプリント期間」のDBをリレーションで紐づけます。 同様に、タスクの紐づけを行うためにSBIとPBIにもリレーションを貼っておきます。双方向でリレーションを貼っておくとPBI側のDBからも操作できるのでいい感じです。 最低限のカンバンボードとしては機能しますが、更に自動化するために以下を行いました。 SBIのポイントをPBIで合算してみる PBIに紐づくSBIのポイントを集計し、PBIごとの達成率を表示させます。 以下のように、SBIのDBにタスクに対するポイントの見積もりを入れるプロパティを追加し数値を入れます。 ここまででSBIのポイント算出はできましたが、PBI側のポイントはまだ分かりません。そこでSBIのポイントをPBI側で集計できるようにしてみます。 PBIのDBでロールアップを追加し、SBIのDBをリレーションとして選択します。さらに、ロールアップ内で見積もりをプロパティとして指定し、計算から合計を選択すれば完了です。 PBIの完了割合を算出してみる PBIのポイントの算出は出来ましたが、これだと全体のポイントの母数がわかるだけなので、今どのくらいSBIが進んでいるのかといった進捗具合は何も分かりません。 ここでは無理やりSBIのステータスをロールアップで個別に取得し、PBIの完了割合を算出しようと思います。 まずは、SBIのDBにポイント算出用の関数プロパティを2つ追加します ポイント算出用(合計) if(prop("ステータス") != "取り下げ", prop("見積もり"), 0) ポイント算出用(完了) if(prop("ステータス") == "完了", prop("見積もり"), 0) PBIでは以下のように、SBIで定義した値のロールアップを追加します。 ポイント(全体) ポイント(完了) さらに、PBI側でポイントの完了割合を可視化してみます。 参考までにコードは以下のようにしてみました。関数プロパティを2つ追加しています。 ポイント計算用 prop("ポイント(完了)") / prop("ポイント(全体)") 完了割合 slice("▓▓▓▓▓▓▓▓▓▓", 0, round(prop("ポイント計算用") * 10)) + slice("░░░░░░░░░░", 0, 10 - round(prop("ポイント計算用") * 10)) + " " + format(round(prop("ポイント計算用") * 100)) + "%" + "(" + format(prop("ポイント(完了)")) + "/" + format(prop("ポイント(全体)")) + "pt)" PBI側でスプリントを管理する ここまでの操作で既にSBIでは、以下のようにスプリント期間でフィルターを行いどのタスクをどのスプリント期間内で行うのか、ということが一目で分かるようになったはずです。 とはいえ、似たようなビューがたくさんある場合、スプリント期間が変わる度にフィルターをわざわざ張り替えるは面倒です。それを避けるために、まずは現在のスプリント期間を算出できるようにします。 スプリント期間のDBに、以下のような3つの関数プロパティを追加します。 開始日 start(prop("期間")) 終了日 end(prop("期間")) 現在のスプリントフラグ if(dateBetween(prop("終了日"), now(), "hours") > -24 and dateBetween(prop("開始日"), now(), "hours") < 0, true, false) SBIと連携させるため、SBIのDB以下のようなプロパティを追加します。 現行スプリント(ロールアップ) リレーション:スプリント プロパティ:現在のスプリントフラグ 計算:オリジナルを表示 現行スプリント(SBI) contains(prop("現行スプリント(ロールアップ)"), "Yes") すると以下のようになるはずです。 これで、今現在の日時を比較して現在のスプリントをフィルターできるようになりました。 ですが、SBIに紐づけたスプリント期間の情報をPBIへは何も渡していないので、PBIのみで進捗を把握したい場合などでは不便です。そこでスプリント期間もPBI、SBI間で自動連携できるように、PBIでロールアップを2つ追加します。 スプリント(PBI) リレーション:SBI プロパティ:スプリント 計算:オリジナルを表示する 現行スプリント(PBI) リレーション:SBI プロパティ:現行スプリント(SBI) 計算:オリジナルを表示する これで、PBI側のDBでもスプリント期間を指定してフィルターできるようになりました。 SBIとPBIのステタータス自動連携 最後にこの記事の本題でもある、「SBIとPBIのステータスを自動連携する方法」について考えてみます。 ここまでの操作で、SBIのDBではステータスを管理できているので、ロールアップなどを用いてPBI側とステータスも連携させてしまえば良さそうです。 ということで、まずはステータスを取得するためのロールアップをPBIのDBに追加します。 ステータス(ロールアップ) リレーション:SBI プロパティ:ステータス 計算:オリジナルを表示する これで、SBI側のステータスを全て取得することができました。 ただこの状態だと1つのPBIに複数のSBIが紐付けられている場合は上手くフィルターできないので、どれか一つのステータスに絞る必要がありそうです。 そこで、ステータスを自動算出するための関数プロパティを追加します。 PBIで管理するステータスは、一旦SBIと同じ4種類とします。 ステータス(自動連携) if(or(contains(prop("ステータス(ロールアップ)"), "着手中"), and(contains(prop("ステータス(ロールアップ)"), "完了"), contains(prop("ステータス(ロールアップ)"), "未着手"))), " 着手中", if(and(contains(prop("ステータス(ロールアップ)"), "完了"), not contains(prop("ステータス(ロールアップ)"), "未着手")), if(not contains(prop("ステータス(ロールアップ)"), "保留"), " 完了", " 保留"), " 未着手")) 残念ながらNotionの関数ではswitch文などが使えないので、無理やりこのようなif文で算出しました。 式のみだと分かりづらいので、関数式の説明を以下に書いておきます。このあたりはプロジェクトごと管理方法に合わせてカスタマイズすると良さそうです。 着手中 紐づくSBIのうち1つでも「着手中」が存在していれば反映される もしくは「着手中」が存在しない場合でも、紐づくSBIに一部でも「完了」が存在していれば反映される 完了 紐づくSBIが全て「完了」になっていれば反映される 保留 紐づくSBIに「未着手」「着手中」が存在せず、他全てが「完了」「保留」である場合のみに反映される 未着手 紐づくSBIが全て「未着手」、もしくは紐づくSBIが存在しない場合に反映される 成果物 色々詰め込んでしまいましたが、これで「ステータス」「スプリント」「ポイント」が自動連携されたカンバンボードの作成が完了したと思います。 この状態でPBIのボードビューから「ステータス(自動連携)」でグループ化を行うと、以下のような表示になります。 まとめ 今回は、NotionDBを用いたカンバンボードの自動連携について紹介しました。 これはカンバンボードの作成に限らずですが、実際にやってみた感想として、NotionDBを用いた改善では「試しに触ってみて少しづつ理解しながら改善していく」という形を取るのが良いのかなと感じました。 実際、業務で取り組む際には「こういう機能があったらいいな〜」といった疑問や、開発メンバーの意見なども取り入れながら少しづつカンバンボードに反映させていく…という手法を取っていました。結果的に、遠回りにはなりましたがNotion自体の機能や自動化の勘所など、多くの学びが得られたなと思います。 ただし、NotionDBにはリレーションを追加すると動作が重くなってしまう…という問題があるため、実際の改善でもこれ大きくぶち当たりました…。もし、自動化を試すのであれば「チームメンバーのPCのスペックとも相談しながらあまり機能を詰め込みすぎないようする」といった工夫が必要になってくるかと思います! カンバンボードに限らず、NotionDBを使って何かを自動化をするための参考に少しでもなれば嬉しいです。 参考記事 https://www.notion.so/product We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに はじめまして。ニフティでインフラエンジニアをしている横山です。 自身が担当しているシステムの一部にVDI環境があり移動ユーザープロファイルの機能を利用しているのですが業務効率の低下につながる課題を抱えております。そんな中、課題解決につながりそうなソリューションとしてFSLogixに興味を持ちまして実際に利用してみました。 用語について VDIとは? 仮想デスクトップ(Virtual Desktop Infrastructure)を指します。ユーザーが利用するPC端末のデスクトップ環境をサーバ上で一元管理する仕組みを指します。従来の環境と比べてセキュリティ対策やコスト削減などのメリットがあります。 ユーザプロファイルとは? ユーザ個人のファイルや設定などが保存されたもので、下記の例ではWindowsクライアントへアクセスした際にYokoyamaというユーザでアクセスすると、Yokoyamaフォルダをユーザプロファイルとして利用することができます。このフォルダ群をユーザプロファイルと呼んでいます。 移動ユーザープロファイルとは? 複数のコンピューター間でユーザの設定やカスタマイズ、個人データを移動させるための機能です。VDI環境では仮想マシン上でユーザーの仮想デスクトップが実行されますが、ユーザが異なるコンピューターで作業する際に一貫性のある環境と個人設定を提供するためこの機能を用います。一般的にフォルダリダイレクトと組み合わせて使うことが多いかと思います。 抱えている課題 移動ユーザープロファイルは端末へログインする際、ファイルサーバに格納されているユーザプロファイルを端末にダウンロードしますが、ダウンロードが完全に終わるまでログインが完了することはありません。そのため大多数のユーザが同タイミングで一斉にログインしたり、ファイルサーバ側にサイズの大きなファイル等がある場合にサーバへの負荷が集中してしまい、VDI端末を利用するまでにユーザーはかなり待たさせることになります。 こうしたI/O集中などのサーバへの負荷によりログインストームと呼ばれる状態が起きることがあり、業務のレスポンス低下を招いていました。何か手立てはないか考えていたところFSLogixというソリューションがあることを知りました。 FSLogixについて FSLogixは仮想デスクトップ環境や仮想アプリケーション環境において、ユーザのプロファイルデータとアプリケーションデータを効率的に管理するためのソフトウェアです。今回はFSLogixの提供している機能の一つであるプロファイルコンテナについて触れていきます。 プロファイルコンテナはユーザプロファイルをコンテナ化しマウントする仕組みになります。コンテナ化されたファイル(VHDX)はファイルサーバ等のストレージへ保存することができ、ユーザのログイン時においては該当するVHDXファイルをマウントして利用する形になります。 ※コンテナ化 = アプリケーションやサービスを実行するための環境をパッケージ化したものです。 ファイルサーバから端末に対してファイルのダウンロードを行う移動ユーザプロファイルに対して、ユーザプロファイルを直接マウントするFSLogixでは後者のほうがかなりの 速度向上 を見込めるのではないかということで実際に検証してみることにしました。 検証内容 FSLogix(Profile Container)利用と従来の移動ユーザープロファイル利用時のパターンにおいて、ログイン/ログオフの速度やアクセス先のファイルサーバへの負荷等を検証してみます。 検証環境 役割 OS スペック(CPU / メモリ / ディスク) 台数 VDI端末 Windows10 4CPU / 16GB / 80GB 10 ファイルサーバ Windows Server 2022 2CPU / 4GB / 80GB 1 Active Directory Windows Server 2022 2CPU / 4GB / 80GB 1 検証方法 ActiveDirectory上に移動プロファイルを利用/FSLogixを利用するための接続するためのユーザをそれぞれ10アカウントずつ作成する。 各アカウントのプロファイルデータには5GB程度のダミーファイルをあらかじめ配置する。 それぞれのパターンの10アカウントで同じタイミングでのVDIクライアント接続を行う。 検証結果 検証パターン ログイン/ログオフ サーバ負荷状況 FSLogix(プロファイルコンテナ) 4秒前後/3秒前後 CPU:3%上昇 メモリ:2~3%上昇 移動ユーザプロファイル 10秒前後/3秒前後 CPU:5%上昇 メモリ:5%程度上昇 ファイルサーバへの負荷はそこまで変わらなかったものの、FSLogixを利用することでクライアントへのログイン速度が格段に速くなりました。上述した課題の解決するための手段としてとても実用性を感じる結果になったかと思います。 所感 検証を踏まえて、FSLogixはインストールや設定についても簡単で導入の敷居はとても低いのではないかと感じました。また、今回細かな設定までは触れませんでしたがプロファイルコンテナの設定で1ユーザあたりが作成できるファイルサイズに制限をかけたり、ユーザープロファイルの格納先を複数指定することが設定一つで行える為、管理者にとってもシンプルで扱いやすいように思えました。今後も提供機能や詳細設定について利用者だけではなく管理者の運用が今以上に楽になるようなものがないかを引き続き調べていきたいと思います。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
こちらは2023年7月に投稿された記事です。 2023年9月以降、ZapierのTwitter連携機能は使用できなくなりましたのでご注意ください。 https://help.zapier.com/hc/en-us/articles/18657531069965 はじめに こんにちは。ニフティ株式会社の並木です。 今回は、Zapierを使ってRSSフィードの更新をトリガーにしたTwitterへの自動投稿機能を作ってみましたので、その方法について紹介いたします。 背景 ブログとTwitterの連携機能が元々用意されていたのですが、そちらが使用できなくなってしまい、ある時期からブログの更新情報をTwitterに手動で投稿していました。 しかし、手作業だとミスする可能性がある&手間もかかるため、RSSフィードの更新をトリガーにして自動化できないかという話になり、Zapierを使って自動化することになりました。 Zapierとは? Zapierとは、複数のアプリ連携し、タスクを自動化するツールです。 今回自動化したいタスクは以下の通りです。 ①ブログの更新を検知したい ②Twitter投稿用のタグを作りたい  ・ブログについているタグと同じタグをTwitterでも付けたい  ・ブログについているタグに半角スペースが入っている場合、Twitterでは取り除きたい ③Twitter投稿用のタグに「#」を付けたい ④以下の形式でTwitterに文章を投稿したい ブログを更新しました! 今回の記事は「〇〇」です。 https://engineering.nifty.co.jp/blog/xxxxxxx #タグ #タグ #タグ ①ブログの更新を検知したい トリガーの設定をします。 Appは「RSS by Zapier」、Eventは「New Items in Multiple Feeds」を選択します。 FeedsURLsには、RSSフィードURLを設定します。 ②Twitter投稿用のタグを作りたい ブログについているタグを取得し、半角スペースが入っている場合は取り除きます。 Appは「Formatter by Zapier」、Eventは「Text」、Transformは「Replace」を選択します。 Inputで「Raw Category」を選択すると、ブログについているタグを取得できます。 半角スペースの除外をしたいので、Findに「[:space:]」を入力し、Replaceは空のままにします。 ③Twitter投稿用のタグに「#」を付けたい ②で作成したTwitter投稿用のタグに「#」を付け、タグとタグの間に半角スペースを入れます。 Appは「Code by Zapier」、Eventは「Run Python」を選択します。 今回は「Run Python」を選択しましたが、「Run Javascript」を選択すればJavascriptでコードを書くこともできます。 Input Dataの右側の入力ボックスに②で作成したデータを入れ、左側の入力ボックスにキー名を入れます。(以下画像ではキー名を「original_data」としましたが、どんな名前をつけても良いです) Input Dataを用意することで、Codeの中でそれを取り出して使うことができます。 ②で作成したTwitter投稿用のタグに「#」を付け、タグとタグの間に半角スペースを入れる、という処理をPythonで書きます。 できあがったデータ(コード内にある「result」)に対して、「tags」というキー名を付けます。(キー名はどんな名前をつけても良いです) 「output」という辞書型変数に、上記のキー名とデータを設定しておくと、ここで作成したデータを後続の処理で取り出すことができます。 result = "" original_data = input_data['original_data'] tag_list = original_data.split(',') for tag in tag_list: value = "#" + tag + " " result = result + value output = [{'tags':result}] Code by Zapierにおけるデータの渡し方(=「Input Data」及び「output」の使い方)については、公式ドキュメントに詳細が載っています。 https://zapier.com/blog/code-by-zapier-guide/ ④Twitterに文章を投稿したい ブログのタイトル、ブログのURL、③で作成したタグを埋め込み、Twitterに投稿します。 Appは「Twitter」、Eventは「CreateTweet」、Accountで連携したいTwitterのアカウントを選択します。 MessageにTwitterに投稿する文章を入力します。 ブログのタイトル、ブログのURL、③で作成したタグを、文章の中に埋め込んでいきます。 「Should Shorten URLs?」で、URLを短縮化するかどうかを選択することができます。 「false」を選択すると、URLは短縮されずそのまま表示されます。 以上の設定で、RSSフィードの更新をトリガーにしたTwitterへの自動投稿を実現することができました! 感想 Zapierを使用することで、おおむねノーコードで作成できたので、やりたいことを楽に実現することができました。 苦労した点は、③で使用した「Code by Zapier」の書き方について解説されている日本語の記事を探すことができず、「Input Data」及び「output」の使い方を理解するのに時間がかかったことです。 今後Zapierの機能を使う時は、無理に日本語の記事を探すのではなく、困ったらまずは公式ドキュメントを参照しようと思いました。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは、ニフティ株式会社 基幹システムグループの多田 圭佑です。 今回はE2Eテストフレームワークである「Playwright」を使ってテスト自動化をしてみた記事になります。 Playwrightとは Webブラウザのテスト自動化を実行するためのライブラリ 対応ブラウザ:Chromium、WebKit、Firefox、Edgeなど プラットフォーム:Windows、Linux、macOS 言語:TypeScript、JavaScript、Python、.Net、Java ざっくりできること Webブラウザを操作して自動でテストコードを生成してくれる 作成したテストファイルでテスト実行、デバッグ 事前準備 node.js の公式サイトからインストーラーをダウンロードしインストールする 18.17.0LTS(掲載時点のもの) Playwrightを開発プロジェクトのディレクトリ内にインストールする インストール中の確認項目 TypescriptかJavaScriptどちらで使用するか 本記事ではTypeScriptを使用 E2Eテストに使用するディレクトリ名 デフォルトでは「tests」ディレクトリが作成される GitHub Actionsワークフローの追加 デフォルトではfalse ブラウザインストールの有無 デフォルトではtrue npm init playwright@latest 使ってみた 実施環境 windows 10 自動コード作成編 テスト記録 ブラウザ操作ですぐにテストを生成できるツール。 以下のコマンドを実行後にWebサイトを操作するためのブラウザとテストコードをする記録のウィンドウが立ち上がります。 npx playwright codegen ブラウザ この画面で操作した内容がテストコード記録に自動入力される 最初はテストを実施したいURLにアクセスするところから始める テストコード記録 ブラウザで操作した内容が自動でコードとして記録される テストのコピー、クリア、および言語の変更を行うこともできる nifty.comから「nifty engineering」を検索して「nifty engineering」にアクセスする 1.nifty.comにアクセスする 2.「nifty engineering」と入力して検索する 3.検索結果から「NIFTY engineering」を選択する 4.「NIFTY engineering」が表示される 出来上がったコードがこちらとなります。 page:ブラウザのタブ Locator:ページ上の要素(id, nameなど)を取得 getByTestId:テストID(data-testid)で要素を取得 getByRole:要素を役割別に取得 waitForEvent:イベントハンドラーの待機(ex.ポップアップウィンドウなど) import { test, expect } from '@playwright/test'; test('test', async ({ page }) => { await page.goto('https://www.nifty.com/'); await page.getByTestId('search-input').click(); await page.getByTestId('search-input').fill('nifty engineering'); await page.getByTestId('search-button').click(); const page1Promise = page.waitForEvent('popup'); await page.getByRole('link', { name: 'NIFTY engineering - ニフティ株式会社のエンジニアたちの ...' }).click(); const page1 = await page1Promise; await page1.getByRole('link', { name: '【6/27(火) 12:00~】スクラム開発の真髄を探る!認定スクラムマスター研修参加者が語る成功のカギを開催します!' }).click(); }); テストファイル作成編 生成されたテストコードを元にtestsディレクトリ配下にテストファイルを作成します。 ( search-test.spec.ts というファイルを作成) テスト実行編 以下の単位でテストを実行することができます。ブラウザは1つから複数で実行できますが、実行中はウィンドウが開かれず、結果のみがターミナルに表示されます。 全てのテストファイル テストファイル単位 テストグループ単位 テスト実行するためには以下コマンドを実行します。 npx playwright test 作成したテストファイルを実行した結果がこちらとなります。 PS C:\workspace\nifty-blog> npx playwright test search-test.spec.ts Running 1 test using 1 worker 1 passed (18.7s) To open last HTML report run: npx playwright show-report PS C:\workspace\nifty-blog> テストが完了すると結果を記す詳細ページが表示されます。 表示されない場合、「npx playwright show-report 」を実行してください。 各テストコードに緑のチェックマークがついています。これはテストが成功したという意味です。 デバッグ編 UI Modeは、テストの作成・実行を視覚的にサポートするためのツールとなります。テストファイルを実行、デバッグした結果をリアルタイムで閲覧することが可能となります。 UI Modeを開くには次のコマンドを実行します。 ※Playwright v1.32.0以上 npx playwright test --ui 赤枠のアイコンを押すことでテスト実行ができます。 ①テストファイル単位 ②テストグループ単位 設定は? playwright.config.ts でテストに関する設定をすることができます。 デフォルトで設定されているブラウザ(projects)はchromium、firefox、webkit(Safari)となっています。 Edgeなど別ブラウザを追加したい場合、projects内に加えてあげる必要があります。 またデフォルトではタイムアウト時間が30秒となっており、時間を変更したい場合は追記する必要があります。(タイムアウトをさせない場合は「0」を設定する) import { defineConfig, devices } from '@playwright/test'; /** * Read environment variables from file. * https://github.com/motdotla/dotenv */ // require('dotenv').config(); /** * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ testDir: './tests', /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: 'html', /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ // baseURL: 'http://127.0.0.1:3000', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', }, timeout: 60000, // 60秒 /* Configure projects for major browsers */ projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, { name: 'firefox', use: { ...devices['Desktop Firefox'] }, }, { name: 'webkit', use: { ...devices['Desktop Safari'] }, }, ], }); ポイント テストを実施したいファイルを作成したい場合 インストールの際に設定したディレクトリ内にテストファイルを配置する テストファイルの拡張子に「.spec.ts」または「.test.ts」を付ける javascriptの確認ダイアログでどちらを選択したかは自動コード作成では取得できません。 そのため以下のようにコードを追記する必要があります。 // ダイアログで「はい」を選択する dialog.accept(); // ダイアログで「いいえ」を選択する dialog.dismiss(); テストコードの量が増えたらtest.step等で区切って上げた方が可読性が上がります! import { test, expect } from '@playwright/test'; test('test', async ({ page }) => { await test.step('nifty.comから「nifty engineering」を検索', async () => { await page.goto('https://www.nifty.com/'); await page.getByTestId('search-input').click(); await page.getByTestId('search-input').fill('nifty engineering'); await page.getByTestId('search-button').click(); }); await test.step('「nifty engineering」にアクセスする', async () => { const page1Promise = page.waitForEvent('popup'); await page.getByRole('link', { name: 'NIFTY engineering - ニフティ株式会社のエンジニアたちの ...' }).click(); const page1 = await page1Promise; await page1.getByRole('link', { name: '【6/27(火) 12:00~】スクラム開発の真髄を探る!認定スクラムマスター研修参加者が語る成功のカギを開催します!' }).click(); }); }); We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは。ニフティ株式会社の添野隼矢です。 今回は、ノーコードタスク自動化ツールであるZapierを使って、Notionのデータベースに定期的なタスク(毎月や隔月など)を作成する方法をご紹介します。 上記の作成経緯としては、前にいたチームでNotionのDBを使って仕事をしており、また実施する定例的なタスクも実施するタスクが奇数月と偶数月で異なっていました。 そのような状況により、NotionのDBにアイテムを作成し忘れるということが多々ありましたので、NotionとZapierを使って、定期アイテムを作成するようにしました。 設定方法 毎月の例 ①Zapierにログインし、「Create Zap」でZap作成画面に行きます。 ②Zapの名前を編集します。 今回は、「(毎月)アンケート実施」としました。 ③Triggerの画面でScheduleと検索し、「Schedule by Zapier」を選択します。 ④Schedule by ZapierのEventを選択します。 今回は毎月で作成するため、「Every Month」を選択します。 ⑤日時を設定します。 今回は、1日の9時に動くように設定しました。 ⑥Continueを押し、Test triggerで今日の日付が取れていることを確認します。 ⑦Actionで「Notion」と検索して、「Notion(Latest)」を選択します。 ⑧Eventで「Create Database Item」を選択し、Continueをします。 ⑨「Connect a new account」を選び、定例アイテムを追加したいNotionDBを選択します。 今回は、定例アイテムを追加したいNotionDBとして、「タスク」というDBを作ってそちらを選択しました。 ⑩Databaseの項目に追加したいNotionDBを選び、後は追加したいNotionDBの形式や作業内容に合わせて項目を埋めていきます。(Contentは、Markdown形式で記載ができます) ⑪Contiuneを押すと、Testに進み「Test Action」を実施されます。 実施されると、以下のような画面が出ます。(再度Testを実行したい場合は、Reset actionボタンを押します。) また成功していれば、NotionDBにアイテムが追加されています。 ⑫「Publish」を押す前に、Zapの設定でTimeZoneが「Asia/Tokyo」になっていることを確認します。 ⑬「Publish」を押し、Zap公開すれば完成です。 隔月の例 基本的な流れは、上記の毎月の定例アイテム作成のZapと同じですが、 上記の毎月の定例アイテムのZapに、1個アクション(Filter by Zapier)を追加します。 アクションを追加するところは、TriggerとCreate Database Itemの間です。 Filter by Zapierで以下の条件でフィルターしていきます。 ※フィルターの設定内容 Schedule by Zapierで取得したDate Month(月)を、右に入力した数字とExactly matches(完全一致)比較を行います。 今回は、奇数月に定例アイテムをNotionDBに作成したかったので、右に入力した数字は奇数月の数字を入力しています。 Continueを実行し、「Your Zap  would  have continued」と表示が出て、想定通りの結果になっていれば完了です。 あとはTimeZoneなどを一応確認して、Publishで公開すれば、隔月(例では奇数月)でNotionDBにアイテムが作成されるZapが完成です。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは、ニフティ インフラシステムグループ社内情報システムチームの仲上です。 先日、非エンジニアでもメール配信サービスからAPI経由で情報を取得できるように、Slack boltを使用してbotを作成しました。しかし、情報の取得・整形処理が想定より重く、エラーが頻発するようになってしまいました。その際にlazy listenerを使用してこの問題を解決したことについて紹介しようと思います。 Slack bolt と lazy listener 今回Slack botを作成するにあたって、機能の充実さと導入が容易な点から公式ライブラリのSlack boltを使用しました。 https://slack.dev/bolt-python/ja-jp/tutorial/getting-started Slack boltを使用した場合、Slackへの応答には3秒以内返信という制約があります。処理が重かったり、ネットワークの問題などでレスポンスを返すのに3秒以上かかってしまった場合、Slack側でエラー処理されてしまします。そこでslack boltに搭載されているlazy listener を使用します。この機能を使うことにより、重い処理を非同期で実行できるので、タイムアウトによるエラーを回避することができます。 https://slack.dev/bolt-python/api-docs/slack_bolt/lazy_listener/index.html lazy_listener を使用することで処理結果が出るより先にSlackへの応答を返すことができ、重い処理を非同期で実行することができます。 今回つくったもの メール配信サービス(SendGrid)に登録されている情報をAPI経由で取得し、Slackに表示するbotを作りました。 SendGridとは SendGridとは、クラウドベースのメール配信サービスです。こちらは世界的に利用されている高い到達率を誇るサービスで、APIを叩いてメールを送信することができます。また、SendGridにはテンプレート機能というものがあります。これはメールの送信元や件名、本文などを予め設定しておくことができる機能で、APIのパラメータに本文内の埋め込み情報などを渡すだけで定型文を送ることができます。 今回このテンプレートに登録されている情報を誰でも確認できるようにしたかったため、Slack botを作成しました。 構成図 Slackのグローバルショートカットをクリックするだけで使用できるようにしました。 SlackのショートカットがクリックされるとLambdaがSendGridのAPIを叩きテンプレートに関する情報を取得します。取得した情報はLambdaでSlack用のメッセージに整形され、メッセージが送信されます。 環境 Python 3.9 serverless framework 3.31.0 serverless-python-requirements 6.2.3 aws cli 2.12.4 slack-bolt 1.18.0 slack-sdk 3.21.3 実装 Slack appの登録やLambdaへの登録説明は省略します。 ファイル構成 │ ┣lib #ライブラリ保存用ディレクトリ ┣formatter.py ┣modal.py └sendgrid.py ┣slack #マニュフェスト保存用ディレクトリ ┣manifest-dev.yml └manifest-prod.yml ┣app.py ┣package-lock.json ┣package.json ┣requirements.txt └serverless.yml app.py # Serverless Python Requirements を使用するためにimpoertします try: import unzip_requirements except ImportError: pass import os import logging from datetime import datetime # slack bot関係 from slack_bolt import App, Ack, Say, BoltContext from slack_sdk import WebClient # 独自関数 from lib.formatter import ( format_template_list, format_template_content, ) from lib.sendgrid import ( get_template_list, get_template_id, get_template_content, ) from lib.modal import get_template_detail_modal app = App( # Settings > Basic Information > App Credentials > Signing Secret で取得可能 signing_secret=os.environ.get("SLACK_SIGNING_SECRET"), # Settings > Install App で取得可能 token=os.environ.get("SLACK_BOT_TOKEN"), # AWS Lambdaで動作させるために、以下の設定を有効にします。 process_before_response=True, ) # 登録されているテンプレート一覧(テンプレート名、件名)を返す関数 def post_template_list(body: dict, client: WebClient) -> None: user_id = body["user"]["id"] template_list = get_template_list() templates_length = len(template_list) send_message = format_template_list(template_list) comment = f"<@{user_id}>\\nテンプレートは以下 {templates_length}件 が設定されています" client.files_upload( channels=os.environ["SLACK_CHANNEL"], content=send_message, filename=f"{datetime.now().strftime('%Y%m%d%H%M%S')}_RTMテンプレート一覧.tsv", filetype="tsv", initial_comment=comment, ) # 応答用 def ack(ack, body): ack() # 「realtime-mail-テンプレート一覧取得」が押されたとき、post_template_list を非同期で実行 app.shortcut("get-template-list")(ack=ack, lazy=[post_template_list]) # 「realtime-mail-テンプレート詳細取得」が押されたとき、検索項目入力用のモーダルを表示 @app.shortcut("get-template-detail") def send_modal(ack: Ack, body: dict, client: WebClient): ack() client.views_open(trigger_id=body["trigger_id"], view=get_template_detail_modal()) # モーダルのsubmitボタンが押されたとき、テンプレートの詳細を返す def post_template_details( view: dict, logger: logging.Logger, say: Say, client: WebClient, payload: dict, context: BoltContext, ) -> None: # 入力値の取得 user_id = context.get("user_id", "") inputs = view["state"]["values"] input_value = ( inputs.get("input-block", {}).get("number-input-action", {}).get("value", 0) ) # テンプレートの検索 template_list = get_template_list() template_info = get_template_id(input_value, template_list) template_id = template_info.get("id", "") # テンプレートがなかった場合 if template_id == "": client.chat_postMessage( channel=os.environ["SLACK_CHANNEL"], text=f"""<@{user_id}> 検索内容:{input_value} 検索結果 > 入力された番号で登録されたテンプレートはありませんでした。 """, ) return # テンプレートの内容を取得して変換 template_content = get_template_content(template_id) send_message = format_template_content(template_content, template_id) # テンプレート名を格納 template_name = template_info.get("template_name", "") comment = f"""<@{user_id}> 検索内容:{input_value} 検索結果 > テンプレート番号:{template_name[:4]} > 件名:{send_message.get("subject", "")} > 最終更新日:{send_message.get("updated_at", "")} """ client.files_upload( channels=os.environ["SLACK_CHANNEL"], content=send_message.get("plane_contents", ""), filename=f"{template_name[:4]}_{datetime.now().strftime('%Y%m%d%H%M%S')}.txt", filetype="text", initial_comment=comment, ) # modalのsubmitボタンが押されたとき、post_template_details を非同期で実行します app.view("modal-id")(ack=ack, lazy=[post_template_details]) # アプリを起動します(デバッグ用) if __name__ == "__main__": app.start() # --lamda用の設定 ここから-- from slack_bolt.adapter.aws_lambda import SlackRequestHandler # ロギングを AWS Lambda 向けに初期化します SlackRequestHandler.clear_all_log_handlers() logging.basicConfig(format="%(asctime)s %(message)s", level=logging.DEBUG) # AWS Lambda 用handler def handler(event, context): slack_handler = SlackRequestHandler(app=app) return slack_handler.handle(event, context) lasy_listener を使用する際は以下のように書きます。 # app.<アクション>("<modalIDまたはアクションID>")(ack=<ack関数名>, lazy=[<非同期で実行したい関数>]) # ↓はmodalのsubmitボタンが押されたときのアクション app.view("modal-id")(ack=ack, lazy=[post_template_details]) serverless.yaml frameworkVersion: "3" useDotenv: true service: supsys-mailrelay-slackapp provider: name: aws runtime: python3.9 region: ap-northeast-1 iam: role: statements: - Effect: Allow Action: - lambda:InvokeFunction - lambda:InvokeAsync Resource: "*" environment: SERVERLESS_STAGE: ${opt:stage, 'dev'} SLACK_SIGNING_SECRET: ${env:SLACK_SIGNING_SECRET} SLACK_BOT_TOKEN: ${env:SLACK_BOT_TOKEN} SENDGRID_API_KEY: ${env:SENDGRID_API_KEY} SLACK_CHANNEL: ${env:SLACK_CHANNEL} functions: app: handler: app.handler name: supsys-mailrelay-slackapp-${sls:stage} events: - httpApi: path: /slack/events method: post package: patterns: - "!.venv/**" - "!node_modules/**" - "!.idea/**" plugins: - serverless-python-requirements custom: pythonRequirements: zip: true slim: true useDownloadCache: false useStaticCache: false lambdaでは標準搭載されているパッケージ以外は自分で入れる必要があります。これらを手動で行う場合、 パッケージをローカルにダウンロード zipファイルで圧縮 lambdaに転送 と非常に手間がかかります。 そこで serverless-python-requirements を使うことでこれらの手間を低減します。このプラグインは requirements.txt を宣言すると自動でパッケージの圧縮・デプロイまで行ってくれます。 デプロイ $env:SLACK_SIGNING_SECRET='XXXXXXXX' $env:SLACK_BOT_TOKEN='xoxb-XXXXXXXX' $env:SLACK_CHANNEL='XXXXXXXXXXX' # 送信先SlackチャンネルのID $env:SENDGRID_API_KEY='SG.XXXXXX.XXXXXXXXX'D serverless deploy 動作確認 テンプレート一覧 テンプレート一覧を選択します。 登録されているテンプレート一覧がDMで送られてくることが確認できました。 テンプレート詳細 テンプレート詳細を選択します。 表示されたmodalに管理番号を入力して送信します。 DMでテンプレートの内容が送られてくることが確認できました(画像はテスト用テンプレートです) おわりに このbotを開発したことにより、sendgridのアカウントを持っていなくてもSlackからSencGridのテンプレートを見れるようになりました!今までは問い合わせベースで対応していたので、対応の時間を大きく減らすことができました。 Slack bolt + severless framework を使ったbotの開発は非常に柔軟性・拡張性が高いので、みなさんも是非試してみてください! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
ニフティ株式会社に新卒で入社した中井です。 突然ですが皆さん、退勤時の打刻を忘れたことはありませんか?ありますよね。私も入社してすぐの4月でやらかしました 背景 ニフティでは、勤怠管理のWebアプリ上で打刻ボタンを押してから退勤することになっています。私は自分をほとんど信じていないので、業務が終了する時刻に自動的にWebアプリのURLをブラウザを開くよう、Windowsのタスクスケジューラで設定していました。ところが… 起こったこと 研修の関係でいつもより早く業務が終了したので、打刻画面が自動的に表示されるよりも前に、そのままシャットダウンして帰りました。翌日出勤打刻をしようとしたときに前日の退勤打刻を忘れていたことが発覚しました。 私は自分をこれっぽっちも信じられなくなったので、より強力な対策に乗り出すことにしました。 対策 思いついたのは次のような対策です。 退勤画面を開いてシャットダウンするバッチファイルを作成する。 PCをシャットダウンするときは、必ず作成したバッチファイルから行う。 PCの設定を変更し、スタートメニューからシャットダウンできないようにする。 バッチファイルの作成 もともと退勤時刻である17:45に打刻画面を開くように設定していたのですが、実際には早めに業務が終わることもあると思います。本当は退勤したいと思ったとき、つまり、シャットダウンする前に画面を開いてもらうべきではないでしょうか。 しかしシャットダウンイベントをフックするとなると大変ですし、不確実性がだいぶ高くなりそうです。若干使いやすさは落ちますが、一連の動作をバッチファイルにしてしまう方針でいきましょう。 打刻画面を開く ブラウザが閉じたことを確認する shutdown コマンドを発行する @echo off :: 念のため、本当にシャットダウンしたいのか確認する set /p yn_check="Do you want to shutdown? (y/N) >" if not %yn_check:Y=Y% == Y goto end :: 打刻画面を開く start /w {ここに打刻画面のURLを入れます} :: ブラウザが閉じるのを待ちます。 :: とりあえずChromeとFirefoxのプロセスがあるか監視する感じで。 :try powershell sleep 1 tasklist | findstr chrome.exe > NUL if %errorlevel% equ 0 ( echo Google Chrome has not finished, watching... goto try ) tasklist | findstr firefox.exe > NUL if %errorlevel% equ 0 ( echo Firefox has not finished, watching... goto try ) :: ブラウザが閉じたことを確認したらシャットダウンします。 echo Browser has finished. Shutdown 10 seconds later. shutdown /s /t 10 シャットダウンは必ずこのバッチファイルを使うということにすれば解決です。 スタートメニューのシャットダウンを無効化する 単にそういうルールを課すだけというのは、いわゆる「運用でカバー」というやつです。どうせまた普通にシャットダウンしてしまうのが目に見えています。そこで、スタートメニューから電源系のメニュー項目を消してしまいましょう。「ローカル グループ ポリシー エディタ」を使うと達成できます。 この項目を開いて次のように有効化します。 いつものスタートメニューの電源オプションが「現在、利用できる電源オプションはありません。」となり、スタートメニューからシャットダウンできなくなれば成功です。 これで今度こそ「うっかり」はなくなるはずです。 ショートカットをタスクバーに追加 あとはお好みですが、最後の一仕事をしましょう。 作成したバッチファイルはデスクトップに置いておくのでもよいのですが、デスクトップを開かないとシャットダウンできないのもまた不便なので、私は上の画像のようにタスクバーに用意することにしました(一番左のアイコン)。 ただし、バッチファイルをそのままタスクバーにピン止めすることはできないので、ひと工夫が必要です。バッチファイルを実際に実行するのはコマンド プロンプトなので、コマンド プロンプトへのショートカットとして作成することで、この問題を回避することができます。 どこか適当なフォルダで [新規作成] > [ショートカット] から C:\\Windows\\System32\\cmd.exe /c "<バッチファイルのパス>” へのショートカットを作成する。 ショートカットを右クリックしてプロパティを表示し、お好みのアイコンを設定する。 作ったショートカットを右クリックから [タスクバーへピン止めする] を選んで完成。 おわりに 一応まあ、ここまでしても打刻を忘れる可能性があります。シャットダウンせずそのままPCを閉じて帰ってしまう場合です。私は自分を一切信じていないので、ある程度遅い時刻に画面ロック状態に入ったらビープ音を鳴らすという施策も用意しましたが、それはまた別の話としましょう。ただ実際には、ここまでの作業をしたことで打刻のことが頭の中に完全に刷り込まれ、「打刻を忘れてたけどこれのおかげで助かったー」という事案は発生しませんでした。 良かったと言えば良かったのですが、なんとも複雑な気持ちです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も常時受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
お初にお目にかかります。基幹システムグループの桑原です。 システム開発に携わっていれば、多くの方が大なり小なり障害に遭遇しているかと思います。 私も長年開発・運用業務をやっており、システム障害や運用ミスなど、いろんな障害に携わってきました。自分が起こしたり、巻き込まれたりなどなど。 その中から最近発生した、そんなところに原因が・・と思ったもののお話しをします。 障害の概要 ある日お客様への通知物関連の処理にて、お客様の元へ届かないという障害が発生しました。 原因となった該当の処理自体は単純なもので、ファイルをリネームして移動するだけのものでバグが入り込む余地がないほどの処理です。 登場するサーバは下記の2台。 サーバA:ファイルをリネーム・移動する処理が実行されるサーバ 0:30にcron実行される サーバB:移動後のファイルを使用する後続処理が動くサーバ 1:30にcron実行される オマケ情報 サーバAとサーバBは同じNASをマウントしている 時を遡ること約1年、サーバAの処理の終了時間が少しずつ遅れはじめました。 ここからカウントダウンが開始されたのでした。 移動されたファイルのタイムスタンプが今までは0:30だったのが、最終的にリミットの1:30を越えて後続処理に間に合わなくなり、障害の発生。 先に記述したとおり、ファイルをリネーム・移動するだけの処理がなぜこんなに時間がかかるのかまったく理由がわかりませんでした。 調べてみる まずは、サーバAで遅れていった処理のログを見てみました。単純な処理過ぎて使えるログはほぼ出力しておらずまったく役に立ちません。 参考になったのは、ログのタイムスタンプで、0:30となっていたことで、処理自体は時間通りに開始しているらしい点。 移動先のファイルのタイムスタンプを確認してみると、やっぱり開始時間とはかなりかけ離れていることがわかりました。 -rw-r--r-- 1 user1 group1 0 2月 27 01:29 2023 file_20230227.txt -rw-r--r-- 1 user1 group1 0 2月 28 01:29 2023 file_20230228.txt -rw-r--r-- 1 user1 group1 28 3月 1 01:30 2023 file_20230301.txt -rw-r--r-- 1 user1 group1 28 3月 2 01:30 2023 file_20230302.txt -rw-r--r-- 1 user1 group1 84 3月 3 01:30 2023 file_20230303.txt -rw-r--r-- 1 user1 group1 84 3月 4 01:30 2023 file_20230304.txt -rw-r--r-- 1 user1 group1 28 3月 5 01:30 2023 file_20230305.txt -rw-r--r-- 1 user1 group1 0 3月 6 01:31 2023 file_20230306.txt ←この日から障害 -rw-r--r-- 1 user1 group1 0 3月 7 01:31 2023 file_20230307.txt -rw-r--r-- 1 user1 group1 28 3月 8 01:31 2023 file_20230308.txt なぜこの処理でこんなに時間がかかるのか、ソースを見ても時間のかかるところなんてありませんでした。 ファイルサイズは0~100byte前後がほとんどで普通に考えれば一瞬で終わります。 そしてさらに謎なことに、10日程度でこれがおさまったことです。 ちなみに3月15、16日はなにもしていません。 -rw-r--r-- 1 user1 group1 28 3月 14 01:32 2023 file_20230314.txt -rw-r--r-- 1 user1 group1 56 3月 15 01:33 2023 file_20230315.txt -rw-r--r-- 1 user1 group1 28 3月 16 00:30 2023 file_20230316.txt ←0:30に戻る -rw-r--r-- 1 user1 group1 84 3月 17 00:30 2023 file_20230317.txt -rw-r--r-- 1 user1 group1 56 3月 18 00:30 2023 file_20230318.txt -rw-r--r-- 1 user1 group1 56 3月 19 00:30 2023 file_20230319.txt -rw-r--r-- 1 user1 group1 28 3月 20 00:31 2023 file_20230320.txt ←また遅れ始めた -rw-r--r-- 1 user1 group1 252 3月 21 00:31 2023 file_20230321.txt その後また少しずつ遅れ始めていて、このままではまた1年後くらいに同じことが起こってしまう可能性がありました。 調査に行き詰まり、チームでの障害共有のときに何かとっかかりになるような観点ないか相談をしてみました。 解決 結果からいうと、処理に時間がかかっていたわけではなく、サーバAの時計が遅れていました。 約1年前から少しずつ時計が遅れていき、後続処理までの1時間を超えてしまったというオチでした。 相談したときにNTPでは?と言われ、確認してみたら # vmware-toolbox-cmd timesync status Disable と出てきました。時刻同期が無効だった・・・ そのときのファイルのタイムスタンプと実際の時刻のズレもほぼ同じでしたので、これかと。 なるほど、サーバAではズレている時刻どおり0:30に実行し終わっているので、ログのタイムスタンプは0:30になり、サーバBから見たらファイルは遅れて置かれた時間がタイムスタンプになるわけです。 # vmware-toolbox-cmd timesync enable サーバAで時刻同期を行って対応は終わりました。 他にも時刻同期が無効になっているサーバがないか確認したら数台見つかりました。 しかし、数分のズレで済んでおり、ここまで遅れていったのはサーバAのみでした。なぜこいつだけ・・ それなりに古いシステムで、構築時を思い返しても時刻同期をどうするみたいな細かいところまで手順にはなかった気がします。 約1年前なにがトリガーになって時計遅れ始めたのか、何もしてないのに正しい時刻になおったことなど気になる点はまだありますが、syslog見ても影響していそうなのもなく謎は残りますが、この件は一旦これで終わり。 障害原因の調査をするときは、該当システムばかり調査しがちになりますが、今回のように他のところに問題があることもあるのだなと。 今後の教訓として、迷ったら少しそっちに目を向けた調査も考慮しようと思った一件でした。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは。ニフティ株式会社の添野翔太です。 今回はモノレポ用のデプロイパイプラインを構築した話を共有します。 背景 現在、 @niftyトップページ ではアプリケーション基盤の刷新を進めていますが、その過程で一部においてモノレポを採用しています。このリポジトリは、Web3層アーキテクチャにおけるWeb層にあたるもの、App層にあたるもの、およびその他のバッチ処理からなる構成です。 デプロイパイプラインの構築には、Github ActionsとCodeシリーズ(AWS CodePipeline、AWS CodeBuild、AWS CodeDeploy)を利用しています。 モノレポ用のデプロイパイプラインを作ってみる Codeファミリーに関する問題として、一つのパイプラインに対応するブランチが一つしか設定できないという点が挙げられます。 そこで、 Stack OverflowのQ&A を参考にしながら、GitHub Actions上で特定のブランチに強制Pushする機構を作成しました。 まず、ディレクトリ構成を以下に示します。 (Gitリポジトリ) └─.github │ ├─actions │ │ └─applications │ │  └─sample │ │       └─deploy │ │           └─action.yaml │ └─workflows │    └─auto_push.yaml ├─buildspec_app.yaml ├─appspec_app.yaml ├─taskdef_app.json (以下略) 次に、特定のブランチかつ特定のファイルで、Codeシリーズが監視するブランチに強制Pushするコード(.github/workflows/auto_push.yaml)を以下に示します。pathsキーには、主にCodeシリーズで使用するファイル類(BuildSpecやAppSpec、ECSタスク定義など)やデプロイ対象のソースコードを並べます。 name: sample_application_deploy on: # NOTE: PRがマージされた際に動くようにする push: branches: - develop - master paths: - 'buildspec_app.yaml' - 'appspec_app.yaml' - 'taskdef_app.json'             (中略) jobs: development: if: github.ref == 'refs/heads/develop' runs-on: ubuntu-latest timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@v3 with: ref: develop - name: Deployment uses: ./.github/actions/applications/sample/deploy with: pipeline-branch: pipeline/dev/app production: if: github.ref == 'refs/heads/master' runs-on: ubuntu-latest timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@v3 with: ref: master - name: Deployment uses: ./.github/actions/applications/sample/deploy with: pipeline-branch: pipeline/prod/app そして、./.github/actions/applications/sample/deploy/action.yamlに共通処理である強制Pushを行う以下のコードを記載します。 name: auto_push_to_branch description: Auto push to branch inputs: pipeline-branch: required: true description: name of the codepipeline branch runs: using: "composite" steps: - name: Switch branch run: | git fetch --prune git switch -c ${{inputs.pipeline-branch}} shell: bash # NOTE: リポジトリ上でブランチが作られているとpush時にrejectされるためforce pushを実施する - name: Push changes run: | git push origin ${{inputs.pipeline-branch}} --force shell: bash 上記コードのイメージを以下に示します。developブランチとmasterブランチはPRを使用して更新します。PRがマージされると、自動的に別のブランチに強制的にPushされます。強制Pushするブランチ先(pipeline/dev/appブランチとpipeline/prod/appブランチ)は、Codeシリーズを使用して作成するデプロイパイプラインとそれぞれ対応しています。 ここまでApp層のみをデプロイ対象として説明しましたが、Web層をデプロイしたい場合にも同様に展開できます。 おわりに 今回はモノレポ用のデプロイパイプラインを構築した話を紹介しました。何かの参考になれば幸いです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター