古いOSで発生したエラーをSentryでフィルタリングする

この記事はトラストバンクAdvent Calender 2023の12日目の記事です。

お久しぶりになってしまいました。フロントエンドエンジニアの田口です。
しばらくSentryのお世話がおざなりになってしまっていましたが、最近またフィルタリングの設定を加えました。
そのときにSentryと直接やり取りしたり、ドキュメントを見直したりして自分の勘違いに気づくことができましたので、共有したいと思います。

今回やりたかったこと

今回追加したかったフィルタリングは、サービスの推奨環境外の古いモバイルOSを検知対象からは外すというものです。
ふるさとチョイスでは携帯端末の推奨環境を以下のように定めています。

iPhone iOS14以降 Safari 最新版
Android 9.0以降 Google Chrome 最新版

www.furusato-tax.jp

この推奨環境未満のバージョン、つまりiOS 13やAndroid 8といった古いOSバージョンの端末で発生したクライアントエラーについては、 SentryのIssuesに追加しないようにします。

これの理由としてはSentryのクォータの節約が主です。

フィルタリングの仕込み

BeforeSendの使用

以前Sentryのフィルタリングについて書いた際、beforeSendについて記載しました。
ふるさとチョイスで使用しているSentryのプランは変わっていませんので、今回もbeforeSendでフィルタリングします。

docs.sentry.io

beforeSendの引数であるeventの持っている情報が重要そうです。

Sentryの画面でeventの中身を推測してみる

Sentryの管理画面では全てのエラーイベントの発生した環境が確認できます。

OSのタイプだけでなく、バージョンまで分かります。
Sentryの管理画面ではエラーイベントをJSONとして拾うこともできます。

JSONの内容は割愛しますが、このJSONにもOSなどの情報が同じように載っています。

Event Payload

恐らく上に書いたような内容がbeforeSendeventに入ってくるはずですが、SentryのAPIドキュメントを更に漁ってみます。

develop.sentry.dev

これですね。

OSに関する情報はこの中のContexts Interfaceで実装されています。

develop.sentry.dev

JSONの中身の紹介は割愛しましたが、そこにもcontextsのキーと値が入っています。

いざ実装

event.contextsからOSの情報まで辿り着けそうだったので、最初は以下の実装を試しました。

const checkLegacyOS = event => {
  const IOS_VERSION = 14;
  const ANDROID_VERSION = 9;
  const os = event.contexts.os.name;
  const { version } = event.contexts.os;
  return ((os === 'iOS' && Number(version.split('.')[0]) < IOS_VERSION) || (os === 'Android' && Number(version.split('.')[0] < ANDROID_VERSION)));
};

しかしなんということでしょう、os.nameos.versionも存在していません。そもそもOSなどの情報がeventに一切ありません。
試しに発生させたエラーはSentryで検知されており、しっかり管理画面から見ることができます。そしてOSの情報も入っている……
一時的に混乱に陥りました。

解決

とりあえずSentryのチャットとメールでやり取りをしつつ、色々調べたところ、普通にドキュメントに書いてありました。

In events reported from a JS web frontend, the SDK typically reports no OS context.

develop.sentry.dev

こんなこと書いてあったけどマジ?とSentryのフランシスにメールで聞いてみたところ、

「あ〜そうそう!その通り!OS ContextsはbeforeSendじゃ拾えないよ。SentryにPOSTするときのヘッダーでユーザーエージェントとってるからそれとeventをくっつけてるんだ。」
「だからbeforeSendでフィルタリングするときに使うなら、ユーザーエージェントからtagsに情報入れるとできるよ。」

と教えてくれました。ありがとうフランシス。

tagsはここに記載がありますが、要はeventに任意のパラメータを追加できる、みたいな考え方で良いと思います。

docs.sentry.io

event.tagsでオブジェクト形式で拾えます。公式のスニペットを貼っておきます。

{
  "tags": {
    "ios_version": "4.0",
    "context": "production"
  }
}

Event Payloads | Sentry Developer Documentation

tagsの付与はinitialScopeで行うのが良いとフランシスが言ってました。

docs.sentry.io

ということで、最終的にこんな感じになりました。

// 古いモバイルOSか(trueなら除外)
const checkLegacyOS = event => {
  const IOS_VERSION = 14;
  const ANDROID_VERSION = 9;
  const mobileType = event.tags?.mobileType;
  const version = event.tags?.majorVersion ? Number(event.tags.majorVersion) : null;
  if (!mobileType || version === null) return false;
  if (mobileType === 'iPhone' || mobileType === 'iPad') return version < IOS_VERSION;
  if (mobileType === 'Android') return version < ANDROID_VERSION;
  return false;
};

const getMobileTag = () => {
  const ua = navigator.userAgent.toLowerCase();
  const isIphone = ua.includes('iphone');
  const isIpad = ua.includes('ipad') || (ua.includes('macintosh') && 'ontouchend' in document);
  const isAndroid = ua.includes('android');
  if (isIphone) {
    const type = 'iPhone';
    return createTagObject(type, ua, /iphone os [\d_]+/);
  }
  if (isIpad) {
    const type = 'iPad';
    if (ua.includes('ipad')) return createTagObject(type, ua, /cpu os [\d_]+/);
    return createTagObject(type, ua, /version\/[\d.]+/);
  }
  if (isAndroid) {
    const type = 'Android';
    return createTagObject(type, ua, /android [\d.]+/);
  }
};

// SentryのTag情報を作成
const createTagObject = (mobileType, ua, matcher) => {
  const [osDetail] = ua.match(matcher) ?? ['unknown'];
  const [majorVersion] = osDetail.match(/\d+/) ?? ['unknown'];
  return { mobileType, osDetail, majorVersion };
};

Sentry.init()はこんな感じです。(だいぶ省略してます)

Sentry.init({
  integrations: [new Sentry.BrowserTracing()],
  initialScope(scope) {
    const tags = getMobileTag();
    if (tags) scope.setTags(tags);
  },
  beforeSend(event) {
    // 色々フィルタリング
  }
}

まとめ

Sentryのフィルタリングについてまた一つ理解しました。
特にtagsの使用は応用範囲が広く感じましたので、みなさんもぜひ活用してみてください。

最後にいつもの!
トラストバンクではフロントエンドエンジニアの仲間を大募集しております。
この投稿以外にも他の記事で興味を持ったらぜひ一度お話ししてみませんか?

www.wantedly.com

IT健保メシコンプリートを支える技術

トラストバンク Advent Calendar 2023の6日目の記事です。

IT健保ユーザーには多くの人が夢を見ながらも、たどり着くことができない幻の地がある。
IT健保レストランだ。

我々はその謎を解き明かすべくジャングルの奥地へと向かった。

powered by iwatea

下準備

IT健保メシをコンプリートするには入念な計画と計画を実行をする根気強さが必要だ。
それには共に行くメンバーとのコミュニケーションが必須となる。

しかし、リモートの現場が増えた現在、チーム内であってもコミュニケーションにコツが必要な時代となってしまった。

我々SREチームではGatherを使う事で通話のハードルを下げ、ある程度バランスを取ることができているが、出社時と同じレベルのコミュニケーションが取れるのか?と言われると弱いところがある。

だが、ここで一つ決め事を作ると突然景色が変わる。

それは「まあ月1回くらいはうまい飯食べるついでに出社しとく?」という雰囲気をふんわり醸成することだ。
そしてこの月1回というのが予約で埋まりがちなIT健保メシの攻略法の鍵となるのである。

出国準備

IT健保メシにたどり着くのに最初にして最大の難関がある。 予約だ。

空き状況カレンダーを見てみてほしい。
※寿司はWebでは見れません。電話してください。

基本的にどの店も直近1ヶ月くらいは埋まっている。
だがそこで諦めず2ヶ月後の予定を見てほしい。

アレ、意外と空いてる日があるぞ?とならないだろうか?

もちろん人気の店(寿司、和食)は2ヶ月後も埋まっているが、3ヶ月後はどうだろう?
3ヶ月後指定なら案外予約できるものである。

さて、ここで日付を決める上で大事なポイントがある。

「まあ月1回くらいはうまい飯食べるついでに出社しとく?」ということだ。
出社のついでにメシを食うのではない、メシのついでに出社をするのである。

そうすることで、IT健保メシを最優先とした日付設定が実現できる。

ここを勘違いするとIT健保メシのコンプリートは遠くなるので、これまでの常識にとらわれず意識を変える事をおすすめする。

Tips

実はIT健保メンバーでなくても一緒に店にいくことは可能である。
ただし価格は1.5倍程になるので、悔しかったら弊社に転職するんだなと煽っておこう。

入国

赤坂(寿司、和食、バー)、大久保(中華)、曙橋(イタリアン)と店によって場所が違うので注意しよう。

そしてIT健保メシの地には共通で入国書類としてIT健保の保険証が必要だ。
受付の際に求められるので忘れずに持っていこう。

ここまで来てしまえば現地の住民達(店員さん)の手厚いサポートにより食事を楽しむだけである。

筆者はアルコールを飲まないので相場感が分からないがドリンク類もかなり安い。
参考までにソフトドリンクは日本円で160円前後といった価格帯である。

ちなみに筆者はやはり寿司が一番好きであった。
SUSHI is justice.

Tips

店舗によっては料理を単品で注文することも可能なようだ。
気が付かなかった&お腹が限界でそれどころじゃなかったのであまり利用できていないが、
追加料理も安いので現地の住民の方に聞いてみよう。

番外編

ここまで読んだ読者はすでにレストランへの予約が終わっているころだろう。
そうしたら次のステップは保養施設だ。

保養施設の予約には2パターンある。
抽選か、空いている日への予約かだ。

抽選は応募期間が決まっており、決まった日程で実施されている。
といってもWeb画面からポチポチするだけなので、エンジニアなら入力の自動化をしてしまえば簡単だろう。

もう一つは空いている日への予約だ。
この画面にある空き状況確認から調べ、空いている日から予約をすれば良い。
おそらく応募が少なかったり、予約のキャンセルがあった日しか空いていないので日程の調整が難しいかもしれない。

人気の保養施設はやはり直営のトスラブ系だろう。

保養施設は1泊2食付きで5500円という破格。
そしてトスラブは追加注文も健保レストラン同様の安さとあって、基本的に抽選必須になってしまう。

抽選じゃやっぱりハードル高いな...休日なんか取れそうもないなと思われる方もいるだろう。
しかしエンジニアには必殺のカードがある。

開発合宿、もしくはワーケーションという文化だ。

これは自分と周りを納得させる、まるで魔法のような素敵な言葉。
そしてこの言葉が意味するところ、それは平日の解禁。
以前SREチームの合宿で平日利用する際にトスラブ箱根ビオーレ、和奏林(隣接してる)にメンバー4人で抽選を出したところ全員どちらかは当選した。
そういう当選率なのである。

和奏林で追加した伊勢海老

この技術を習得してしまえば、あなたの健康は促進されること請け合いだろう。

まとめ

多くの人にとって謎のヴェールに包まれていたIT健保の一端を見ることはできただろうか?

IT健保には紹介しきれなかった多くの未開地がまだまだ残されている。
我々特捜班は新たな謎を解明するため、今後もこの地で調査を進めていきたいと思う。

エンジニア募集

弊社ではSREを絶賛募集中です。
興味がある方はぜひ一度お話ししましょう!

www.wantedly.com

New Relicを用いたキャッシュ効果の推定

はじめに

この記事は、トラストバンク Advent Calendar 2023New Relic Advent Calendar 2023シリーズ3の4日目の記事となります!

こんにちは、今年でサーバーサイドエンジニア3年目となったトラストバンクの@h0r4kです。

今回の記事では、NewRelicのNRQLを利用したリクエストキャッシュの効果推定のプロセスとその際に使用したNRQLについてまとめてみました。

キャッシュ導入の動機とNewRelicによる効果推定を試みた理由

近頃、昨年私がリリースに携わった新規サービスが徐々にスケールしてきており、リリース当初よりもアクセス数が増加してきていました。

これに伴って、リリース当初よりもDBへのアクセス数も増加しており、全体へのパフォーマンス影響を考慮する必要がでてきたため、いくつかのエンドポイントについて、常にDBへのリアルタイムなSELECTが必須ではないものを対象に、Redisキャッシュを適用してみることにしました。

そんな中で、既に過去のアクセスログが集約されておりかつ、NRQLによる柔軟なログ集計が可能なNewRelicを用いて効果推定を行うことにしました。

事前準備と補足

今回の集計では、NRQLのFACET句を利用するため、事前にNewRelicのLogParsingもしくはaparse関数を用いて、url毎に集計が行えるよう準備しておきます。 (今回私はLogParsingで事前準備を行いましたが、おそらくaparseでもできるはずです。できなかったらゴメンナサイ。)

なお、今回はECSの複数コンテナから同一のキャッシュを読み書きしたいため、Elastic Cache(Redis)を使用しており、キャッシュ期間は、キャッシュ対象のエンドポイントの特性上から1分として設定しています。

キャッシュ対象のイメージ

今回キャッシュするのはお礼の品の情報を取得するエンドポイントで、URLの中にお礼の品IDを含んでいます。

GET /products/{お礼の品ID}

※URLはあくまでイメージであり実際のエンドポイントとは異なります。

実際にキャッシュ効果の推定を試みる

では実際にアクセスログからキャッシュ効果を推定してみましょう。

今回は、キャッシュ対象のエンドポイントに対して、ピーク時にどの程度キャッシュが効きそうかを調査します。

ピーク時分間最大アクセス数とその日時を算出

まずは、下記のNRQLを用いて、キャッシュ対象のエンドポイントの分間最大アクセス数とその日時を確認します。 (分間アクセス数を見たいのでTIMESERIESMINUTEに設定しています)

SELECT count(*) FROM Log WHERE 【リクエスト絞り込み条件】 TIMESERIES MINUTE LIMIT MAX SINCE 開始日時 UNTIL 終了日時

ピーク時の重複リクエスト有無の確認

次に、先程確認したピーク1分の中で、実際に重複したリクエストがあったかどうかをざっくり確認します。

SELECT count(*) FROM Log WHERE リクエスト絞り込み条件 FACET url LIMIT MAX SINCE 開始日時 UNTIL 終了日時

今回は、重複したリクエストがあったようなので次のステップに進みますが、もしここで重複したリクエストがなければキャッシュを行っても効果が見込めないので、キャッシュ期間を伸ばせないか等別途検討が必要となります。

ピーク時1分以内に重複してリクエストのあったURLの数を集計

ここでは、ピーク時の1分以内に2回以上リクエストが発生したURLを集計します。

SELECT count(count) AS '重複のあるリクエストの数' FROM (SELECT count(*) FROM Log WHERE リクエスト絞り込み条件 FACET url LIMIT MAX) WHERE count >= 2 SINCE 開始日時 UNTIL 終了日時

ピーク時1分以内に重複してリクエストのあったリクエスト数を集計

次にこちらでは、先程の集計した重複のあったURLに対して、合計で何件のリクエストが発生したのかを集計します。

SELECT sum(count) AS '重複のあるリクエストの実行回数の合計' FROM (SELECT count(*) FROM Log WHERE リクエスト絞り込み条件 FACET url LIMIT MAX) WHERE count >= 2 SINCE 開始日時 UNTIL 終了日時

集まった情報からピーク時のキャッシュヒット率を推定

では実際に集めた情報から、ピーク時のキャッシュヒット率の推測値を算出します。 計算式は下記のとおりです。

ピーク時キャッシュヒット率の推測値 = (ピーク時に重複してリクエストのあったリクエスト数の合計 - ピーク時に重複してリクエストのあったURL数) / ピーク時分間最大アクセス数

なお、今回の記事の検証に利用したデータでは、ピーク時のキャッシュヒット率は約43.96%と算出されました。 (キャッシュ期間を伸ばせばもう少しヒット率も上がりそうですね)

終わりに

今回の記事では、NewRelicの簡単なNRQLを用いてキャッシュ効果を推定してみました。

実際にNRQLを作成してみたところ、案外簡単なNRQLで集計を行うことができましたが、私自身不慣れなのもあり、実際にはNRQLを作成するまでになかなか時間がかかってしまいました。

今回はキャッシュ期間を1分として決め打ちで推定してみましたが、今後はキャッシュ期間を変数化してキャッシュ効果の推定ができれば面白いなと思いました。

最後までご覧いただきありがとうございました!

エンジニア募集

弊社では絶賛エンジニア募集中ですので、気になった方は是非ご連絡ください!

www.wantedly.com

控除額シミュレーションのnpmライブラリを公開しました

この記事は、トラストバンク Advent Calendar 2023の3日目です。

お疲れさまです。フロントエンドエンジニアの片柳です。
先日、トラストバンクからふるさと納税の控除額シミュレーションライブラリfurusato-tax-simulationがリリースされましたので、紹介と実装時に考えたことなどを紹介できればと思います。

www.npmjs.com

なぜライブラリを作るのか

トラストバンクが提供するふるさと納税サイト「ふるさとチョイス」では、2種類の控除上限額シミュレーションを提供しています。

「家族構成」「年収」から簡単に上限額を知ることができる簡易シミュレーション。

簡易シミュレーション

源泉徴収票を利用して、より細かな上限額を知ることができる詳細シミュレーション。

詳細シミュレーション

これらはJavaScriptを用いて各ページに実装されています。
ふるさとチョイスの他にも、トラストバンクが提供する多くのウェブサイトやアプリの中で、それぞれが独自の実装を行い、運用を行なっています。

私たちが支払う税金や、ふるさと納税にまつわる法律は日々更新されていきます。
シミュレーション結果が変わるたび、各サービスの運用者がそれぞれで修正を行うのでは手間も時間もかかります。
また、新しくふるさと納税サイトを立ち上げたいと考えているパートナーが、0から控除上限額計算の資料を読み解いてシミュレーションを作成することは難しく、「控除上限額シミュレーションを掲載したいのにできない」と、ハードルを生むことにも繋がっていました。

すべてのサービスの運用工数を下げたい社内と、従来よりも簡単に控除上限額シミュレーションを実装したい社外の双方に向け、furusato-tax-simulationは作成されました。

どうやってライブラリを作るのか

以前、社内向けのライブラリとして、eslint-config-trustbankを公開したことがあった*1ため、npmライブラリの作成方法については大まかに知見がありました。
(「トラストバンクのフロントエンドを支える(予定の)ESlint」もぜひご一読ください) tech.trustbank.co.jp

index.jsを作成するだけでよいESLintのコンフィグとは異なり、今回のライブラリでは

  • TypeScriptをコンパイル
  • 複数のファイルを1つにまとめ上げ
  • ES Modules/Common.jsなど、環境ごとに異なる記法になるように書き分ける

といった作業が必要となります。
月並みですが、Rollup.jsを用いて環境構築を行いました。

Rollup.jsをベースとしたビルドツールとして有名なViteにも、ライブラリのためのJavaScriptを書き出すための専用モードがありますが、今回は利用していません。
想定通りの書き出しを行うためにはVite上でRollup.jsの設定情報を上書きする必要があり、それなら最初からRollup.jsを利用したほうがシンプルだろうと判断しました。

具体的な設定はrollup-minimum-setupにアップロードされていますので、興味がある方はぜひご覧ください。
今回のライブラリも、このリポジトリをフォークして作成しました。

github.com

バージョン管理と運用保守

一度公開したnpmパッケージを更新するためには、必ずバージョンを更新しなくてはいけません。
npmにはいくつかのバージョンアップコマンドが存在するため、更新の規模によって、以下のように使い分けるように運用方針を定めました。

コマンド バージョンの変更 対応する更新
npm version patch 1.0.0 -> 1.0.1 関数から返却される数値やレスポンスの形が変わらない軽微な修正
npm version minor 1.0.0 -> 1.1.0 計算式の更新など、関数から返却される数値が変わる修正
npm version major 1.0.0 -> 2.0.0 関数から返却されるレスポンスの形変わる修正

furusato-tax-simulationのこれから

現在は、簡易シミュレーション・詳細シミュレーションともに、計算結果のみが返される小さなライブラリです。
社内に散らばっているシミュレーションをこのライブラリに変更する作業を進めつつ、必要なレスポンスや関数の追加、使いやすさの向上を目指します。

furuasto-tax-simulationは、MITライスセンスで公開されており、ライブラリを実装したリポジトリも、近日中に公開予定です。
たくさんの方のご利用、IssueやPRの作成もお待ちしております。

最後に

トラストバンクでは、一緒に働く仲間を募集中です。

www.wantedly.com

トラストバンク Advent Calendar 2023は、@h0r4kの「New Relicを用いたキャッシュ効果の推定」に続いていきます。
ぜひお楽しみに。

Cloudflare WaitingRoomでサーバーリソース過負荷を予防した話

おいしい秋刀魚で秋を感じているSREのbutadoraです。

直近、過負荷対策としてCloudflare WaitingRoomを導入したので紹介します。

背景

ふるさと納税の制度改正

ふるさとチョイスのトラフィック特性により、通常12月が1年で最もトラフィックが伸びる時期で*1

年をまたぐ直前の12月31日にピークを迎えます。

しかし、今年は2023年10月1日に制度改正が実施されました。

www.soumu.go.jp

これに伴い、制度改正前の9月30日に年末相当のトラフィックが予測され、

急遽年末のスケールアップとスケールアウトを前倒しで実施する必要が生じました。

想定以上のアクセス増

制度改正の約1週間前、某テレビ番組で制度改正が取り上げられ、急激なアクセス数の増加が発生しました。

これにより、各種リソースは昨年大晦日相当の負荷状況に達しました。

1週間前の時点で想定以上のアクセス状況となっており、

スケールの限界に備えるための手段としてCloudflare WaitingRoomの導入を決めました。

Cloudflare WaitingRoomとは?

Cloudflare WaitingRoomは、文字通り「待合室」を実現するツールです。

これを使うことで、サービスにインフラリソースの限界を超えてユーザーがアクセスしてきた際に、

Cloudflareが提供する待機画面に誘導することで、サービスへの流入を制限することができます。

www.cloudflare.com

導入の決め手

  • すでにCloudflare(DNS Proxyモード)を使用していたこと
  • 契約中のプランにWaitingRoomが含まれており、追加費用が発生しなかったこと
  • 数日以内に対策を実施する必要があったこと
    • WEBコンソール上で簡単に検証し、すぐに利用できることを確認
    • (検証から導入まで3日で完了することができた🚀)

設定の勘どころ

詳細な設定方法は公式ドキュメント *2 をご覧いただくとして、 ユーザーがWaitingRoom入るための条件に必要なパラメータがいくつかあります。

Total active users(総アクティブユーザー数)

WaitingRoomが発動する条件の一つで、アクティブユーザー数がこのしきい値を超えることが目安です。

当初、Google Analyticsのアクティブユーザー数を基準にしようとしていましたが、

後述のセッション時間の定義により、ここでの「アクティブユーザー」の意味が変わることが分かりました。

したがって、最初は大きな値からスタートし、Cloudflareのダッシュボードに記録されるメトリクスを追いながら微調整しました。

New users per minute(1分間あたりの新規ユーザー数)

これは総アクティブユーザー数とは別に、急激なアクセス増加時にWaitingRoomを迅速に発動させるためのしきい値です。

前述の急激なアクセス数増加が発生した際のアクティブユーザー数について、 増加傾向をGoogle Analyticsから算出し、その値を設定しました。

結果としてはWaitingRoom導入以降に急激なアクセス増は発生することはなかったため、 このパラメーターをトリガーとしたWaitingRoom発動はありませんでした。

Session duration(セッション時間)

ユーザー1人あたりが対象のサイトに滞在している時間をSession Cookieで計測しています。

こちらも総アクティブユーザー数同様、最初は大きな値からスタートし、 Cloudflareのダッシュボードに記録されるメトリクスを追いながら微調整していきました。

導入効果

結論としてはWaitingRoomのおかげでサービスダウン無く、9月30日を過ごすことができました!🎉

当日はリアルタイムでアクティブユーザー数をウォッチしつつ、パラメーターチューニングしながら見守ってました。

アクセス数は昨年末を上回りましたが、WaitingRoomのおかげでアプリケーションへのユーザー流入を制御でき、過負荷を未然に防ぐことができました。

まとめ

今回、スケールアウトやスケールアップ以外の観点でもサービスへのアクセス増に対処し、 ユーザー体験の低下を最小限に抑えることができました。

ただし、これは過負荷対策の一手段ではあるため、年末に予想される次のアクセス増に向けてアプリケーションやインフラリソースのチューニングを弊社エンジニア一丸となって取り組んでおります!💪

参考記事

以下クラスメソッドさんの記事のお陰で、WaitingRoomのパラメーター設定や発動条件理解が捗りました! ありがとうございます🙏

dev.classmethod.jp

dev.classmethod.jp

エンジニア募集

弊社ではSREを絶賛募集中です。 興味がある方はぜひ一度お話ししましょう!

www.wantedly.com

半角英数が改行されない原因と対処方法

フロントエンドチームの君田(きみた)です。

本日は半角英数が改行されない原因とその対処方法に関して書いていこうと思います。 要素の横幅は指定しているのに、半角英数がその要素のないに収まってくれない!という事象を今更ながら経験しました。 そんなときに少しでも役に立てれば嬉しいです。

なぜ半角英数は改行されないのか?

タイトルでは直面する状況がわかりやすいように書きましたが、「半角英数が改行されない」は実際は正しくないです。 正確には「長すぎる半角英数の単語がある場合に改行されずに要素幅を超えて表示されてしまう」ということが起こっています。

CSS では、非常に長い単語などの切れない文字列がある場合、既定ではインライン方向に小さすぎるコンテナからはみ出します。

ということなのです。 例えば以下のようなコードを書いてみるとわかりやすいです。

<div class="box">veryLongSequenceOfEnglishWordsveryLongSequenceOfEnglishWordsveryLongSequenceOfEnglishWordsveryLongSequenceOfEnglishWords</div>
.box {
  background-color: yellow;
  width: 200px;
}

これをブラウザで表示してみると以下のようになります。

背景を黄色にしている部分の横幅を指定していますが、テキストが改行されずに表示されてしまっています。 これはテキストが1単語と認識されているので、改行されていないのです。テキスト中に半角スペースを入れることで改行はされますが、今回は指定した横幅に対して、テキストが長すぎるので、単語区切りにしたところで要素からはみ出して表示されてしまいます。

<!-- 単語区切りで半角スペースを挿入 -->
<div class="box">veryLongSequenceOfEnglishWords veryLongSequenceOfEnglishWords veryLongSequenceOfEnglishWords veryLongSequenceOfEnglishWords</div>

次から本題の半角英数が改行されない対処方法を書いていきます。

半角英数が改行されない対処方法

対象の要素にoverflow-wrapもしくはword-breakを指定します。 overflow-wrapword-breakはどちらも改行を指定するCSSプロパティです。 実際に使用した例は以下になります。

<div class="box1">veryLongSequenceOfEnglishWordveryLongSequenceOfEnglishWordsveryLongSequenceOfEnglishWordsveryLongSequenceOfEnglishWords</div>
<div class="box2">veryLongSequenceOfEnglishWordveryLongSequenceOfEnglishWordsveryLongSequenceOfEnglishWordsveryLongSequenceOfEnglishWords</div>
div {
  background-color: yellow;
  margin: 50px 0;
  width: 100px;
}

.box1 {
  word-break: break-all;
}

.box2 {
  overflow-wrap: break-word; 
}

どちらを使用しても、指定した要素の横幅に収まるように表示できるようになりました! これで半角英数が改行されないことは解決できました!

overflow-wrapとword-breakの違いは?

先ほどのHTMLを以下のように書き換えてみましょう。

<div class="box1">This is veryLongSequenceOfEnglishWords</div>
<div class="box2">This is veryLongSequenceOfEnglishWords</div>

どちらもテキスト内に空白スペースを挿入し、単語で区切られていることを示しています。 CSSは変更せずにテキストのみを変更した場合、以下のような表示になります。

改行位置が異なっているのがわかると思います。

  • word-breakの場合 1行で収まらない長い単語がある場合でも要素の横幅いっぱいまで表示し、折り返し表示

  • overflow-wrapの場合 要素の横幅いっぱいに収まるようにテキストが表示されるが、1行で収まらない長い単語があった場合は改行される

上記のような違いがあります。実装する画面の表示要件によって使い分けが可能です。

最後に

弊社トラストバンクでは様々な職種で絶賛採用中です! 気になった方、是非お気軽にご連絡ください!

www.wantedly.com

SRE4人目としてジョインしました!

2023年1月より、SREの4人目としてジョインしたyoshiroooooです。

あっという間に3ヶ月の試用期間が過ぎましたが、ジョインするまでの経緯や、ジョインしてからやったこと、感じたことをまとめます!

入社する前から、自分の一発目の記事として、こういうタイトルで書くんだ!、という気持ちがあったんですが、「まぁ試用期間あけてからかな、、、」と思い、今です。

ジョインするまで

前職では、マッチングサービスに携わっていて、そこでもSREやっていました。

これからサービスが成長するぞ、というところから携わるようになり、トラフィックが増え、その中でパフォーマンスチューニングや障害対応など、SREとして良い経験を積ませてもらいました。

良い歳になってきて、今後のワークライフバランスを考えた時に、コロナ禍をきっかけに始まったフルリモート作業でも十分に仕事ができると感じ、転職を考え始めるようになりました。

もちろん、エンジニアとしてのレベルもまだまだ高めたいというも気持ちもあってですが。

そんな中で出会ったのがトラストバンクで、自立した持続可能な地域を実現するために展開している事業・サービスが良いなと思ったこと、また、下記のあたりがポイントでこの会社で働いてみたいと思い、入社させてもらいました。

あと、僕はAWSが好きなんですが、≪TB INTERVIEW≫の記事に「とにかくAWSを弄り倒したい方」ということも書かれていて、弄りたいぞ!と思ったのもあります。

やったこと

正直、まだまだキャッチアップ段階で、そこまで立派にかけることはないんですが(滝汗)、ちょっと挙げていきます。

インフラ構成の把握

自分が所属するSREは、組織を横断してインフラを支えたり、開発者体験を向上させたりしていくのですが、会社が成長しているフェーズで、新しい事業も立ち上がっていることもあって、システムが多いです。。。

2022年の途中までは、SREが2人ということもあって、だいぶリソースが限られていたと思うんですが、そんな中でもインフラ構成図など資料はあったので、まずはその辺りを一通り見ていきました。

これはいきなり全てを把握することは難しいかも、、、と思い、面倒見ているシステムを整理して、SREメンバーに時間をもらって、サービス影響の大きさなどから把握していく優先順位をつけて、把握することにしました。

弊社では基本的にフルIaCを進めていることもあり、コード(Terraform・Ansible)を見ればわかることが多かったので、その点は助かりました。

アラート調査とその対策

インフラ構成を把握する時は、先に挙げたような座学や資料からの環境確認も必要ですが、ボリュームが多いと、全部を把握するのは大変。。。

そこで、自分の場合は、調査や分析をすることが好きというのもあるのですが、検知したアラートは基本的に全て原因調査し、一時的な事象でないなら、対策するところまでやるようにしています。

既知のアラートというのもあって、サービスに影響がなく、そのまま保留状態になっているものもありましたが、新人の自分にとっては既知とかありませんので、とにかくissueを立てて調査させてもらいました。

そうすると当たり前ですが、原因調査することになり、インフラやアプリケーションの構成を把握しないといけないので、自動的に?インプットされますw

血となり肉となる、ような感じです。

いくつか対策して、止まったアラートもありますが、これからもアラートノックを受けていきたいと思います(違う)

そもそも不要な監視設定があるかもしれませんので、それは見直したり、抜本的にインフラ構成などの改善が必要なら、それは対策していきます。

ドキュメント整理

先に書いた通り、SREのリソースは限られている中で、けっこうなスピードでインフラや開発の環境が変わってきているのですが、ドキュメントが追いついていません。。

なので、自分が入社して新鮮な感じでいる間に、用意しておいた方が良いと思うドキュメントを洗い出し、SREメンバーの中で話し合い、用意するもの・しないものを決めました。

(Terraformのコードやプルリク(なぜその実装にしたか)を見ればわかるものはドキュメント化しない、など)

ドキュメントは重要ですが、全部をドキュメント化することで、今度はそのドキュメントを更新するという工数が発生し、いつの間にかまたドキュメントが陳腐化するということになりかねませんので。。

そこからissueを立てて、今後、時間を確保して、不足している・古くなっているドキュメントを作成・更新します。

AWS移行

ふるさとチョイスを取り巻くインフラ環境2022 - トラストバンクテックブログ の記事にもありますが、大半のサービスの本番環境はさくらのクラウドで稼働しています。

これを徐々にAWSへ移行していこうと準備を進めていますが、そのうちのOEMサイトの移行を進めました。

インフラの移行になるので、慎重に進め、そして有事の際には即切り戻し、サービス影響のリスクを軽減したいところですが、そんな時に利用したのが、Cloudflareのロードバランシングです。

さくらとAWSの2つのクラウドに対して、トラフィック割合を調整することができて、稼働確認しながら、徐々にAWSトラフィックを寄せるということができます。

このおかげでカナリアリリース的な移行ができました!

どんなリリースも障害ゼロと言い切ることはできませんので、いざ障害が出た時に、落ち着いて切り戻してサービス復旧する必要があります。

この安心感があるだけで、どんなリリースも怖くありません・・・!

感じたこと

フルリモートでもコミュニケーションは大丈夫そう

前職でもリモート作業でしたが、出社するケースもあり、フルリモートでの作業は初めてでした。

普段一緒に作業するメンバーとのコミュニケーション面でどうかな、と思ったんですが、割と良い感じでコミュニケーションが取れています。

自分が所属するSREは、日々朝会でタスク確認や課題共有などしていますが、ゆるい雑談の時間もあったりして、仕事以外の面でも話すことがあるので、フルリモートの中でも関係値も高められているのかなと思っています。

フルリモートだからこそ、ということもありませんが、個人的にはやっぱり雑談も大事かなと。

たまにはオフラインで飲み会もあったりします!(自分が入社してからは、毎月のようにオフラインで会っている気がする。。)

メンバーに恵まれている

転職する際のポイントの1つに、誰と、どんなチームで働けるかとということを重要視していましたが、面接でのフィーリングは間違っていなくて、SREメンバーは話しやすい感じで、忙しい中でも良い雰囲気で作業できています。

転職先でどんなに自分がやりたいことがあっても、たとえば、一緒にやっていくメンバーが相手のことを考えない人だったり、チームプレーの面では協力体制がないと、困難な場面を乗り越えることが難しいと思っています。

まだ入社してから浅く、コミュニケーション取れていない方もいますが、少しずつ他部署のメンバーと話すケースも増えてきていて、そこでも話しやすい雰囲気があるかなと思っています。

とりあえず試してみる文化って好き

やっぱり新しい技術は気になるので、とりあえず試してみて、結果、運用工数の削減に繋がったり何か効果が見込めるなら、工数とのバランスもありますが、個人的には、とりあえず試してみる、は良いと思っています。

逆に思ったようなことができなかった時は、捨てるくらいの気持ちで。

この文化が弊社のSREにはあると思っていまして、提案・相談しやすい雰囲気があります。

ビジネス面で何かしらの課題があって、それを解決するための技術で、手段でしかない、という話もありますし、たしかにその通りだと思いますが、技術面で見つけた「こんなのがある」から課題解決につながることもあると思いますので、この雰囲気が好きです。

今後

3人目のSREとしてジョインして半年やってきた話 - トラストバンクテックブログの記事にもありますが、Toilの自動化や監視周りの整備などやること盛り沢山です・・・!

まずはToilの自動化を進めることで、リソースを確保しつつ、サービスの信頼性や開発者体験の向上に積極的に取り組んでいきたいと思います。

その先にまた何か新しい景色が見えてくるはず。。

そして、これは良い!と思った改善事例などはこのブログで紹介できたらと思います。

最後に

弊社ではSREを絶賛募集中です!

ふるさと納税の市場規模は大きく、今後も成長していくことが見込まれていますが、トラフィックも増大していきます。

そんな中で、パフォーマンス改善や、会社の戦略方針に応える開発スピードの向上などが求められますし、やるべきことは沢山あります。

このフェーズでトラストバンクにジョインし、自分達で変えていければ、間違いなく良い経験になりますし、その先には新たなチャレンジができるステージがあるかもしれません!

「仕事の報酬は仕事」っていうやつですw

今回のこちらの記事やリンクの記事を見て、少しでもトラストバンクに興味が出てきましたら、お気軽にカジュアル面談に申し込んで頂けたら幸いです!

www.wantedly.com