TECH PLAY

KINTOテクノロジーズ

KINTOテクノロジーズ の技術ブログ

969

Introduction Hello, this is Adegawa from KINTO Technologies New Vehicle Subscription Development Group. As an application engineer, I have been in charge of the development, maintenance, and the operation of KINTO ONE, a Toyota New Vehicle subscription service in Japan for three years. I love cars, so I am very happy that my work allows me to be part of it. At the moment, I am prioritizing my family, so I am driving a minivan, but I would like to ride a Toyota GR someday! My favorite engine mechanism is the cam gear train! Let me share today a couple of projects that I've found particularly fulfilling and accomplished. Preparing for the launch of the new Prius January 10 2023 marked the new Prius (5th generation) launch. Prius is a model that attracts attention even within Toyota, which has established itself as an eco-friendly vehicle at the forefront of hybrid vehicles. However, the Prius (predecessor) at the time the project was launched was not particularly popular among the KINTO ONE models, partly because it had already been released for a long time. So, personally, I did not think that the response would be particularly large even if the new model came out. But the goal was to withstand*, 990 PV/min! (This number is 10 times higher than the highest load ever.) At that time, we were only about 3% of our target. There are three main countermeasures. Countermeasure 1: adjusting the connection endpoint of the database RDB was configured with a writer instance and a reader instance. However, due to the access of the reference system being overwhelmingly large from the front, the load was biased on the reader instance, and the writer one had more room. We tentatively changed the setting to connect to the writer instance regardless of reference or update destination from the front. As a result, the load was balanced as intended. Since it was easier than adding a reader instance, I adopted this method first. Countermeasure 2: quotation screen improvement The next most visited screen after the top screen is the quotation screen for each car model. Here, we select car grade, package, option, etc., and we obtained the vehicle master information from the relational database table. This has been optimized to retrieve from the vehicle master information stored in the in-memory key/value cache (redis in Elasticache) to reduce DB load and improve front response. Next, the information that could not be cached was used to identify the high DB load. From quotation to application, I consult the master table containing dealer store information along with vehicle details. While no issues arise in terms of slow queries, there is a notable volume of transactions, resulting in cumulative effects. To address this, I introduced an index to the specific high-cost target table, leading to a significant improvement in query performance, with costs now reduced to single digits. Countermeasure 3: infrastructure enhancement In addition to the above measures, we made adjustments by reviewing the infrastructure structure so that we can withstand the target values of 1and 2. As a special temporary response, we increased the infrastructure as follows by manual scaling. Scale out AWS service Quantity - before change Quantity - after change EC2 Front End 6 36 EC2 Back End 2 15 Scale up AWS service Type - before Change Type - changed to EC2 Scale out only Elasticache t3.medium r6g.large RDS r5.xlarge r5.12xlarge Miscellaneous To proactively handle a sudden surge in access, it's crucial to pre-warm the ALB (Application Load Balancer). We submitted a request to AWS, providing the following information for the pre-warming operations: Expected peak hours The number of requests expected during the peak hour Traffic pattern Use cases etc. On the day of release As for the load, the actual access was about 10% at the peak compared to the allowable range that was prepared, but it was stable from the day of release without any trouble. The response from customers was good, and the influx (quotation and application) of the entire Prius, including the KINTO exclusive grade, seems to have been as expected. The part that had been tentatively responding after watching the transition for a while was calm was restored and finished. Finally It was a rare big event, so I think it was a very valuable experience. Whenever I saw a Prius in the city, I was curious and couldn’t help but follow them with my eyes. Could this be a KINTO one? Looking at the results, it seems that the specifications of the infrastructure were excessive, but I think it was good because it was impossible to accurately predict the inflow in advance and there was no room for mistakes. Despite the busy period from the end of the year to the beginning of the new year, I think that I was able to overcome it safely thanks to the cooperation of many colleagues. Service providers who managed the load test plan and schedule. A team member from the oncoming system who took care of the service outage due to server expansion. We received advice from Platform G team members regarding infrastructure expansion. I also want to express my gratitude here. Thank you very much.
アバター
こんにちは。 DBRE チーム所属の @p2sk です。 DBRE(Database Reliability Engineering)チームでは、横断組織としてデータベースに関する課題解決や、組織のアジリティとガバナンスのバランスを取るためのプラットフォーム開発などを行なっております。DBRE は比較的新しい概念で、DBRE という組織がある会社も少なく、あったとしても取り組んでいる内容や考え方が異なるような、発展途上の非常に面白い領域です。 弊社における DBRE チーム発足の背景やチームの役割については「 KTC における DBRE の必要性 」というテックブログをご覧ください。 本記事では、Aurora MySQL でロック競合(ブロッキング)起因のタイムアウトエラーが発生した際に根本原因を特定することができなかったので、原因を後追いするために必要な情報を定期的に収集する仕組みを構築した事例をご紹介します。尚、考え方自体は RDS for MySQL や、AWS 以外のクラウドサービスの MySQL の PaaS および、MySQL 単体にも適用できるものかと思いますので参考になりましたら幸いです。 背景 : ブロッキング起因のタイムアウトが発生 プロダクトの開発者から「アプリケーションのクエリタイムアウトが発生したため調査して欲しい」という問い合わせを受けました。エラーコードは SQL Error: 1205 とのことで、ロック獲得の待ち時間超過によるタイムアウトだと思われます。 弊社では、 Aurora MySQL のモニタリングに Performance Insights を使用しており、該当の時間帯のデータベース負荷を確認すると、確かに行ロック獲得待ちの時に発生する待ち事象「 synch/cond/innodb/row_lock_wait_cond 」が増加していました。 Performance Insights ダッシュボード : ロック待ち(オレンジ色)が増加している Performance Insights には「 トップ SQL 」というタブがあり、任意の時間帯における「DB 負荷の寄与率が高い順」で実行されていた SQL を表示してくれます。こちらも確認すると下図のように UPDATE SQL が表示されましたが、タイムアウトした SQL、つまりブロックされている側の SQL だけが表示されている状況でした。 トップ SQL タブ  : 表示された UPDATE ステートメントはブロックされている側のもの 「トップ SQL」は、例えば CPU 負荷が高いような状況下では、その寄与率が高い SQL を特定するのに大変便利な機能です。一方で、今回のようなブロッキングの根本原因を特定したい場合には有用ではないケースもあります。なぜなら、ブロッキングを起こしている根本原因の SQL(ブロッカー)自体は、それ単体ではデータベース負荷をかけていない場合もあるためです。 例えば、あるセッションで以下の SQL が実行されたとします。 -- クエリ A start transaction; update sample_table set c1 = 1 where pk_column = 1; このクエリは Primary Key を指定した単一行の更新クエリのため、非常に高速に終了します。しかし、トランザクションを開いたままになっており、この後に別のセッションで以下の SQL を実行すると、ロック獲得待ちとなりブロッキングが発生します。 -- クエリ B update sample_table set c2 = 2 クエリ B はブロッキングされ続けるため、待ち時間が長くなり「トップ SQL」に表示されます。一方でクエリ A は瞬時に実行が完了しており「トップ SQL」に表示されず、MySQL のスロークエリログにも記録されません。 この例は極端ですが、Performance Insights を用いたブロッカーの特定が難しいケースをご紹介しました。 一方で、Performance Insights でもブロッカーを特定できるケースはあります。例えば同一の UPDATE SQL が大量に実行されることで「Blocking Query = Blocked Query」となる状況です。この場合は Performance Insights で十分です。しかしブロッキングの発生原因は多様であり、現状の Performance Insights だと限界があります。 今回発生したインシデントも、Performance Insights ではブロッカーを特定できず、各種ログから原因の特定を試みました。Audit Log / Error Log / General Log / Slow Query Log の各種ログを確認しましたが、原因を特定できませんでした。 今回の調査を通して、現状だとブロッキングの原因特定を後から実施するための情報が不足していることが分かりました。しかし、今後同じような事象が発生しても「情報が不足しているため原因は分かりません」と回答するしかない状況は改善すべきです。したがってブロッキングの根本原因を特定するために「ソリューションの調査」を行うことにしました。 ソリューションの調査 この問題を解決するためにどうしたらいいか、下記について調査を行いました。 Amazon DevOps Guru for RDS 監視系 SaaS DB 系の OSS、DB モニタリングツール 以降、それぞれについて説明します。 Amazon DevOps Guru for RDS Amazon DevOps Guru は、監視対象の AWS リソースのメトリクス・ログを機械学習を使って解析し、パフォーマンスや運用上の問題を自動で検出し、問題の解決策に関する推奨事項を提案してくれるサービスです。 DevOps Guru for RDS は、DevOps Guru における DB の問題検出に特化した機能です。Performance Insights との違いとしては、DevOps Guru for RDS は自動で問題分析と解決案の提示まで行ってくれる点が挙げられます。「インシデント発生時の課題解決までマネージドに」という世界を実現したい AWS の思想が伝わってきます。 実際にブロッキングを発生させると、以下のような推奨事項が表示されました。 DevOps Guru for RDS の推奨事項 : 調査すべき待ち事象と SQL を提案 表示されている SQL はブロックされている側の SQL であり、ブロッカーの特定は難しそうでした。現状は「synch/cond/innodb/row_lock_wait」という待ち事象が DB 負荷に寄与している場合の調査方法を記した ドキュメントへのリンク を提示するにとどめているようです。したがって現状は提案された原因や推奨事項を、人間が最終的に判断する必要がありますが、将来的にはよりマネージドなインシデント対応の体験が提供されるようになるのではと感じています。 監視系 SaaS データベースのブロッキング原因を SQL レベルで調査できるソリューションとしては、 Datadog のデータベースモニタリング機能 があります。しかし、現時点では PostgreSQL と SQL Server にのみ対応しており、 MySQL には対応していません。また、 New Relic や Mackerel においても同様にブロッキングの事後調査を実施できる機能は提供されていないようでした。 DB 系の OSS、DB モニタリングツール 他にも、以下の DB 系の OSS、DB モニタリングツールについて調査しましたが、ソリューションは提供されていないようでした。 Percona Toolkit Percona Monitoring and Management MySQL Enterprise Monitor 一方、今回の調査で唯一 MySQL のブロッキング調査のソリューションを提供している可能性があるのが SQL Diagnostic Manager for MySQL でした。こちらは MySQL 用の DB モニタリングツールですが、今回の要件に対して機能がリッチすぎるのと、それに伴い価格面がネックとなり検証および導入を見送りました。 本調査を踏まえて、ほぼ既存のソリューションが存在しないことがわかり、自前で仕組みを作ることにしました。そのため、まずは「ブロッキング原因の手動での調査手順」について整理しました。尚、Aurora MySQL のバージョン 2(MySQL 5.7 系) が今年の 10 月 31 日に EOL を迎える予定であるため、対象は Aurora 3 系(MySQL 8.0 系)とします。また、対象のストレージエンジンは InnoDB とします。 ブロッキング原因の手動での調査手順 MySQL でブロッキングの情報を確認するためには、 下記 2 種類のテーブルを参照する必要があります。注意点として、MySQL のパラメータ performance_schema に 1 をセットして performance_schema を有効化しておく必要があります。 performance_schema.metadata_locks 獲得済みのメタデータロックに関する情報が格納される lock_status = 'PENDING' なレコードでブロックされているクエリを確認 performance_schema.data_lock_waits ストレージエンジンレベルでのブロッキング情報が格納される(行など) 例えば、メタデータ起因のブロッキングが発生している状況で performance_schema.data_lock_waits を SELECT してもレコードは取れません。そのため 2 種類のテーブルに格納されている情報を併用して調査を実施します。調査には、これらのテーブルと他のテーブルを組み合わせて分析しやすくした View が存在するため、そちらを使った方が便利です。以下に紹介します。 調査手順 1 : sys.schema_table_lock_waits を活用 sys.schema_table_lock_waits は、以下の 3 つのテーブルを使った SQL を ラップした View です。 performance_schema.metadata_locks performance_schema.threads performance_schema.events_statements_current リソースへのメタデータロック獲得で Wait が発生している時にこの View を SELECT すると、レコードが返ってきます。 例えば、以下のような状況です。 -- セッション 1 : lock tables でテーブルのメタデータロックを獲得し、保持し続ける lock tables sample_table write; -- セッション 2 : 互換性のない共有メタデータロックを獲得しようとして待たされる select * from sample_table; この状況で sys.schema_table_lock_waits を SELECT すると以下のようなレコードセットが取得できます。 この View の結果からは、直接ブロッカーとなっている SQL を特定することはできません。 waiting_query カラムでブロックされているクエリは特定できますが、 blocking_query カラムは無いため、 blocking_thread_id または blocking_pid を用いて SQL を特定します。 ブロッカーの特定方法 : SQL ベース SQL ベースでブロッカーを特定する場合、ブロッカーのスレッド ID を用います。 performance_schema.events_statements_current を用いた以下のクエリを実行することで、該当スレッドが最後に実行していた SQL テキストを取得できます。 SELECT THREAD_ID, SQL_TEXT FROM performance_schema.events_statements_current WHERE THREAD_ID = 55100\G 実行結果は、例えば以下のようになります。sample_table への lock tables を実行していたことがわかり、ブロッカーを特定できました。 この方法には欠点があります。ブロッカーがロック獲得後に追加で別のクエリを実行した場合、その SQL が取得されてしまうためブロッカーが特定できません。例えば、以下のような状況です。 -- セッション 1 : lock tables でテーブルのメタデータロックを獲得し、保持し続ける lock tables sample_table write; -- セッション 1 : lock tables 実行後、別のクエリを実行 select 1; この状態で、同様のクエリを実行すると以下の結果となります。 別の方法として performance_schema.events_statements_history を用いると、該当スレッドが過去に実行した直近 N 件の SQL テキストを取得できます。 SELECT THREAD_ID, SQL_TEXT FROM performance_schema.events_statements_history WHERE THREAD_ID = 55100 ORDER BY EVENT_ID\G; 結果は以下のようになります。 履歴が取得できるためブロッカーも特定できました。スレッドあたり何件 SQL 履歴を保持するかは performance_schema_events_statements_history_size パラメータで変更できます(検証時は 10 を設定)。サイズを大きくするほどブロッカーの特定確率は上がりますが、使用するメモリサイズも増えることと、どれだけサイズを大きくしても限界はあるため、バランスが重要となります。なお、履歴の取得が有効化されているかどうかは performance_schema.setup_consumers を SELECT することで確認できます。Aurora MySQL の場合 performance_schema.events_statements_history の取得はデフォルトで有効化されているようです。 ブロッカーの特定方法 : ログベース ログベースでブロッカーを特定する場合、General Log や Audit Log を用います。例えば Aurora MySQL で General Log の取得を有効化している場合、CloudWatch Logs Insights で以下のクエリを実行することで、該当プロセスが実行した SQL の履歴を全て取得できます。 fields @timestamp, @message | parse @message /(?<timestamp>[^\s]+)\s+(?<process_id>\d+)\s+(?<type>[^\s]+)\s+(?<query>.+)/ | filter process_id = 208450 | sort @timestamp asc このクエリを実行すると、以下のような結果を得ることができます。 CloudWatch Logs Insights のクエリ実行結果 : 赤枠で囲まれた SQL がブロッカー 弊社では基本的に General Log の取得を有効化しています。SQL ベースだとブロッカーが履歴テーブルから削除されて特定できない懸念があります。したがって今回はログベースでの特定方法を採用することにしました。 ブロッカー特定における留意事項 ブロッカーの特定には、最終的には人間の目視確認と判断が必要です。理由としては、ロックの獲得情報はあくまでスレッドと直接紐づいており、スレッドが実行している SQL は時事刻々と変化していくからです。したがって例示したような「ブロッカーがクエリを実行し終わっているがロックは獲得している」状況の場合、ブロッカーのプロセスが実行した SQL の履歴から、根本原因となる SQL を推測する必要があります。 とはいえ、ブロッカーとなるスレッド ID やプロセス ID が分かるだけでも、根本原因の特定率の大幅な向上が期待できます。 調査手順 2 : sys.innodb_lock_waits を活用 以下の 3 つのテーブルを使った SQL を ラップした View です。 performance_schema.data_lock_waits information_schema.INNODB_TRX performance_schema.data_locks ストレージエンジン(InnoDB)で実装されているロックの獲得で wait が発生している時にこの View を Select すると、レコードが返ってきます。 例えば、以下のような状況です。 -- セッション 1 : レコードを UPDATE したトランザクションを開きっぱなしにしておく start transaction; update sample_table set c2 = 10 where c1 = 1; -- セッション 2 : 同一レコードを更新しようとする delete from sample_table where c1 = 1; この状況で sys.innodb_lock_waits を SELECT すると以下のようなレコードセットが取得できます。 この結果からは sys.schema_table_lock_waits の時と同様に、直接ブロッカーを特定することはできません。したがって blocking_pid を用いて前述のログベースの方法でブロッカーを特定します。 fields @timestamp, @message | parse @message /(?<timestamp>[^\s]+)\s+(?<process_id>\d+)\s+(?<type>[^\s]+)\s+(?<query>.+)/ | filter process_id = 208450 | sort @timestamp asc このクエリを実行すると、以下のような結果を得ることができます。 CloudWatch Logs Insights のクエリ実行結果 : 赤枠で囲まれた SQL がブロッカー ここまでのまとめ Aurora MySQL のブロッキングの根本原因を事後調査できる状態にするための第一歩として、ブロッキングが発生している時の根本原因の調査方法を整理しました。調査手順は以下の通りです。 sys.schema_table_lock_waits と sys.innodb_lock_waits という 2 種類の View を用いてブロッカーのプロセス ID を特定 CloudWatch Logs Insights を使って General Log から、該当のプロセス ID の SQL 実行履歴を取得 目視で確認しながら、根本原因となっている SQL を特定(推定) 手順 1 は「ブロッキングが発生している状況」でないと結果が取得できません。したがって、N 秒間隔で定期的に 2 種類の View 相当の情報を収集して保存しておけば、事後調査ができることになります。なお、 N 秒 < アプリケーションタイムアウト時間 という関係性が成り立つような N を選定する必要があります。 ブロッキングについての補足 ブロッキングについて 2 点補足します。まずデッドロックとの違いについて、次にブロッキングツリーについて説明します。 デッドロックとの違い ブロッキングはデッドロックと混同されることが稀にありますので、その違いについて整理しておきます。デッドロックもブロッキングの一種ですが、デッドロックの場合は「いずれかのプロセスを強制的にロールバックさせない限り、事象が解消しないことが確定」しています。したがって InnoDB がデッドロックを検出すると比較的すぐに自動解消が行われます。一方で、通常のブロッキングの場合はブロッカーのクエリが終了すれば解消するため InnoDB による介入はありません。両者に比較を表にまとめると以下のようになります。 ブロッキング デッドロック InnoDB による自動解消 × ⚪︎ クエリの終了 KILL やタイムアウトエラーで途中で終了しない限り、ブロックしている側もされている側も最終的には実行完了する 片方のトランザクションは InnoDB によって強制的に終了させられる 一般的な解消方法 ブロッカーのクエリが実行完了することによる自然解消もしくは、アプリケーション側で設定したクエリタイムアウト時間経過後にタイムアウトエラー発生とともに解消 InnoDB がデッドロックを検知後、片方のトランザクションを強制的にロールバックさせることで解消 ブロッキングツリー MySQL の正式な用語ではありませんが、ブロッキングツリーについて説明します。これは「ブロッカーとなっているクエリも、別のブロッカーによってブロックされている」ような状況を指します。 例えば以下のような状況です。 -- セッション 1 begin; update sample_table set c1 = 2 where pk_column = 1; -- セッション 2 begin; update other_table set c1 = 3 where pk_column = 1; update sample_table set c1 = 4 where pk_column = 1; -- セッション 3 update other_table set c1 = 5 where pk_column = 1; この状況では、 sys.innodb_lock_waits を SELECT した時に、「セッション 1 が セッション 2 をブロックしている」という情報と「セッション 2 が セッション 3 をブロックしている」という情報の 2 レコードが取得できます。この場合、セッション 3 からみたブロッカーは セッション 2 ですが、問題の根本原因(Root Blocker)としてはセッション 1 です。このように、ブロッキングの発生は時にツリー状になることがあり、このようなケースではログベースでの調査がさらに困難になります。事前にブロッキングに関する情報を収集することの重要性は、このようなブロッキング関連の原因調査の難しさにあります。 以降では、ブロッキングの情報収集の仕組みの設計と実装についてご紹介します。 アーキテクチャ設計 弊社では、マルチリージョンかつ、リージョン内で複数の Aurora MySQL クラスタが稼働しています。したがって、リージョンおよびクラスタ横断でデプロイや運用の負荷を最小限に抑える構成にする必要がありました。 他にも、以下のような要件を整理しました。 機能要件 任意の SQL を Aurora MySQL に対して定期的に実行できる 任意のリージョンにある Aurora MySQL の情報を収集できる 実行対象の DB を管理できる クエリの実行結果を外部のストレージへ保管できる SQL ベースで格納したデータをクエリできる 収集元の DB への権限を持った人だけが収集したデータへアクセスできるように権限管理できる 非機能要件 収集対象の DB への負荷増(オーバーヘッド)は最小限に抑えられる 分析時のデータ鮮度は 5 分程度のタイムラグまでに抑える システムが稼働できない状況に陥った際は通知により気づける状態にある SQL ベースでの分析時のレスポンスが数秒で返ってくる 情報の収集先(なんらかのストレージ)は 1 箇所に集約できる 運用に必要な金銭的コストを最小限におさえる また、収集対象のテーブルについて以下の通り整理しました。 収集対象のテーブル sys.schema_table_lock_waits と sys.innodb_lock_waits の SELECT 結果を定期的に収集すればそれで OK なのですが、これらの View は複雑なため、元になっているテーブルを直接 SELECT するよりも負荷が高いです。したがって、非機能要件の「収集対象の DB への負荷増(オーバーヘッド)は最小限に抑えられる」を考慮し、View の元となっている以下の 6 テーブルを SELECT し、クエリエンジン側で View を構築し、クエリ負荷をクエリエンジン側にオフロードする構成にしました。 sys.schema_table_lock_waits の元テーブル performance_schema.metadata_locks performance_schema.threads performance_schema.events_statements_current sys.innodb_lock_waits の元テーブル performance_schema.data_lock_waits information_schema.INNODB_TRX performance_schema.data_locks 最も簡単な方法としては、MySQL のタスクスケジューリング機能である MySQL Event で、これらのテーブルに対する SELECT クエリを N 秒間隔で実行し、結果を専用のテーブルに保存する、というものが考えられます。しかしこの方法では 対象 DB に高頻度で書き込み負荷が発生したり、結果を確認するために該当の DB に個別にログインする必要があるなど、要件に対して適当ではない性質があります。したがって別の方法を検討しました。 アーキテクチャ案 最初に抽象的なアーキテクチャ図を以下の通り作成しました。 このアーキテクチャ図に対して、要件を踏まえつつ各レイヤーで使用する AWS サービスを選定していきました。 Collector のサービス選定 Collector の実装としては、弊社での利用実績を踏まえて以下のサービスを検討した結果、Lambda の使用をメインに設計を進めることにしました。 EC2 今回のワークロードは常時 EC2 を実行するほどの処理能力は必要ないと想定され、管理面・コスト面から過剰と判断 仕組みが EC2 へのデプロイや、EC2 上の実行環境に依存 ECS on EC2 今回のワークロードは常時 EC2 を実行するほどの処理能力は必要ないと想定され、管理面・コスト面から過剰と判断 ECR などの Container Repository に依存 ECS on Fargate Lambda 同様サーバーレスだが、ECR などの Container Repository には依存 Lambda 他のコンピュートレイヤのサービスよりも独立性が高く、今回想定する軽量な処理を実行するのに最適と判断 Storage / Query Interface のサービス選定 Storage / Query Interface は S3 + Athena 構成としました。理由は以下の通りです。 JOIN を含む SQL を実行したい Storage として CloudWatch Logs も検討したがこの要件により却下 高速な応答速度やトランザクション処理は求められない RDS / DynamoDB / Redshift などの DB サービスを使うメリットが無い Buffer のサービス選定 Collector と Storage の間のバッファレイヤとして Amazon Data Firehose を採用しました。他にも Kafka / SQS / Kinesis Data Streams 等検討しましたが、以下の理由で Firehose を採用しました。 Firehose に Put すれば自動で S3 にデータを保存してくれる(追加のコーディングが不要) 時間またはデータサイズによりバッファリングして一括で S3 に保存できるため S3 側のファイル数を少なくできる 自動で圧縮してくれるため S3 側のファイルサイズが抑えられる 動的パーティショニング 機能により、S3 のファイルパスを動的に決められる 上記で選定したサービスをベースに、アーキテクチャ案を 5 パターン作成しました。簡易的に、1 リージョンを対象に図示します。 案 1 : MySQL Event で Lambda を実行 Aurora MySQL は Lambda と統合 されています。これを利用して、MySQL Event を使って定期的に Lambda を Invoke するパターンです。アーキテクチャは以下の通りです。 ![案 1 : MySQL Event で Lambda を実行するパターンのアーキテクチャ図](/assets/blog/authors/m.hirose/2024-03-12-13-16-16.png =600x) 案 2 : Aurora から S3 に直接データを保存 Aurora MySQL は S3 とも統合 されており、直接 S3 にデータを保存できます。アーキテクチャは下図の通り非常にシンプルになります。一方で、案1 も同様ですが MySQL Event のデプロイが必要なため、Event の新規作成や修正時に複数の DB クラスタに対して横断的なデプロイが必要になります。手動で個別に対応するか、対象の全クラスタにデプロイする仕組みを用意する必要があります。 ![案 2 : Aurora から S3 に直接ファイルを保存するパターンのアーキテクチャ図](/assets/blog/authors/m.hirose/2024-03-12-13-15-50.png =300x) 案 3 : Step Functions 案 A パターン Step Functions と Lambda を組み合わせるパターンです。Map ステートを使うことで、対象のクラスタごとに Collector に相当する 子ワークフロー を並列で実行できます。「N 秒間隔で SQL を実行」という処理は Lambda と Wait ステートの組み合わせで実装します。この実装にするとステートの遷移数が非常に多くなります。Step Functions の標準ワークフローの料金体系ではステートの遷移数に対して課金が発生しますが、Express ワークフローは 1 回あたりの実行時間が最長 5 分という制約があるものの、ステートの遷移数は課金対象となりません。したがって、ステートの遷移数が多くなる箇所は Express ワークフローとして実装します。 こちらの AWS Blog を参考にしました。 案 4 : Step Functions 案 B パターン 案 3 と同様、Step Functions と Lambda を組み合わせるパターンです。案 3 と違う点として「N 秒間隔で SQL を実行」という処理は Lambda 内に実装し「SQL を実行 -> N 秒 Sleep」を 10 分間繰り返し続けます。Lambda の実行は最長で 15 分という制約があるため、10 分ごとに EventBridge で Step Functions を起動します。ステートの遷移数が非常に少ないため、Step Functions の金銭的コストを抑えることができます。一方で、Sleep している時間も Lambda が起動し続けるため、Lambda の課金額は 案 3 よりも高くなることが想定されます。 ![案 4 : Step Functions 案 B パターンのアーキテクチャ図](/assets/blog/authors/m.hirose/2024-03-12-13-23-40.png =600x) 案 5 : Sidecar パターン 弊社ではコンテナオーケストレーションサービスとして主に ECS を使用しており、各 Aurora MySQL にアクセス可能な ECS クラスタが最低 1 つは存在するという前提を利用した案です。タスク内に新規実装した Collector を Sidecar として配置することで、Lambda などの追加のコンピューティングリソースコストが発生しないメリットがあります。ただし、Fargate のリソース内に収まらない場合は拡張が必要になります。 ![案 5 : Sidecar パターンのアーキテクチャ図](/assets/blog/authors/m.hirose/2024-03-12-13-47-37.png =600x) アーキテクチャ比較 各案を比較した結果を以下の通り表にまとめました。 案 1 案 2 案 3 案 4 案 5 開発・運用者 DBRE DBRE DBRE DBRE コンテナ周りは管轄外のため他チームに依頼が必要 金銭的コスト ◎ ◎ ⚪︎ △ ◎ 実装コスト △ ⚪︎ △ ⚪︎ ⚪︎ 開発のアジリティ ⚪︎(DBRE) ⚪︎(DBRE) ⚪︎(DBRE) ⚪︎(DBRE) △(チーム間で要調整) デプロイ容易性 △(Event のデプロイが手動または専用の仕組み作りが必要) △(Event のデプロイが手動または専用の仕組み作りが必要) ⚪︎(既存の開発フローで IaC 管理可能) ⚪︎(既存の開発フローで IaC 管理可能) △(チーム間で要調整) スケーラビリティ ⚪︎ ⚪︎ ⚪︎ ⚪︎ △(Fargate 管轄のチームと要調整) 固有の考慮事項 Aurora から Lambda を起動するために IAM や DB ユーザーへの権限設定が必要 バッファリングしないため、S3 への書き込みが同期かつ API 実行回数が多い Express ワークフローが At least once モデルであることを考慮した実装が必要 Lambda の実行時間が必要以上に長くなるため、最も金銭的コストが高い Sidecar コンテナがタスク数と同じ数できるので、処理が重複して実行される 以上の比較を踏まえて、案 3(標準ワークフローと Express ワークフローを併用した Step Functions を用いる案)を採用しました。理由は以下の通りです。 収集データの種類を拡充していく見込みがあり、自チーム(DBRE)で開発・運用をコントロールできる方がスピード感を持って対応できる MySQL Event を使用する案はシンプルな構成だが、横断的な IAM 権限の修正や DB ユーザーへの権限追加など気にすべき点が多く、自動化するにしても手動でカバーするにしても人的コストが高い 多少実装にコストがかかってもそれ以外でメリットを享受できる案 3 が最もバランスが取れていると判断 以降では、採用した案を実装する過程で工夫した点や最終的なアーキテクチャをご紹介します。 実装 DBRE チームではモノレポで開発を行っており、管理ツールとして Nx を採用しています。インフラストラクチャ管理は Terraform で行い、Lambda の実装は Go 言語で行っています。Nx を用いた DBRE チームの開発フローについては、弊社テックブログ「 AWSサーバレスアーキテクチャをMonorepoツール - Nxとterraformで構築してみた! 」をご覧ください。 最終的なアーキテクチャ図 マルチリージョン対応やその他の点を考慮し、最終的なアーキテクチャは下図のようになりました。 主な考慮事項は以下の通りです。 Express ワークフローは 5 分で強制終了でエラー扱いとなるため、4 分間経過後に終了 DynamoDB へのアクセス回数は少なくレイテンシもネックにならないため東京リージョンに集約 Firehose へ Put した後の S3 へのデータ同期は非同期であるためレイテンシがネックにならず、S3 を東京リージョンに集約 Secrets Manager への高頻度アクセスによる金銭的コストを抑えるために、シークレットの取得はステートのループ外で実施 各 Express ワークフローが複数回実行されるのを防ぐためのロック機構を DynamoDB を使って実装 ※ Express ワークフローは At least once 実行モデルであるため 以降では、実装時に工夫した点をいくつかご紹介します。 各 DB に専用の DB ユーザーを作成 今回対象の SQL を実行するのに必要な権限は以下の 2 つだけです。 GRANT SELECT ON performance_schema.* TO ${user_name}; -- information_schema.INNODB_TRX の SELECT に必要 GRANT PROCESS ON *.* TO ${user_name}; この権限だけを持つ DB ユーザーが全ての Aurora MySQL に対して作成される仕組みを作りました。弊社では、 全ての Aurora MySQL に対して日次で接続し、様々な情報を収集するバッチ処理 が存在します。このバッチ処理を修正し、全 DB に対して必要な権限を持った DB ユーザーを作成するようにしました。これにより、新しい DB が作成されても自動で必要な DB ユーザーが存在する状態になりました。 DB 負荷および S3 に保存されるデータサイズの低減 収集対象の 6 テーブルのうちいくつかは、ブロッキングが発生していなくてもレコードが取得できます。そのため N 秒間隔で毎回全件 SELECT すると、わずかではありますが Aurora への負荷が無駄に増え、S3 にもデータが無駄に溜まってしまいます。これを避けるために、ブロッキングが発生している時だけ関連するテーブルを全件 SELECT するような実装にしました。ブロッキング検知用の SQL も負荷を最小限に抑えることを意識して、以下の通り整理しました。 メタデータのブロッキング発生検知 メタデータのブロッキング発生検知クエリは以下の通りです。 select * from `performance_schema`.`metadata_locks` where lock_status = 'PENDING' limit 1 このクエリでレコードが取得できた時だけ、以下の 3 テーブルを全件 SELECT して Firehose へ Put します。 performance_schema.metadata_locks performance_schema.threads performance_schema.events_statements_current InnoDB のブロッキング発生検知 InnoDB のブロッキング発生検知クエリは以下の通りです。 select * from `information_schema`.`INNODB_TRX` where timestampdiff(second, `TRX_WAIT_STARTED`, now()) >= 1 limit 1; このクエリでレコードが取得できた時だけ、以下の 3 テーブルを全件 SELECT して Firehose へ Put します。 performance_schema.data_lock_waits information_schema.INNODB_TRX performance_schema.data_locks goroutine を用いたクエリの並行処理 各テーブルへの SELECT 実行タイミングに多少のズレがあっても、ブロッキングが継続していれば後で JOIN したときにデータ不整合が発生する確率は低いといえます。しかし、できるだけ同じタイミングで実施した方が望ましくはあります。また「N 秒間隔でデータが収集され続ける」という状態を達成するためには、Collector の Lambda の実行時間を可能な限り短く終了させる必要もあります。以上 2 点を踏まえて、クエリ実行は goroutine を用いて可能な限り並行処理しています。 想定外の過負荷を避けるためのセッション変数の使用 事前に実行予定のクエリ負荷が十分に低いことは確認していますが、時には「想定以上に実行時間が長くなる」「情報収集のクエリがブロッキングに巻き込まれる」といった状況も考えられます。したがって、できる限り安全に情報を取得し続けるために max_execution_time と TRANSACTION ISOLATION LEVEL READ UNCOMMITTED をセッションレベルで設定しています。 Go 言語でこの処理を実装するために、 database/sql/driver パッケージの driver.Connector インタフェースの関数 Connect() をオーバーライドしています。エラー処理を除いた実装イメージとしては以下のとおりです。 type sessionCustomConnector struct { driver.Connector } func (c *sessionCustomConnector) Connect(ctx context.Context) (driver.Conn, error) { conn, err := c.Connector.Connect(ctx) execer, _ := conn.(driver.ExecerContext) sessionContexts := []string{ "SET SESSION max_execution_time = 1000", "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED", } for _, sessionContext := range sessionContexts { execer.ExecContext(ctx, sessionContext, nil) } return conn, nil } func main() { cfg, _ := mysql.ParseDSN("dsn_string") defaultConnector, _ := mysql.NewConnector(cfg) db := sql.OpenDB(&sessionCustomConnector{defaultConnector}) rows, _ := db.Query("SELECT * FROM performance_schema.threads") ... } Express ワークフローのためのロック機構 StepFunctions の Express ワークフローは At least once 実行モデルのため、ワークフロー全体が複数回実行される可能性があります。今回のケースだと重複実行されても大きな問題ではないのですが、Exactly once の方が望ましくはあるため、 AWS Blog を参考に DynamoDB を用いた簡易的なロック機構を実装しました。 具体的には、Express ワークフロー開始時に実行される Lambda で、DynamoDB のテーブルに attribute_not_exists 条件式 つきでデータを PUT します。パーティションキーには、親ワークフローで生成した一意な ID を指定するため「PUT が成功する = 自分自身が初回実行者」である、と判断できます。失敗した場合は既に別の子ワークフローが稼働中と判断し、以降の処理をスキップして終了します。 Amazon Data Firehose の動的パーティショニングの活用 Firehose の 動的パーティショニング 機能を使って、S3 のファイルパスを動的に決定しています。動的パーティショニングのためのルール(S3 バケットプレフィクス)は、後述の Athena でのアクセス制御も考慮して以下のように設定しました。 !{partitionKeyFromQuery:db_schema_name}/!{partitionKeyFromQuery:table_name}/!{partitionKeyFromQuery:env_name}/!{partitionKeyFromQuery:service_name}/day=!{timestamp:dd}/hour=!{timestamp:HH}/ この設定を入れた Firehose の Stream に json データを Put すると、json 内の属性からパーティションキーとなる属性を探して、自動でルール通りのファイルパスで S3 へ保存してくれます。 例えば、以下の json データを Firehose へ Put したとします。 { "db_schema_name":"performance_schema", "table_name":"threads", "env_name":"dev", "service_name":"some-service", "other_attr1":"hoge", "other_attr2":"fuga", ... } その結果 S3 へ保存されるファイルパスは以下のようになります。Firehose へ Put する際にファイルパスを指定する必要は一切なく、事前に定義しておいたルールに基づいて Firehose が自動でファイル名を決定して保存してくれています。 Firehose が S3 に保存したファイル : 動的パーティショニングでファイルパスは自動で決定 スキーマ名やテーブル名などは MySQL テーブルの SELECT 結果には存在しないため、Firehose に Put する json を生成するタイミングで共通のカラムとして追加するように実装しています。 Athena のテーブルとアクセス権限の設計 MySQL 側のテーブル定義をもとに、Athena 側でテーブルを作成する例を 1 テーブル分ご紹介します。 performance_schema.metadata_locks の MySQL 側の CREATE 文は以下の通りです。 CREATE TABLE `metadata_locks` ( `OBJECT_TYPE` varchar(64) NOT NULL, `OBJECT_SCHEMA` varchar(64) DEFAULT NULL, `OBJECT_NAME` varchar(64) DEFAULT NULL, `COLUMN_NAME` varchar(64) DEFAULT NULL, `OBJECT_INSTANCE_BEGIN` bigint unsigned NOT NULL, `LOCK_TYPE` varchar(32) NOT NULL, `LOCK_DURATION` varchar(32) NOT NULL, `LOCK_STATUS` varchar(32) NOT NULL, `SOURCE` varchar(64) DEFAULT NULL, `OWNER_THREAD_ID` bigint unsigned DEFAULT NULL, `OWNER_EVENT_ID` bigint unsigned DEFAULT NULL, PRIMARY KEY (`OBJECT_INSTANCE_BEGIN`), KEY `OBJECT_TYPE` (`OBJECT_TYPE`,`OBJECT_SCHEMA`,`OBJECT_NAME`,`COLUMN_NAME`), KEY `OWNER_THREAD_ID` (`OWNER_THREAD_ID`,`OWNER_EVENT_ID`) ) これを Athena 用として以下のように定義しました。 CREATE EXTERNAL TABLE `metadata_locks` ( `OBJECT_TYPE` string, `OBJECT_SCHEMA` string, `OBJECT_NAME` string, `COLUMN_NAME` string, `OBJECT_INSTANCE_BEGIN` bigint, `LOCK_TYPE` string, `LOCK_DURATION` string, `LOCK_STATUS` string, `SOURCE` string, `OWNER_THREAD_ID` bigint, `OWNER_EVENT_ID` bigint, `db_schema_name` string, `table_name` string, `aurora_cluster_timezone` string, `stats_collected_at_utc` timestamp ) PARTITIONED BY ( env_name string, service_name string, day int, hour int ) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' LOCATION 's3://<bucket_name>/performance_schema/metadata_locks/' TBLPROPERTIES ( "projection.enabled" = "true", "projection.day.type" = "integer", "projection.day.range" = "01,31", "projection.day.digits" = "2", "projection.hour.type" = "integer", "projection.hour.range" = "0,23", "projection.hour.digits" = "2", "projection.env_name.type" = "injected", "projection.service_name.type" = "injected", "storage.location.template" = "s3://<bucket_name>/performance_schema/metadata_locks/${env_name}/${service_name}/day=${day}/hour=${hour}" ); ポイントはパーティションキーの設計です。これにより「元の DB へのアクセス権限を持った人だけがデータにアクセスできる」状態にしています。弊社では、各サービスに固有の service_name と、環境ごとに固有の env_name という 2 つのタグを全ての AWS リソースに付与しており、このタグをアクセス制御手段の 1 つとして活用しています。この 2 つのタグを S3 に保存するファイルパスの一部に含め、各サービスに共通で付与している IAM Policy に対してポリシー変数を用いて Resource を記述することで、同じテーブルであってもアクセス権限を持っている S3 のファイルパスに相当するパーティションのデータしか SELECT できない、という状態にしています。 各サービスに共通で付与している IAM Policy に付与する権限のイメージは以下の通りです。 { "Effect": "Allow", "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::<bukect_name>/*/${aws:PrincipalTag/env_name}/${aws:PrincipalTag/service_name}/*" ] } また、今回はパーティションをメンテナンスフリーにしたかったので、 パーティション射影 を使っています。パーティション射影を使う場合、基本的にはパーティションキーの取りうる値の範囲が既知である必要がありますが、 injected 射影型 を使うことで値の範囲を Athena に伝える必要なく、メンテナンスフリーな動的パーティショニングを実現しています。 Athena 側での View の再現 ブロッキングの事後調査に必要な 6 つのテーブルを Athena に作成し、MySQL 側と同様に View でラップした方法をご紹介します。View の定義は、MySQL 側の View 定義をもとに、前述の共通カラムを付与したり、パーティションキーの比較を JOIN 句に追加するなどの修正を加えました。 sys.innodb_lock_waits の Athena 側での定義は以下の通りです。 CREATE OR REPLACE VIEW innodb_lock_waits AS select DATE_ADD('hour', 9, w.stats_collected_at_utc) as stats_collected_at_jst, w.stats_collected_at_utc as stats_collected_at_utc, w.aurora_cluster_timezone as aurora_cluster_timezone, r.trx_wait_started AS wait_started, date_diff('second', r.trx_wait_started, r.stats_collected_at_utc) AS wait_age_secs, rl.OBJECT_SCHEMA AS locked_table_schema, rl.OBJECT_NAME AS locked_table_name, rl.PARTITION_NAME AS locked_table_partition, rl.SUBPARTITION_NAME AS locked_table_subpartition, rl.INDEX_NAME AS locked_index, rl.LOCK_TYPE AS locked_type, r.trx_id AS waiting_trx_id, r.trx_started AS waiting_trx_started, date_diff('second', r.trx_started, r.stats_collected_at_utc) AS waiting_trx_age_secs, r.trx_rows_locked AS waiting_trx_rows_locked, r.trx_rows_modified AS waiting_trx_rows_modified, r.trx_mysql_thread_id AS waiting_pid, r.trx_query AS waiting_query, rl.ENGINE_LOCK_ID AS waiting_lock_id, rl.LOCK_MODE AS waiting_lock_mode, b.trx_id AS blocking_trx_id, b.trx_mysql_thread_id AS blocking_pid, b.trx_query AS blocking_query, bl.ENGINE_LOCK_ID AS blocking_lock_id, bl.LOCK_MODE AS blocking_lock_mode, b.trx_started AS blocking_trx_started, date_diff('second', b.trx_started, b.stats_collected_at_utc) AS blocking_trx_age_secs, b.trx_rows_locked AS blocking_trx_rows_locked, b.trx_rows_modified AS blocking_trx_rows_modified, concat('KILL QUERY ', cast(b.trx_mysql_thread_id as varchar)) AS sql_kill_blocking_query, concat('KILL ', cast(b.trx_mysql_thread_id as varchar)) AS sql_kill_blocking_connection, w.env_name as env_name, w.service_name as service_name, w.day as day, w.hour as hour from ( ( ( ( data_lock_waits w join INNODB_TRX b on( ( b.trx_id = cast( w.BLOCKING_ENGINE_TRANSACTION_ID as bigint ) ) and w.stats_collected_at_utc = b.stats_collected_at_utc and w.day = b.day and w.hour = b.hour and w.env_name = b.env_name and w.service_name = b.service_name ) ) join INNODB_TRX r on( ( r.trx_id = cast( w.REQUESTING_ENGINE_TRANSACTION_ID as bigint ) ) and w.stats_collected_at_utc = r.stats_collected_at_utc and w.day = r.day and w.hour = r.hour and w.env_name = r.env_name and w.service_name = r.service_name ) ) join data_locks bl on( bl.ENGINE_LOCK_ID = w.BLOCKING_ENGINE_LOCK_ID and bl.stats_collected_at_utc = w.stats_collected_at_utc and bl.day = w.day and bl.hour = w.hour and bl.env_name = w.env_name and bl.service_name = w.service_name ) ) join data_locks rl on( rl.ENGINE_LOCK_ID = w.REQUESTING_ENGINE_LOCK_ID and rl.stats_collected_at_utc = w.stats_collected_at_utc and rl.day = w.day and rl.hour = w.hour and rl.env_name = w.env_name and rl.service_name = w.service_name ) ) また、sys.schema_table_lock_waits の Athena 側での定義は以下の通りです。 CREATE OR REPLACE VIEW schema_table_lock_waits AS select DATE_ADD('hour', 9, g.stats_collected_at_utc) as stats_collected_at_jst, g.stats_collected_at_utc AS stats_collected_at_utc, g.aurora_cluster_timezone as aurora_cluster_timezone, g.OBJECT_SCHEMA AS object_schema, g.OBJECT_NAME AS object_name, pt.THREAD_ID AS waiting_thread_id, pt.PROCESSLIST_ID AS waiting_pid, -- sys.ps_thread_account(p.OWNER_THREAD_ID) AS waiting_account, -- MySQL 側での情報収集時に select に含めておく必要があるが、不要なため未対応 p.LOCK_TYPE AS waiting_lock_type, p.LOCK_DURATION AS waiting_lock_duration, pt.PROCESSLIST_INFO AS waiting_query, pt.PROCESSLIST_TIME AS waiting_query_secs, ps.ROWS_AFFECTED AS waiting_query_rows_affected, ps.ROWS_EXAMINED AS waiting_query_rows_examined, gt.THREAD_ID AS blocking_thread_id, gt.PROCESSLIST_ID AS blocking_pid, -- sys.ps_thread_account(g.OWNER_THREAD_ID) AS blocking_account, -- MySQL 側での情報収集時に select に含めておく必要があるが、不要なため未対応 g.LOCK_TYPE AS blocking_lock_type, g.LOCK_DURATION AS blocking_lock_duration, concat('KILL QUERY ', cast(gt.PROCESSLIST_ID as varchar)) AS sql_kill_blocking_query, concat('KILL ', cast(gt.PROCESSLIST_ID as varchar)) AS sql_kill_blocking_connection, g.env_name as env_name, g.service_name as service_name, g.day as day, g.hour as hour from ( ( ( ( ( metadata_locks g join metadata_locks p on( ( (g.OBJECT_TYPE = p.OBJECT_TYPE) and (g.OBJECT_SCHEMA = p.OBJECT_SCHEMA) and (g.OBJECT_NAME = p.OBJECT_NAME) and (g.LOCK_STATUS = 'GRANTED') and (p.LOCK_STATUS = 'PENDING') AND (g.stats_collected_at_utc = p.stats_collected_at_utc and g.day = p.day and g.hour = p.hour and g.env_name = p.env_name and g.service_name = p.service_name) ) ) ) join threads gt on(g.OWNER_THREAD_ID = gt.THREAD_ID and g.stats_collected_at_utc = gt.stats_collected_at_utc and g.day = gt.day and g.hour = gt.hour and g.env_name = gt.env_name and g.service_name = gt.service_name) ) join threads pt on(p.OWNER_THREAD_ID = pt.THREAD_ID and p.stats_collected_at_utc = pt.stats_collected_at_utc and p.day = pt.day and p.hour = pt.hour and p.env_name = pt.env_name and p.service_name = pt.service_name) ) left join events_statements_current gs on(g.OWNER_THREAD_ID = gs.THREAD_ID and g.stats_collected_at_utc = gs.stats_collected_at_utc and g.day = gs.day and g.hour = gs.hour and g.env_name = gs.env_name and g.service_name = gs.service_name) ) left join events_statements_current ps on(p.OWNER_THREAD_ID = ps.THREAD_ID and p.stats_collected_at_utc = ps.stats_collected_at_utc and p.day = ps.day and p.hour = ps.hour and p.env_name = ps.env_name and p.service_name = ps.service_name) ) where (g.OBJECT_TYPE = 'TABLE') 結果 構築した仕組みを使って実際にブロッキングを発生させ、Athena 側で調査を行なってみます。 select * from innodb_lock_waits where stats_collected_at_jst between timestamp '2024-03-01 15:00:00' and timestamp '2024-03-01 16:00:00' and env_name = 'dev' and service_name = 'some-service' and hour between cast(date_format(DATE_ADD('hour', -9, timestamp '2024-03-01 15:00:00'), '%H') as integer) and cast(date_format(DATE_ADD('hour', -9, timestamp '2024-03-01 16:00:00'), '%H') as integer) and day = 1 order by stats_collected_at_jst asc limit 100 ブロッキングが発生していた時間帯を指定して Athena で上記クエリを実行すると、以下のような結果が返ってきます。 ブロッカーの SQL は分からないため、プロセス ID(blocking_pid カラム)をもとに CloudWatch Logs Insights を使ってブロッカーが実行した SQL の履歴を確認します。 fields @timestamp, @message | parse @message /(?<timestamp>[^\s]+)\s+(?<process_id>\d+)\s+(?<type>[^\s]+)\s+(?<query>.+)/ | filter process_id = 215734 | sort @timestamp desc 以下のような結果が得られ、ブロッカーの SQL が update d1.t1 set c1 = 12345 であることを特定できました。 同様の手順で schema_table_lock_waits でもメタデータ関連のブロッキング状況を確認することができるようになりました。 今後の展望 今後の展望としては、以下のようなことを考えています。 プロダクトへの展開はこれからなので、実運用を通してブロッキング起因のインシデントに関する知見をためる Lambda の 課金時間(Billed Duration) を最小化するためのボトルネック調査とチューニング performance_schema と information_schema における収集対象の拡充 インデックス使用状況の分析など調査の幅を広げる インシデント対応からのフィードバックで収集情報を拡充するサイクルを回すことで、DB レイヤーの課題解決力を向上 Amazon QuickSight などの BI サービスによる可視化 performance_schema 等に精通していないメンバーでも原因調査できる世界にする まとめ 本記事では、Aurora MySQL で発生したロック競合(ブロッキング)起因のタイムアウトエラーの原因調査をきっかけに、ブロッキング原因を後追いするために必要な情報を定期的に収集する仕組みを構築した事例をご紹介しました。MySQL でブロッキングの情報を後追いするためにはメタデータロックと InnoDB のロックという 2 種類のロックに関する待ち情報を以下の 6 テーブルを使って定期的に収集する必要があります。 メタデータロック performance_schema.metadata_locks performance_schema.threads performance_schema.events_statements_current InnoDB のロック performance_schema.data_lock_waits information_schema.INNODB_TRX performance_schema.data_locks 弊社の環境を踏まえてマルチリージョンかつ、複数の DB クラスタに対して情報収集を実施できるアーキテクチャを設計し、実装しました。その結果、ブロッキング発生から最長 5 分のタイムラグで SQL ベースで事後調査が実施でき、結果が数秒で返ってくるような仕組みを構築することができました。いずれ SaaS や AWS サービスへも組み込まれる機能かもしれませんが、DBRE チームでは必要と判断すれば積極的に自分たちで機能を実装することを大切にしています。 KINTO テクノロジーズ DBRE チームでは一緒に働いてくれる仲間を絶賛募集中です!カジュアルな面談も歓迎ですので、 少しでも興味を持っていただけた方はお気軽に X の DM 等でご連絡ください。併せて、 弊社の採用 Twitter もよろしければフォローお願いします! Appendix : 参考記事 MySQL 8.0 系におけるブロッキングの調査方法は、以下の記事にとても分かりやすくまとまっており参考にさせていただきました。 InnoDBの行ロック状態を確認する[その1] InnoDBの行ロック状態を確認する[その2] 磯野ー、MySQLのロック競合を表示しようぜー また、ブロッカーが分かった後は「どんなロックが起因でブロッキングが起きていたか」といった深掘りも必要ですが、MySQL のロックについては以下の記事にとてもわかりやすくまとまっております。 MySQLのロックについて MySQL のリファレンスも参考にさせていただきました。 The metadata_locks Table The data_locks Table InnoDB INFORMATION_SCHEMA Transaction and Locking Information
アバター
Interviewee The Global Development Division within KINTO Technologies has a DevOps team with multinational and diverse backgrounds. Although each member has different strengths in different languages, technologies, and experiences, they work very smoothly as a team. This time, we interviewed a team leader, Li-san ( the author of the article "Introduction of Flyway" ). If you are interested in managing an international team, please read on. Self- and Team-Introduction Self-introduction I'm Li, a DevOps team leader in the Global Development Division at KINTO Technologies. After graduating, I spent five years working at an IT subsidiary of a Japanese manufacturer. During this period, Japanese was the common language used in the company, prompting me to learn Japanese, the Japanese culture, and enhance my communication skills across various cultures. At that time, I started out developing, designing, and evaluating web applications, and gained experience as a systems engineer and project manager. I gained not only development experience, but also knowledge of the development process and management. I then served as a lecturer at a university for three years, learning new technologies and pedagogy. This experience also deepened my understanding of effective learning methods. After moving to Japan, I returned to the IT field when my second daughter started preschool. With my cross-cultural communication skills, development experience, management skills and human resource development experience, I currently lead a DevOps team in the Global Development Division. Team-introduction At present, our DevOps team consists of three subteams: CI/CD, Infrastructure, and Test. The six members of the team are as follows, with different nationalities and areas of expertise. From the beginning, the DevOps team's philosophy has been to support application development teams by intentionally combining members with different skill sets. No. Subteam Previous work experience Nationality English proficiency Japanese proficiency 1 CI/CD Development, project management, quality assurance, and system design China B B 2 Infra Infrastructure engineer, project promotion, integration, and design China C A 3 Infra Infrastructure engineer, development, and pre-sales China C B 4 Test Network engineer and project management New Zealand A C 5 Test Development engineer India A C 6 Test Testing, development, and design Myanmar B C *Language proficiency: A: Can reconstruct and express subtle nuances B: Can discuss a wide range of complex topics C: Can express personal thoughts and reasoning D: Can engage in everyday conversation Q&A Corner It can be hard to imagine the daily work of a team with diverse language, cultural, and technical backgrounds. So this time we asked a few questions to the team leader, Li-san. We would like to summarize them here in a Q&A format to provide you with some insight into the team. Q&A Part 1 Q. How do you keep everyone on your DevOps team working toward a common goal, given the variety of professional backgrounds within the team? A. We share a clear roadmap within our team as shown below. Based on this roadmap, we set specific goals so that all members are aligned and work towards the same direction. The team comprises members with a variety of aspirations; some are interested in quality assurance, others aspire to be in charge of infrastructure projects, while some want to be involved in development. We understand each of our strengths and aspirations, and work collaboratively to create a roadmap that everyone can agree with. Roadmap (example) Q&A Part 2 Q. Seven people in your team speak four different native languages. What language do you use to communicate? What about documentation or messages? A. When communicating verbally and writing documents, they use their preferred language (English or Japanese). Messages are mainly sent in English because everyone on the team can understand English. We also encourage the use of translation tools for better understanding each other. To communicate across languages and cultures, the presenter in our team will speak slowly, use simple words, and create an atmosphere in which questions are immediately asked if they are not understood. Q&A Part 3 Q. How do you promote knowledge sharing in your culturally and technically diverse team? A. Our team values knowledge sharing, and we use three methods: Period Means Content Purpose Ice breaking phase Knowledge sharing meeting for each member's field of expertise Previous knowledge To understand each other and expand their knowledge One year after assignment Online course learning (e.g. automated testing tools and microservices architecture courses on Udemy) To enhance the skills lacking for the current job (e.g. system architecture, automated testing tools, or AWS)Improvement of skills needed in current job At any time (after different tasks are completed) Document and retain Procedures, know-how, etc. ( e.g. Automated test blocks ) To facilitate horizontal development in the future Q&A Part 4 Q. As a mother, is it difficult to lead a cross-cultural team? A. My team is incredibly supportive and understanding of me being a mother. As a culture of the Global Development Division, we respect diversity, respect each other, and maintain an appropriate distance. I have two elementary school children, and when I need to participate in school events, my team members support me by adjusting schedules and reallocating tasks. For example, when my entire family recently contracted the flu, I couldn't come to work for about two weeks, but my team members were willing to take on duties to alleviate my workload. I am very grateful for their support. Q&A Part 5 Q. When managing a multinational team, how can you unify the various standards (e.g. work ethics, professional standards, etc.) and keep members motivated while achieving a certain level of results? A. It is important to recognize and respect the rationality of different cultures. As I am from a foreign country myself, I understand the differences between Japanese and foreign practices and can explain them to the team from this perspective. Since this is Japan, I basically adhere to Japanese standards, but I offer commentary from a foreigner's perspective. I also leverage knowledge of management studies and PMP (Project Management Professional) as well as adopt other common industry practices. I prioritize providing team members with significant autonomy, fostering motivation by enabling them to work on projects of their choosing. Lastly Q. What do you value the most or devise when managing such a global team? A. I still think communication is the most important, in line with the philosophy of PMP. In our team, everyone is committed to communicating their ideas clearly and with precision. We always use the 5W1H framework to communicate in our work. We also respect different ways of thinking. Basically, we communicate with each other on the basis of the understanding that people are different. Q. I think the support you receive from your team members stems from trust. What's your secret? A. In my day-to-day work, I make a conscious effort to support and mentor our members. We work together to help members achieve their goals. As a team, each of us is an indispensable member. Because we work together to achieve our goals, I believe we can support each other regardless of our positions as leaders or members. I think sincerity is essential. Summary and Future Prospects In this article, we interviewed Li-san, the DevOps team leader of Global Development Division, about cross-cultural communication and knowledge sharing in a multinational team, balancing motherhood with leadership responsibilities, and managing a multinational team. As she mentioned at the end, even in teams with members from diverse backgrounds, always be aware and respect that "people are different," and communicate ideas clearly through the 5W1H framework. We have found that the accumulation of these practices builds trust and enables us to efficiently support each other toward common goals. This is certainly not only true for multinational teams, but also for teams of the same nationality. We hope that this article will be of some help to those who are struggling to manage teams with diverse backgrounds. In the future, the DevOps team will face additional challenges as their businesses develop and technology evolves. However, with the efforts made thus far and the team's spirit of embracing diversity, we are sure that they can overcome any obstacle. We look forward to the team's future success and growth.
アバター
Introduction and Summary Hello. I am Miyashita, a membership management engineer in the Common Services Development Group[^1][^2][^3][^4] at KINTO Technologies. Today, I'd like to talk about how we solved the challenges we faced with building an S3-compatible local storage environment in our development site. Specifically, I'll share a practical approach on how to leverage the open source MinIO to emulate AWS S3 features. I hope this article will be helpful for engineers confronting similar challenges. What is MinIO? MinIO is an open source object storage server tool with S3 compatible features. Just like NAS, you can upload and download files. There is also a similar service in this area called LocalStack . LocalStack is a tool specialized in AWS emulation and can emulate services such as S3, Lambda, SQS, and DynamoDB locally. Although these two tools serve different purposes, both meet the requirements for setting up an S3-compatible environment locally. MinIO website LocalStack website Tool Selection with MinIO and LocalStack Development requirements As a development requirement, it was necessary to automatically create an arbitrary S3 bucket simply by running docker-compose, and register email templates, CSV files, etc., in the bucket. This is because it’s cumbersome to register files with commands or GUI after a container is started. Also, when conducting automated local S3 connection testing, the bucket and files must be ready as soon as the container starts. Tool Comparison After comparing which tool can easily achieve the requirements, LocalStack uses aws-cli to create buckets and operate files, while MinIO provides a dedicated command line tool, mc (MinIO Client). This made it easier to build the system. In addition, I found MinIO to be more sophisticated in the GUI-based management console. A comparison on Google Trends shows that MinIO is more popular. For these reasons, we decided to adopt MinIO. Compose Files To set up a MinIO local environment, a "compose.yaml" file must first be prepared. Follow the steps below. Create a directory. Create a text file in the directory with the filename "compose.yaml". Copy and paste the contents of compose.yaml below and save it. docker-compose.yml is not recommended. Click here for the compose file specifications * docker-compose.yml also works with backwards compatibility. For more information, click here. services: # Configure the MinIO server container minio: container_name: minio_test image: minio/minio:latest # Start the MinIO server and specify the access port for the management console (GUI) command: ['server', '/data', '--console-address', ':9001'] ports: - "9000:9000" # for API access - "9001:9001" # for the management console (GUI) # USER and PASSWORD can be omitted. # In that case, it is automatically set to minioadmin | minioadmin. environment: - "MINIO_ROOT_USER=minio" - "MINIO_ROOT_PASSWORD=minio123" # minio-managed configuration files and uploaded files # If you want to refer to the file locally or if you want to make the registered file persistent, # mount a local directory. # volumes: # - ./minio/data:/data # If you want the MinIO container to start automatically after restarting the PC, etc., # enable it if you want it to start automatically when it is stopped. # restart: unless-stopped # Configure the MinIO Client (mc) container mc: image: minio/mc:latest container_name: mc_test depends_on: - minio environment: - "MINIO_ROOT_USER=minio" # Same user name as above - "MINIO_ROOT_PASSWORD=minio123" # Same password as above # Create a bucket with the mc command and place the file in the created bucket. # First, set the alias so that subsequent commands can easily # specify MinIO itself. # This time, the alias name is myminio. # mb creates a new bucket. Abbreviation for make bucket # cp copies local files to MinIO. entrypoint: > /bin/sh -c " mc alias set myminio http://minio:9000 minio minio123; mc mb myminio/mail-template; mc mb myminio/image; mc mb myminio/csv; mc cp init_data/mail-template/* myminio/mail-template/; mc cp init_data/image/* myminio/image/; mc cp init_data/csv/* myminio/csv/; " # Mount the directory containing the files you want to upload to MinIO. volumes: - ./myData/init_data:/init_data Directory and File Structure Create an appropriate dummy file and start it with the following directory and file structure. minio_test# tree . . ├── compose.yaml └── myData └── init_data ├── csv │ └── example.csv ├── image │ ├── slide_01.jpg │ └── slide_04.jpg └── mail-template └── mail.vm Startup and Operation Check The following is the flow of running MinIO and its client on Docker and checking its operation. The Docker container is started in the background (using the -d flag) with the following command: If Docker Desktop (for Windows) is installed, containers can be created using a command line interface such as Command Prompt or PowerShell. ** Download Docker Desktop here * docker compose up -d * The hyphen in the middle of docker-compose is no longer added. For more information, click here. Docker Desktop Open Docker Desktop and check the container status. You can see that the minio_test container is running, but the mc_test container is stopped. Check the execution log of the mc_test container. MC Execution Log The logs indicate that the MinIO Client (mc) has been executed and all commands are completed successfully. Management Console Next, let's explore the MinIO GUI management console. Access port 9001 on localhost with a browser. http://127.0.0.1:9001 When the login screen appears, enter the username and password configured in compose.yaml (minio and minio123 in this example). List of Buckets Select "Object Browser" from the menu on the left. You will see a list of buckets created and the number of files stored in them. List of Files Select the "image" bucket as an example and look inside. You will see the pre-uploaded files. You can directly view the file by selecting "Preview" from the action menu next to the file. File Preview Function Our mascot character, the mysterious creature K , will be shown on preview. The function to preview images directly in MinIO management console is very useful. Installation of MC (MinIO Client) Using the command line can be more efficient than GUI for handling large numbers of files. Also, when accessing MinIO from source code during development and an error occurs, the command line is very useful for checking file paths. This section describes how to install MinIO Client and its basic operations. *If you are satisfied with the GUI management console, feel free to skip this section. # Use the following command to download mc. The executable file is stored in an arbitrary directory. minio_test/mc# curl https://dl.min.io/client/mc/release/linux-amd64/mc \ --create-dirs \ -o ./minio-binaries/mc # Operation check # Check if the installed mc is the latest version and display the version to check that it was installed correctly. # It is your choice whether to pass the mc command through Path. I will not pass through this time. minio_test/mc# ./minio-binaries/mc update > You are already running the most recent version of ‘mc’. minio_test/mc# ./minio-binaries/mc -version > mc version RELEASE.2023-10-30T18-43-32Z (commit-id=9f2fb2b6a9f86684cbea0628c5926dafcff7de28) > Runtime: go1.21.3 linux/amd64 > Copyright (c) 2015-2023 MinIO, Inc. > License GNU AGPLv3 <https://www.gnu.org/licenses/agpl-3.0.html> # Set alias # Set the alias required to access the MinIO server. minio_test/mc# ./minio-binaries/mc alias set myminio http://localhost:9000 minio minio123; > Added `myminio` successfully. # Example of file operation # Display a list of files in the bucket minio_test/mc# ./minio-binaries/mc ls myminio/image > [2023-11-07 21:18:54 JST] 11KiB STANDARD slide_01.jpg > [2023-11-07 21:18:54 JST] 18KiB STANDARD slide_04.jpg minio_test/mc# ./minio-binaries/mc ls myminio/csv > [2023-11-07 21:18:54 JST] 71B STANDARD example.csv # Screen output of file contents minio_test/mc# ./minio-binaries/mc cat myminio/csv/example.csv > name,age,job > tanaka,30,engineer > suzuki,25,designer > satou,,40,manager # Batch file upload minio_test/mc# ./minio-binaries/mc cp ../myData/init_data/image/* myminio/image/; > ...t_data/image/slide_04.jpg: 28.62 KiB / 28.62 KiB # File deletion minio_test/mc# ./minio-binaries/mc ls myminio/mail-template > [2023-11-15 11:46:25 JST] 340B STANDARD mail.txt minio_test/mc# ./minio-binaries/mc rm myminio/mail-template/mail.txt > Removed `myminio/mail-template/mail.txt`. List of MC Commands For more detailed documentation on the MinIO Client, please refer to the official manual. Click here for the official MinIO Client manual. Lastly, Access from Java Source Code After building an S3-compatible development environment using MinIO locally, I'll demonstrate how to access MinIO from a real Java application. First, configure Gradle. plugins { id 'java' } java { sourceCompatibility = '17' } repositories { mavenCentral() } dependencies { // https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3 implementation 'com.amazonaws:aws-java-sdk-s3:1.12.582' } Next, create a Java class to access MinIO. package com.example.miniotest; import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper; import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.S3Object; import com.amazonaws.services.s3.model.S3ObjectSummary; import com.amazonaws.services.s3.model.ListObjectsV2Result; import com.amazonaws.regions.Regions; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.List; public class Main { public static void main(String... args) { new Main().execute(); } /** *S3 compatibility test of MinIO *Obtain a list of files in the bucket and display the contents. */ private void execute() { System.out.println("--- Start ---"); // When connecting to a local MinIO, // switches when connecting to AWS S3. // Assumed to switch with the spring boot profile. boolean isLocal = true; // Since MinIO is compatible with AWS S3, // you can connect from the AWS library. AmazonS3 s3Client = null; if (isLocal) { s3Client = getAmazonS3ClientForLocal(); } else { s3Client = getAmazonS3ClientForAwsS3(); } // Bucket name final String bucketName = "csv"; // List all objects in the bucket. ListObjectsV2Result result = s3Client.listObjectsV2(bucketName); List<S3ObjectSummary> objects = result.getObjectSummaries(); // Loop as many filenames as possible. for (S3ObjectSummary os : objects) { System.out.println ("filename retrieved from bucket: " + os.getKey()); // Obtain the contents of the file in the stream. // Of course, files can also be downloaded. try (S3Object s3object = s3Client.getObject( new GetObjectRequest(bucketName, os.getKey())); BufferedReader reader = new BufferedReader( new InputStreamReader(s3object.getObjectContent()))) { String line; while ((line = reader.readLine()) != null) { // Screen output of file contents one line at a time System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } // Insert a blank line at the file switching. System.out.println(); } System.out.println("--- End ---"); } /** *Click here to connect to local MinIO. * @return AmazonS3 client instance is an implementation of the AmazonS3 interface. */ private AmazonS3 getAmazonS3ClientForLocal() { final String id = "minio"; final String pass = "minio123"; final String endpoint = "http://127.0.0.1:9000"; return AmazonS3ClientBuilder.standard() .withCredentials( new AWSStaticCredentialsProvider( new BasicAWSCredentials(id, pass))) .withEndpointConfiguration( new AwsClientBuilder.EndpointConfiguration( endpoint, Regions.AP_NORTHEAST_1.getName())) .build(); } /** * Obtain an Amazon S3 client and set up a connection to the AWS S3 service. * This method uses the IAM role at runtime on Amazon EC2 instance to automatically * obtain credentials and establish a connection with S3. * The IAM role must have a policy allowing access to S3. * * The client is configured as follows: * - Region: Regions.AP_NORTHEAST_1 (Asia Pacific (Tokyo)) * - Maximum connections: 500 * - Connection timeout: 120 seconds * - Number of error retries: Up to 15 times * * Note: This method is intended to be executed on an EC2 instance. * When running on anything other than EC2, AWS credentials must be provided separately. * * @return AmazonS3 client instance is an implementation of the AmazonS3 interface. * @see com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper * @see com.amazonaws.services.s3.AmazonS3 * @see com.amazonaws.services.s3.AmazonS3ClientBuilder * @see com.amazonaws.regions.Regions */ private AmazonS3 getAmazonS3ClientForAwsS3() { return AmazonS3ClientBuilder.standard() .withCredentials(new EC2ContainerCredentialsProviderWrapper()) .withRegion(Regions.AP_NORTHEAST_1) .withClientConfiguration( new ClientConfiguration() .withMaxConnections(500) .withConnectionTimeout(120 * 1000) .withMaxErrorRetry(15)) .build(); } } Execution Result --- Start --- Filename retrieved from bucket: example.csv name,age,job tanaka,30,engineer suzuki,25,designer satou,40,manager --- End --- Source Code Description A notable feature of this code is that the AWS SDK for Java supports both MinIO and AWS S3. When connecting to a local MinIO instance, use the getAmazonS3ClientForLocal method; when connecting to AWS S3, use the getAmazonS3ClientForAwsS3 method to initialize the client. This approach makes it possible to use the same SDK across different backend environments and the same interface for operation. It is nice to be able to easily test an application before deploying it to AWS environment without incurring additional costs. I hope you find this guide helpful. Thank you for reading my article all the way to the end.‍🙇‍♂ [^1]: Post #1 by a team mate from the Common Services Development Group [ グローバル展開も視野に入れた決済プラットフォームにドメイン駆動設計(DDD)を取り入れた ] [^2]: Post #2 by a team mate from the Common Services Development Group [ 入社 1 年未満メンバーだけのチームによる新システム開発をリモートモブプログラミングで成功させた話 ] [^3]: Post #3 by a team mate from the Common Services Development Group [ JIRA と GitHub Actions を活用した複数環境へのデプロイトレーサビリティ向上の取り組み ] [^4]: Post #4 by a team mate from the Common Services Development Group [ VSCode Dev Container を使った開発環境構築 ]
アバター
Introduction Hello. I'm Kazuki Morimoto from the Analysis Group in the Data Analysis Division. I usually work in the Osaka office and handle analysis topics such as those from the retention project, credit project, used vehicle division and the MyRoute app. (I'd like to post the details separately on the Tech Blog in the future.) In this article, I'd like to share with you what I've learned from using the preview version of "QuickSight Generative BI." When I attended a AWS Generative AI Workshop that was held for TOYOTA Group companies last month, I was introduced to it and thought, "This could be quite useful!" so I gave it a try. What you can find in this article An overview of QuickSight Generative BI I made a Sales Dashboard for a Ramen Subscription service Using Generative BI Good Points and Future Improvements Contents not covered in this article How to Use QuickSight Explanation of QuickSight Q How to Get Started with Generative BI ( This one was well written.) Announcing Generative BI capabilities in Amazon QuickSight What is Generative BI? Simply put, it is a service that applies Amazon Bedrock's LLM to "QuickSight Q" to add a wider range of functions. Originally, there was a function called "QuickSight Q" that enabled users to ask questions in natural language and receive answers with graphs. Applying Amazon Bedrock's LLMs (Large Language Models) to it has empowered us to perform analyses based on natural language with a higher degree of freedom. Quicksight Q *QuickSight Q is available in the Tokyo region and many other regions in Japan. Reference I Made a Dashboard Using Generative BI Let's try out Generative BI right away. I am going to create a dashboard imagining KINTO starting a Ramen subscription service . *As a side note, KINTO is a mobility service company, not in the ramen business... Or at least not for now... Goals This time, I will refer to the "Sales" segment of the Dashboard published by CRISP, with the goal of creating the following two dashboards. Sales (by year and month) Contract plan composition ratio Pre-preparation As a pre-preparation, I will create a service overview and sample data of this Ramen subscription. Service overview I asked ChatGPT to come up with Ramen subscription plans. The plans turned out to be way better than I expected. LOL I’m sold on that! Create sample data Next, I asked ChatGPT to create sample data with the following prompt. Results It generated a CSV file with plausible sample data for real. Practice Now, I'd like to import the sample data I just mentioned into QuickSight to create charts. This time, I'm trying it out using the Northern Virginia region in our in-house sandbox environment. *As mentioned above, how to get started with generative BI is omitted. 1. Create a sales (by year and month) graph First, I'd like to create a graph of sales (by year and month). Generative BI is only available in English (as of December 11, 2023), so I'll create prompts in English. Monthly sales estimates as of December 11, 2023 Enter the following prompt into "Build a visual." Cumulative Sum(Yen) in 2023-12 After pressing Build, the following board was created in about 3 seconds. After confirming that the output is as expected, click "ADD TO ANALYSIS" to add it as a visual. Create a monthly sales trend graph by month and year Similarly, enter the following prompt. Cumulative Sum(Yen) per months This also produced a graph that was almost as expected. Here is the result of manually changing the size of the graph after adding the visual. The horizontal axis is in "MMDD, YYYY HH/hh" format, which is difficult to read, so I changed the visual. Generative BI also seems to be able to make visual changes in natural language. As you may have noticed, my English skills are not very strong, so I rely on our in-house AI-ChatBOT (Sherpa) for support. I Typed in. Apparently, the visual editing functionality is still insufficient. Even if I check the official website , it seems that there aren't many things I can do yet, so I'll modify it manually. I'm looking forward to the future. Create a monthly sales ranking table by prefecture Next, I will try to output a visual in table format. Once again, with the help of Sherpa, I entered the following prompt. Please provide the monthly fee sum yen for each prefecture in a ranking format in a table in December 2023 (Three consecutive “in”s! ) Results How impressive. It displayed exactly the table I wanted. Added to the visual (graph size, etc., has been modified manually.) 2. Contract plan composition ratio Next, I'd like to see the percentage of subscription contract plans as a pie chart. As always, I asked Sherpa to translate and entered the following prompt. total unique number of Contract ID per contract plan in pie It's perfect! I also asked to display the total monthly fee for each plan. Total monthly fee for each contract plan in table Dashboard view Let's turn the created charts into a dashboard and check it. Generative BI created everything, except for the chronological format of the line graph. It looks pretty good, right? Exective summary There seems to be a function that creates a summary based on the dashboard contents. Click on "Executive summary" from the "Build" button in the upper right corner of the dashboard screen. A summary was created in about 10 seconds. The structure seems to be a description of the entire dashboard and each chart. Although it is very simple, the content appears to be accurate. Moreover, a link was embedded in the description of each graph. For large dashboards, clicking on the summary jumps to the linked graph, which is convenient. Good Points and Future Improvements Good points It creates charts instantly by giving natural language commands. For simple graphs, it is faster than making them manually. It will guess the column name to some extent even if you do not explicitly specify it. → Conversely, it is necessary to name the appropriate columns to be guessed. Monthly totals are also done automatically. The Executive Summary can be used as a basis for the material. Future Improvements The fine-tuning function of graphs is still insufficient. It would be faster to do this by hand than by natural language. English only. (As of December 11, 2023) The input field is short, making it difficult to correct sentences. After entering a long sentence, it was a little difficult to edit the sentence when the graph I wanted was not displayed. It does not understand chronological expressions such as last 3 months. Conclusion This time, I tried the public preview version of Generative BI. Although it is not at the level of practical business use yet, I think the service shows a lot of promise depending on future updates. If we can easily and quickly visualize the current situation, we will be able to accelerate the cycle of business improvement, so I look forward to the future. (This is a bit off-topic, but I was very surprised by the high degree of completion in the sample data and illustrations created by ChatGPT.) Furthermore, there is an article about the Analysis Group provided on the Tech Blog below, so please read it if you are interested. A Look into the KINTO Technologies Analysis Group
アバター
Introduction My name is Endo and I am the FE team leader of QA Group at KINTO Technologies. I mainly check QA cases from multiple products and projects for the frontend of the Japanese KINTO website developed by KINTO Technologies, and allocate and manage tasks to each of the QA team members. While working, I often engage in conversations with people from both the development side and QA. This time, when we were chatting, a question came up: "Why do we even do QA? " . Since I've been given this opportunity, I would like to share my own thoughts on this. Is QA Necessary in Development? Before writing about the role and necessity of the QA team on the theme, "Why do we do QA?", I would like to consider whether QA itself is necessary in the first place. In some seminars and articles on quality, there is a discussion about the necessity of QA. I have heard someone say that in Agile development, QA is unnecessary if each team has a QA role within the team, rather than having a separate QA team outside of it. For example, if there is a separate QA team from an Agile team, the following concerns may arise: Trying to be flexible in responding to specification changes in a sprint is likely to affect the subsequent QA process. The separate lead time for QA to understand the specifications lengthens the QA process. When a problem occurs, it is not addressed during the sprint, leading to significant rework. From these points, I think the main idea of the discussion was that Agile development can be managed without these concerns as long as there are members in the team who can handle everything from development to testing, including the role of QA. Here, I believe it is important to note that the role of QA itself is not being denied, even though a QA team may not necessary. On the contrary, those who argue that a QA team is necessary may believe that: By having a QA team independent from the development who can make objective judgments, quality can be improved from a different perspective. Knowledge from different specifications can be easily centralized in the QA team and information can be obtained across projects. Based on this conjunction of knowledge, the QA team can provide missing considerations and necessary information for other projects running in parallel. On the other hand, challenges of inserting a QA role within an Agile team include: The difficulty to include highly skilled team members who have the knowledge to oversee everything testing-related, from development to system testing If that is not the case, then it will be necessary to train team members, but acquiring the appropriate skills takes time. Knowledge pools easily around skilled members, and when those leave the team, it becomes difficult to handle QA. I have come across an article in columns of other companies that they do not have a department or group called QA, yet they do QA work for their service users. In other words, whether to create a QA team as an organization is a choice based on development methods and organizational culture. However, I feel that everyone has a common understanding that the role of QA is necessary to check the overall quality for users based on system requirements. The Role of QA Beyond Testing When conducting confirmation and verification, QA is often seen as a specialized testing team, leading to a common misconception that QA is synonymous with testing. However, the role of QA is not only limited to testing. Here are three major aspects on this point. (1) Confirm the correct understanding of specifications When designing test scenarios, QA has to confirm system requirements and will ask questions when needed to the development and operations sides. From the point of conducting testing, QA first confirms what the “correct answers” are to the specifications, based on the requirements. Through this process, QA can point out details in the specifications, helping prevent requirement omissions and to refine the information given in the specifications. The following is an example of a case where the "Screening Application Process" section of the KINTO website was revised. In this case, the expected test result is that the design of "What is required for the application" and "Screening application steps" will match the screen specification. What is required in case of a regular web application is to upload a driver's license image. However, as KINTO services are also offered via dealerships where driver's licenses can be verified on the spot, the system should be created so that the dealership staff could skip the image upload (as indicated by the red box below). When we consulted this point with the development side, they realized that it was necessary to take it into consideration. While it may be a minor detail, we consider the expected use cases and conditions, ensuring that the correct answer aligns with the expected test results. In this way, the specifications that should be in place are confirmed by making specifics for ambiguous expressions or omissions. As mentioned above, through specification checks from the QA team, it is sometimes possible to point out requirements that the development side was not aware of. In addition, by aligning test perspectives in parallel with the development process, although not at the requirements definition stage, we can enhance quality earlier, before testing is conducted. (2) Organize documentation during test design Working on tight deadlines during development can pose challenges to organize documentation effectively. Even if each specification is available, there are cases where it may not be listed or the operating procedures may not be organized. In QA, while confirming the correct answers to the specifications mentioned in (1) above, the following aspects are identified as necessary in test design: scenarios, function confirmation, and display confirmation. In this case, the original information is in the development side, so basically the materials are used as they are, but if necessary, QA lists procedures and organize the information to facilitate what to check during tests. We sometimes receive positive comments from members outside of the QA team, such as how they were able to gain a bird's-eye view of the overall functionality by referring to the materials created by QA, or how helpful it was in confirming certain processes. Since the information is consolidated within the project, the contents of the materials compiled by QA are not necessarily the latest, but they are organized for the purpose of understanding the current specifications. In addition, since QA can observe projects running in parallel from a horizontal perspective, they can provide information on concerns to the development side while organizing specifications, which can be helpful in terms of quality. (3) Feedback from defect analysis After a project is completed, a defect analysis will be conducted based on the results of the QA testing. The following is mainly done on a project-by-project basis. Depending on the characteristics of each project and product, we offer feedback which may include requests for additional consideration during the requirement definition stage or for stronger emphasis on unit testing. By providing feedback to the project at review meetings, they will be able to use it as a reference for the progression of the next project tasks. When analyzing defects, we collaborate to clarify the defect trends for each product and identify project-specific issues that need to be addressed. It is important to report not only the weaknesses of the project but also the effects. For example, sharing a different approach to fulfilling requirements from a different project to provide insight; or if the portion of a unit test was successful it is crucial to communicate what has been effective. Our reports are to guide the initiative towards a positive direction and strengthen it further, so we are cautious to address not only negative aspects when giving feedback. Consequently, the role of QA is significant not only in testing, but also in building quality. So Why Do We Practice QA? For us who provide web and app services, for example, Design is consistent, but buttons are in different positions on different screens Screen transitions take time While there are no issues on a PC, the text becomes challenging to read on a smartphone due to changes in display size. If these issues persist, users may choose not to use the service, finding it difficult to use or view before even experiencing the appeal of the service. I believe that performing QA work is meaningful not only to confirm that the requirements are met, but also to improve a website so that visitors can use it comfortably. In addition, since system requirements can be checked horizontally through QA work, it also plays a role in discovering unexpected project risks by obtaining a certain level of specification information. As KINTO Technologies has multiple projects running concurrently for each product, Are there any risks associated with the timing of project releases? If a common specification changes, are other products that may be affected aware of the changes? By conducting a series of tests, are there any issues with the functionality, including linking data across products? Even in areas where the project side has already considered risks, we check them again during QA to identify any remaining risks and ensure built-in quality. In this way, I think it is necessary for QA to confirm the requirements from an objective viewpoint for our customers who actually use the service, and provide support for the creation of quality aspects. I believe that this mindset of "for our customers" is important. Our services are used by the majority of people. However, the customer faces the service as an individual. We must prevent a situation where the customer never visit our website again due to minor difficulties in use or view. Therefore, I believe that the mindset of “for our customers” plays an important role in creating a positive cycle. It effectively communicates the appeal of the services we aim to convey, ultimately leading to the acquisition of more customers. Conclusion In this article, I wrote my thoughts starting from the point of why we do QA in the first place. As mentioned earlier, the role of QA varies from organization to organization. If you agree with this content or if you have different opinions and are interested in QA, please feel free to contact me. Moreover, If you find the idea of doing QA together enjoyable, or if you want to make QA more exciting and better, you are always welcome! Please apply from the recruitment page below. We can start with a casual interview. https://hrmos.co/pages/kinto-technologies/jobs?category=1783696806032474116
アバター
Introduction Hello I'm Nakahara who is in charge of frontend development for KINTO ONE (Used Vehicles) at KINTO Technologies. KINTO ONE (Used Vehicles) is an e-commerce site for leasing again vehicles that were once leased through KINTO ONE before, allowing users to check information on actual vehicles in stock, complete the contract process, and manage their contracts. KINTO ONE (Used Vehicles) Website Despite the extended delivery times for new vehicles, this service comes highly recommended due to the availability of high-quality vehicles with relatively short delivery times and a ¥0 cancellation fee for mid-term cancellations. (As of December 2023, this service is available only in Tokyo and Aichi Prefecture.) Vehicle Image Issues Unlike new vehicles, a site that handles used vehicles treats each individual vehicle as a product. Naturally, e-commerce sites must display images of each vehicle. To commercialize the lease-up vehicles, KINTO ONE (Used Vehicles) takes photos of each vehicle, and stores the images in the backend vehicle management service. To display on the site, the vehicle information, including the image URLs, was obtained from the backend and built as a page in the frontend server container, while the vehicle images were obtained from the client side, from the image distribution path of the vehicle management service. --- title: Server Configuration (Overview) --- flowchart LR %%External Element User U[User] %%Group and Service subgraph GC[AWS] subgraph FE[Used Car Site Frontend] subgraph CF["Cloudfront"] end ECS("Frontend Server") end subgraph BE[Vehicle Management Service] UCAR("Vehicle Management Server") end end %% Relationship between services U --> |"Site Access"|CF CF --> ECS ECS --> |"Obtain Vehicle Information"|UCAR U --> |"Obtain Vehicle Image"|UCAR %%Group Style classDef SGC fill:none,color:#345,stroke:#345 class GC SGC Here, the vehicle images distributed by the vehicle management service were one-size JPGs, which caused the following problems. Inefficient compression Distribution at a size not related to the display size Regardless of the display size on the actual site, images over 1000px in width were distributed PageSpeed Insights , which measures site performance in practice, also pointed out several aspects related to vehicle images. PageSpeed Insights indication Ideal State The first thing that can be mentioned is the improvement of the points indicated by PageSpeed Insights. Efficient compression method of distribution Distributing images in sizes according to the display sizes These improvements not only enhance page display speed and reduce client's network traffic, but also improve server-side costs[^1]. In addition, from a development and operational standpoint, the following points can also be mentioned for achieving the ideal state. Minimize additional resources[^2] Can request image conversion settings from the frontend side Low cost and quick response Since adding resources will increase the associated management workload, it is desirable to keep the configuration as small as possible. For conversion settings, we keep in mind that the requirements for displayed images may change due to design modifications or the addition of new types of high-resolution devices. In such cases, it is desirable to be able to change the resolution and compression method of the images easily obtained from the frontend side. [^1]: KINTO Technologies mainly builds its services on AWS, but data transmission to the internet is also costly point [^2]:. "Resources" here refers to the concept that includes not only AWS resources but also external services for image conversion. Review of Image Conversion Methods Image conversion and distribution at the time of photo registration on the vehicle management service side This method can be said to meet the requirement if only a predefined one is created, but it is not chosen because it does not align with the preceding sections, "Minimize additional resources" and "Can request image conversion settings from the frontend side." Use of external services There are various CDNs with image conversion functions, including imgix, but we did not select this one either. Based on site usage, the US$200-300 per month plan seemed to fit. In addition, it is likely to require some workload to change the settings for the current image management storage and to make internal adjustments for this. Although it is good that we do not have to spend workload for monitoring by using an external service, we did not choose this because KINTO ONE (Used Vehicles) is still a developing service, and it is difficult to estimate its implementation effect in terms of monetary and time costs. Remote image optimization of Next.js The method that requires the least workload to implement is to optimize images using the Next.js Image Component. However, we decided not to choose this method because it does not suit the current site situation. Currently, we use Next.js as a framework for site distribution by server-side rendering, but the server is running on a relatively small instance configuration. However, due to the high number of images per page, the processing load spikes. It seemed necessary to increase the instance size at the minimum load. In fact, the site sometimes went down when the same settings were applied at the beginning of the service. We opted against this method to avoid increasing the instance size just for image conversion. Build our own method with Lambda@Edge (★ chosen option) This method is used in combination with Cloudfront to execute a function that performs image conversion on the edge side and distribute the converted images. The site itself was delivered via Cloudfront, so it seemed like it could be implemented quickly with just a few additional settings. The cost of the conversion process is almost minimal due to the number of images, and compressing the image size can further reduce the transfer cost. It takes a little time and effort to implement, but since the server-less operation is available from then on, so as long as the number of concurrent executions is taken care of, it did not seem to require that much time and effort to manage. Therefore, we decided to use this method. Adding the Image Conversion Function in Lambda@Edge Change to the following configuration: --- title: Server Configuration (after amelioration) --- flowchart LR %% External Element User U[User] %% Group and Service subgraph GC[AWS] subgraph FE[Used Car Site Frontend] subgraph CF["Cloudfront"] LM["Lambda@Edge<br>Resize/WebP Conversion"] end ECS("Frontend Server") end subgraph BE [Vehicle Management Service] UCAR("Vehicle Management Server") end end %% Relationship between services U --> |"Site Access"|CF CF --> ECS ECS --> |"Obtain Vehicle Information"|UCAR U --> |"Obtain Vehicle Image"|CF LM --> |"Obtain Vehicle Image"|UCAR %% Group Style classDef SGC fill:none,color:#345,stroke:#345 class GC SGC We added a behavior when accessing a vehicle image path to return the result of resizing and converting to WebP using Lambda@Edge. Regarding the processing contents of Lambda@Edge, there is a lot of information such as Precedents ^3 and AWS official guide ^4 , so I won't delve into details. Instead, I'd like to touch on some key points in this implementation. Specifying image conversion contents with query parameters The image conversion settings should be able to be specified with the following query parameters. query Description width Specify the width of the image after resizing quality Set the image quality during conversion This allows the site to retrieve images of the size the site side wishes to display at the specified size and quality. Cache settings Set the query parameters above as cache keys. Failure to do so may result in caching the previously generated image, resulting in displaying a smaller image when a larger one is requested. Custom loader next/image settings Once image conversion is enabled on the Cloudfront side, it is necessary to implement it on the page side as well. Since this service is built on Next.js, it is possible to request the optimal image size for the displayed size by setting a custom loader for the Image Component, without need for detailed settings. Note that the sizes property setting is important to select the optimal size for display. By setting this value, the srcset property will be configured appropriately for the actual display size when rendering the Image Component. import Image, { ImageLoaderProps } from "next/image"; // components for vehicle image export function CarImage({ src, sizes, alt = "vehicle Image", className = "" }) { // custom loader function optimizeLoader({ src, width, quality }: ImageLoaderProps) { return `${src}?width=${width}&quality=${quality}`; } return ( <Image className={className} src={src} alt={alt} sizes={sizes} quality={90} loader={optimizeLoader} loading="lazy" /> ); } By creating and using such a component, images can be requested with parameters for image size according to the display size on the site, and resized and WebP converted images can be displayed. Results We have confirmed that image optimization using this method has successfully eliminated the image-related indications in PageSpeed Insights. PageSpeed Insights image-related indications have been resolved. Conclusion This time, we attempted to optimize the display images as part of the site performance improvement. However, there are still a lot of performance issues. We will continue to improve site performance and strive to provide a more enjoyable experience for users.
アバター
はじめに こんにちは、今年 1 月に入社した yuki.n です! 2023 年 12 月入社のみなさまと今年 1 月入社のみなさまに入社直後の感想をお伺いしました! KINTO テクノロジーズに興味のある方、そして、今回参加くださったメンバーへの振り返りとして有益なコンテンツになればいいなと思います。 星野 自己紹介 1 月にできた新設部署であるモビリティプロダクト開発部の副部長として入社した星野です。 これまでテクニカルな目線でサービスを作る、運営する、ということを仕事にしてきました。 所属チームはどんな体制ですか? 配下に 4 チームあり、① 自社メディア担当、② インキュベーション案件担当、③ 販売店向けツール開発担当、④ 販売店向けツール企画担当といった感じです。社員数は 2 月時点で 23 名で、エンジニア中心ですが、プロデューサー、ディレクター、デザイナーもいるので、事業を回せる体制です。 KINTO テクノロジーズ(以下 KTC)へ入社したときの第一印象は? ギャップはありましたか? ちゃんとしている! 部署説明だけでなく、商流説明、ビジョン、中長期計画といった、中途社員中心だからこその同じ方向を向くためのオリエンテーションが充実しているのは素晴らしいと思います。 現場の雰囲気はどんな感じですか? 年齢層は二十代〜四十代と幅広いメンバーがいるのにもかかわらず、みな和気あいあいとした感じです。社歴が長いメンバーが多いのかと思いきや、入社してまだ半年経っていない社員も多く、新しい人を向かい入れることへの寛容さを感じます。働き方も多様で、他の部署に比べてリモート勤務の頻度が高いようです。 過去の経歴も様々なので、チャレンジしたい人にはとてもよい部署だと思います。気になる方はぜひ採用担当にご連絡を! ブログを書くことになってどう思いましたか? とても良い取り組みだと思います。情報発信ができる組織は採用競争力を有利にしますからね。 【Romie さんからの質問】サービスを作って運営することは、スタートでつまづくと後から取り戻すのがすごく大変な印象です! そこで最初に着手するにあたって見逃してはいけないポイントや大切にしているマインドを教えてください。 サービスは使われ始めてからがスタートで、そこから価値が発生し、育てていく必要がある、という認識が重要ですね。簡素に表現すると「運用し続ける体制を考慮する」ということでしょうか。ただ新規性のあるサービスは受け入れられない場合もあるので、スタート時点ではマスト要件だけに絞って、最小限でスタートするのも大事かなと思います。サービスなので、スタートした以上はトラブルよりも何よりも「(利用者にとって)サービス終了になる事態」が最も避けるべきこと、という意識も大事で、持続性/継続性についてはプロダクトオーナーとしっかり握っておくと良いと思います。 Choi 自己紹介 12 月に入社した KINTO ONE 開発部 新車サブスク開発 G の Choi です。 これまで色んなウェブサービスのフロントエンド・バックエンドの開発をやってきました。 所属チームはどんな体制ですか? コンテンツ開発チームとして私含め9人の体制となっています。 ほとんどがフロントエンドのエンジニアです。 KTC へ入社したときの第一印象は? ギャップはありましたか? 入社後のオリエンテーションがしっかりあったので、システムがよくできていると感じました。大手会社のシステムと若い IT 会社とのハイブリッドな感じですごくいい印象でした。 エンジニアの方々がベテランで、かつ新しい技術に探究・勉強していることが第一印象でした。 現場の雰囲気はどんな感じですか? 入社して1か月は分からないことが多かったのですが、チームの皆さんが親切で業務上の質問などに教えてくれていました。 勤務先の大阪オフィスはまだ 30 人近くの少人数で、他の部署の方とコミュニケーションがよく取れています。月1回情報共有会でオフィスのメンバーと LT 会、オフィス環境の改善に関して意見共有などを行っています。 ブログを書くことになってどう思いましたか? 日本語を書くのが苦手なので少し不安でしたが、この2か月間の自分の振り返りができたのでいいと思います。 【星野さんからの質問】フロントエンドエンジニアとして「これは秀逸!」と思ったアプリがあれば教えて下さい。 最近のフロントエンドは技術進歩のスピードが早い感がありますね。UI/UX もユーザーフレンドリーになっているサイトが多いです。特にこれはすごい! と思ったアプリはないですが、私はフロントエンドだけではなくバックエンドやアプリ開発の経験もありまして、その観点で最近 Flutter や React Native などでプラットフォームの制約なく作成できるのに興味があります。既に公開されて何年か経っていますが、私が最初にアプリ開発した際は Android、iOS、ウェブアプリを別々作らないといけなかったのでその工数がなくなるのはエンジニアとしてすごく助かる! と思います。 YI 自己紹介 プロジェクト開発部 オペレーションシステム開発 G の YI です。 前職は SIer で業界・業種問わず、またフロント/バックエンド問わず様々な開発プロジェクトで主に B2B のシステム導入に関わるプロジェクトに従事してきました。 KINTO ONE 中古車に関連したバックオフィス業務で扱うシステムの開発をしています。 所属チームはどんな体制ですか? 中古車システム T として 5 名、その他 BP さんが 10 名程度の体制となっています。 KTC へ入社したときの第一印象は? ギャップはありましたか? 高価なソフトウェアライセンスの購入が景山さんへの Slack 承認だけで進み、翌日には使えるようになっていたのには驚きました。 現場の雰囲気はどんな感じですか? 同年代の方々が多い印象なのと、様々なバックグラウンドを持つ方がいらっしゃるという雰囲気を感じています。 ブログを書くことになってどう思いましたか? 実は Tech Blog は入社前から見ていたのでこの企画についてもなんとなく知っていたのですが、改めて書くとなると「来たか…!」という気持ちでした。 【Choi さんからの質問】社内で業務外でしたいアクティビティーがあれば教えてください(趣味・スポーツなど)。 高校の部活からやっていたテニスは「ktc-テニスクラブ」、あとは「ゴルフ部」「自動車部」等をやってみたいと思います。普段の業務では中々関わることのない方々と「横のつながり」ができることはとてもよいことだと思っているので、色々と楽しみたいと思っています! HaKo 自己紹介 データ分析 G 分析プロデュース T の HaKo です。 調査会社や小売通販会社でリサーチやアナリストをやってきました。 人はどういう思いでサービスを利用したり、何を思って利用しているのか、を知る事に面白さを感じています。 所属チームはどんな体制ですか? リーダーと自身を含めて総勢 9 名。 細分化されていたチームが集約してひとつのチームになった歴史有り。 KTC へ入社したときの第一印象は? ギャップはありましたか? 年齢層高めの環境に在籍する事が多かったので、ガチガチな「御作法」が少なくて感動しました。 現場の雰囲気はどんな感じですか? 皆それぞれ得意分野・専門領域を持っていると感じており、多種多様な刺激を得られる現場だと感じています。 ブログを書くことになってどう思いましたか? ブログを書くこと自体が初めてなのですが、遠い昔に mixi で徒然なるままに日記を書いていた頃を思い出しました。 【YI さんからの質問】KTC に入社したことで変わったことはありますか? 入社早々に引き継ぎ案件が多かったのですが、これまで主戦場としてきた販促企画や分析からではなく、メルマガ配信の仕組みなど技術的な側面から入っていくようになった気がします。 yuki.n 自己紹介 KINTO ONE 開発部 新車サブスク開発 G の yuki.n です。 今年1月にフロントエンドエンジニアとして入社しました。大阪配属です。 フロントエンドに限らず、いろいろ携われたら嬉しいな、と思っています。 所属チームはどんな体制ですか? 新設されたチームということもあり、現時点ではチーム内外問わず、わたし含めて4名で動いています。 KTC へ入社したときの第一印象は? ギャップはありましたか? 入社時のオリエンテーションだったり、会社のルールだったり、いろんなところがとてもしっかりしていてびっくりしました。 あまりない経験だったこともあって、ものすごく新鮮でした。 現場の雰囲気はどんな感じですか? 居心地がよく、いい意味での落ち着きを感じています。自分以外のメンバーはみなさん東京にいらっしゃるのですが、コミュニケーションについて特に壁を感じず、気兼ねなくやり取りさせてもらえています。また、自分の「やってみたい」を受け入れていただけるなど、かなり自由にやらせてもらっているので、ありがたい気持ちでいっぱいです。 ブログを書くことになってどう思いましたか? 会社でのブログは初めての経験なので書くこと自体緊張ですが、すごく良い取り組みだと思いました。 【HaKo さんからの質問】KTC に入社して驚いた事や感動した事を教えてください。 「現場の雰囲気」のところと重複しますが、入社直後なのに、すでに自分の「やってみたい」を受け入れていただけていることです。びっくりと感動を同時に味わいました。 きーゆの 自己紹介 プロジェクト開発部プロジェクト推進部のきーゆのです。KINTO FACTORY のフロントエンド開発を担当しています。室町オフィスに勤務しています。 所属チームはどんな体制ですか? 私含め 6 名でフロントエンドの開発をしています。チーム内の最年少エンジニアという肩書きを欲しいままにしています。なんなら KTC 全体で見ても最年少の部類かもしれない。 KTC へ入社したときの第一印象は? ギャップはありましたか? いい意味でゆるいなという印象でした。ギャップは特になく、期待通りのゆるさで幸せです。これをやりたい! をどんどん受け入れてくれるところが素敵です。 現場の雰囲気はどんな感じですか? 「アットホームな井の中の蛙」が自チームの特徴です。チーム内コミュニケーションが活発で個人を尊重しあえる一方で、内向的で対外的な影響力に改善の余地があるチームです。 という結論がストレングスファインダーでわかりました。私も入社後とても手厚く迎え入れていただいたので、すぐに馴染める雰囲気です。 ブログを書くことになってどう思いましたか? 前職でもテックブログをお願いされたことがあったので、特に気構えるようなことはありませんでした。量産型シャイボーイなので自己開示は不安ですが、少しでも興味を持ってもらえたら嬉しいです、弊社に。 【yuki.n からの質問】技術面でいま興味のある・追いかけていることについて教えてください! ChatGPT 等のアウトプットを最大限に高めるための”プロンプト力”という分野を追いかけています。KINTO テクノロジーズで活用されている”しぇるぱ”を利用する際にも、この分野が活きています。 K 自己紹介 プロジェクト開発部プロジェクト推進部の K です。 Salesforce 開発を担当していて、室町オフィスに勤務しています。 前職は SIer で業種問わず、マルチクラウドのシステム導入に従事してきました。 所属チームはどんな体制ですか? Salesforce チームとして 4 名、その他 BP さんが 10 名程度の体制となっています。 KTC へ入社したときの第一印象は? ギャップはありましたか? 技術系の勉強会が多いことが第一印象でした。 現場の雰囲気はどんな感じですか? ベテランのエンジニアの方が多くて、皆新しい技術を積極的に勉強していることを実感しました。 ブログを書くことになってどう思いましたか? これから KTC テックブログを執筆することになりましたので、良い経験になるかと思います。 【きーゆのさんからの質問】開発する上で大切にしているマインドを教えてください! 技術の進化やプロジェクトの要件の変化に対応できる柔軟性が必要で、新しい状況に適応し、柔軟に対処することが重要だと思います。 問題が発生した際に冷静に対処し、効果的な解決策を見つける能力が求められます。ルーチンな問題解決だけでなく、創造的な解決方法も模索することが大切だと考えています。 向井 (mt_takao) 自己紹介 12 月入社の向井 (mt_takao) です。前職では、タクシー配車アプリの toB 向けプロダクトの(デジタル)プロダクトデザイナー兼プロダクトマネージャーを主に担当していました。 KTC でも、前職同様、プロダクトデザイナーとして、トヨタ販売店向けプロダクトのデザイン開発全般を担当しています。 所属チームはどんな体制ですか? 所属部署は、モビリティプロダクト開発部 オウンドメディア&インキュベート開発グループ DX Plannning チームです。 トヨタ販売店が抱えている課題やお困りごとをデジタル・テクノロジーの力を活用して解決を目指していくことをミッションに日々取り組んでいます。 KTC へ入社したときの第一印象は? ギャップはありましたか? 入社時のオリエン等のオンボーディングが想定していた以上に整備されている印象を受けました。 組織課題などは入社前に何度もお話を聞く機会をいただき、十分に把握した上で入社の意思決定をしたので、大きなギャップはありませんでした。 現場の雰囲気はどんな感じですか? 自分が所属している DX Planning チームは、組織が出来てまだ若く、最近入社した方が多いのですが、それぞれがこれまで経験してきたものを活かし、泥臭く推進していく姿勢に共感しています。 ブログを書くことになってどう思いましたか? 個人としても組織としても発信力強化は課題と捉えており、その機会をいただいたことに感謝しています。 【K さんからの質問】UI/UX 観点で最高と思ったデザインがあれば教えてください。 最高のデザインと言うと結構難しいのですが、最近注目しているものと言えば、「 Apple Vision Pro 」です。既に、AR や VR と現実世界を拡張したようなテクノロジーが世の中に浸透し始めているようですが、いよいよ空間自体でアプリケーションを実行できるそんな世界がやってきたのだと感じました。 参考 Apple Vision Pro 実機レビュー。「空間全部を仕事に使う」世界がやってきた まだ、アメリカでしか体験できないようなので、日本で触れるようになったら体験したいと思います。 余談ですが、Microsoft 社の未来を描いた「 Productivity Future Vision 」も、Apple Vision Pro が実現する世界に近いと思うので、ご興味あればご覧ください。 Romie 自己紹介 2023 年 12 月に入社した Romie です。プラットフォーム開発部モバイルアプリ開発 G 所属です。 組み込み →Web 系からのモバイルアプリ開発なのでまだまだこれからです。 所属チームはどんな体制ですか? iOS/Android と分かれていて Android 側ですが私を入れて 5 名です! うち 3 名が外国の方です。多国籍です。 KTC へ入社したときの第一印象は? ギャップはありましたか? 最新の技術を積極的にキャッチアップしていてスピード感に驚きました。 会社のバックアップはしっかりしていて、社風は思った以上に自由で感激しました。 現場の雰囲気はどんな感じですか? お互い遠慮せずに意見を言えて安心して仕事ができる感じです。バックグラウンドがそれぞれ違いますが、フラットな関係性でバランスの取れたチームだと感じます。 ブログを書くことになってどう思いましたか? アウトプットは日々の振り返りにもつながりますし、コツコツ情報発信しているとそれだけ注目度も上がりますからこれからもやっていきたいと思いました! 【向井さんからの質問】KTC or モビリティ領域で、どんなことを成し遂げたいですか? 私はモバイルアプリ開発の担当者ですので自分が任されているアプリを通じて KTC ひいてはモビリティ領域に貢献したいです。そのためには絶えず技術をキャッチアップし、目の前のプロダクトの成長・発展に取り組みたいと思います。 さいごに みなさま、入社後の感想を教えてくださり、ありがとうございました! KINTO テクノロジーズでは日々、新たなメンバーが増えています! 今後もいろんな部署のいろんな方々の入社エントリが増えていきますので、楽しみにしていただけましたら幸いです。 そして、KINTO テクノロジーズでは、まだまださまざまな部署・職種で一緒に働ける仲間を募集しています! 詳しくは こちら からご確認ください!
アバター
Introduction Hello everyone! This is Mori from the Global Development Division and the Tech Blog operation team. I usually work as the Product Manager (PdM) for the Global KINTO Web and the lead for compliance with personal information-related laws in various countries. (Well, I'm doing all kinds of things lol) To share some updates from me, the team I lead, the Product Enhancement team changed its reporting line as of July due to shifts in our organizational structure. (The team name has also changed a little! ) The new group manager for us is Mizuno-san. There has been some communication in the past, but not too much interaction with him and the other teams under Mizuno-san, so we took this opportunity to conduct a "Leadership Integration" workshop with the group manager and team leaders. Today, I would like to share its report📝 It was held in August, but my writing was slow and this article was released at the end of the year😅 What is Leadership Integration? Leadership Integration serves as a framework for communicating between leaders and team members to enhance team cohesion. It is effective when onboarding a new leader or when addressing team relationship issues that require improved team cohesion. Reference: An Encouragement of Leadership Integration I became aware of this workshop when I heard that it was conducted by the Corporate IT Group. Apparently, they had experience in their previous jobs. It wasn't exactly the same as "when onboarding a new leader," but it was right around the time I joined the new reporting line and I hadn't had much interaction with other teams, so I thought, "Why not?" I approached my manager and he readily agreed, so I asked Zushimi-san from Corporate IT Group to facilitate the workshop✨ Leadership Integration Flow Date & Time: 17:30-19:30 August 29, 2023 Place: Jimbocho Office Participants: Global Product Introduction Group, Global Development Division 1 manager (hereinafter “leader”) 5 team leaders (hereinafter “member”) Facilitator: Zushimi-san from Corporate IT Group Time Action Time (m) 17:30 Explanation of initiatives / Facilitator Introduction 5 17:30 Opening from the leader 3 17:33 (Leader leaves the room) 17:35 Write down what members know about the leader 15 17:50 Write down what members don't know about the leader 15 18:05 Write down what you want the leader to know 15 18:20 Write down what members can do for the leader and the group 15 18:35 (Members leave the room, and leader enters the room) 18:40 Time for the leader to look at the opinions expressed by everyone and think about the answers 10 18:50 (Members return to the room) 18:55 Response time from the leader! 30 19:25 Buffer and free talk 5 20:00 Get-together Introduction As introduction, the facilitator and the leader gave respectively an explanation of this workshop and its background. This time, Mizuno-san said, "I'd be happy to receive opinions from everyone in a place different from the usual one-on-one meetings." And then, surprisingly, he left the room! But this is when it really starts. Writing Time by Members It’s when members write down what they know, what they don't know, what they want the leader to know, and what each member can do for the leader. I can't share too much here because some of the content is private, but I will try to mention a few things that came up (Sorry, Mizuno-san). What Members Know About the Leader📝 When he joined KINTO Technologies, he was first in charge of the Used Vehicle projects in Japan. He then joined Global about a year ago. He likes cats.🐱 He likes driving,🚗 etc. Although not for the other leaders, he was a new manager to me, so I often thought, "Oh, I didn't know that about him" during the workshop. What Members Don't Know About the Leader📝 The reason for joining KINTO Technologies. Career to date Development experience 💻 What he evaluates, etc. Here, on the contrary, I had the impression that "surprisingly, everyone is thinking the same thing." What Members Want the Leader to Know📝 The want to communicate more. Interest in getting involved in R&D. The struggle with member management. Interest in going camping with everyone⛺, etc. Since the workshop was held on our assessment period, and we had all become evaluators for the first time due to the organizational changes, we found that we were all struggling with the same issues. What Members Can Do for the Leader and the Group📝 Knowledgeable about vehicles and the automotive industry. Able to listen to leader’s complaints. Having connections with other development teams Able to plan study sessions for engineers. Happy to give new business ideas, etc. I was surprised, in a good way, at the number of things that each of us could do. Response Time from the Leader Then the leader joined and answered each of the sticky notes in place. Without knowing who wrote what, the leader shared his thoughts. As it is not every day you get a chance to hear what a manager thinks, 30 minutes passed in no time. We were able to hear about his personal life, such as his love of cats despite his cat allergy (poor thing!), that he has a closet full with only white t-shirts and black pants (I think I’ve heard a similar anecdote somewhere...), as well as his opinion about the members, such as the importance of what has changed since the beginning of the term, and wanting members to do their best without being demotivated. In particular, when it came to “what members want the leader to know” and “what members can do for the group”, as there were a lot of enthusiastic notes, the leader’s comments included, "Let's share evaluations and organizational concerns with each other," "Let's work together to solve communication challenges," and "I understand that I can leave more to them." Somehow, the impression that the team was united made me feel passionate. The wall was covered with this many sticky notes! Sorry about the mosaic Impressions I participated as a member, and it was great to hear what each team leader was thinking, not to mention the deeper connections I made with the manager. Since some projects do not give the opportunity to work with many people and not everyone was familiar with all participants, this event was a good opportunity to check if we were on the same page. I discovered that all participants were thinking seriously about KINTO Technologies and about Global KINTO, more than I had imagined. Voice from Participants: It was good to know about the challenges other team members were facing. I was able to see the depth and breadth of what I want and know about my leader and compare it objectively with other members. In order to create an atmosphere that is easy to talk, I tried not to get angry or show negative emotions. I discovered that my approach may not have been entirely wrong. It might be a good idea to do a look back or something a few months later to check on the status of what was agreed on the workshop. Even things you don't dare to tell sometimes hold meaning for others. This kind of workshop is effective to bring these things out. For myself, the timing was good because I was new to the group, but others seemed to have a sense of "why now?" I regret not having considered the timing of the workshop. However, there was no opinion that it was completely meaningless, so I felt that it would be even more effective at times such as when a new leader takes office! Conclusion Throughout the workshop, I felt that the results can be greatly influenced by facilitation, such as time allocation or talking to participants while they are writing. For example, when you can't write your thoughts down very well, the facilitator suggested "Have you thought about XXXXX?", or gave good remarks such as "Right, this is also a new discovery, isn't it?" He also considered the allocation of time in a flexible manner. Thank you, Zushimi-san, for coming all the way to Jimbocho🙏 Lastly, if you are going to conduct a Leadership Integration workshop, here is a book that was recommended to me. The power of facilitation is truly amazing when done right! 🥺✨ @ card This article has become quite long, but I'd like to close with a picture of the huge, delicious lamb we enjoyed at the get-together🍖🤤 Thank you very much🙏
アバター
Introduction to Istio for Non-Infrastructure Engineers Hello. I'm Narazaki from the Woven Payment Solution Development Group. We are involved in the development of the payment infrastructure application used by Woven by Toyota at Toyota Woven City , and are developing payment-related functions across the backend, web frontend, and mobile application. Within this project, I am mainly responsible for the development of backend applications. The payment backend we are developing contains microservices and runs on a Kubernetes-based platform called City Platform. In this article, I would like to introduce you to Istio , a mechanism to set up microservice networks on Kubernetes. My aim is to explain its purposes and functions in an easy-to-understand manner for backend application engineers who are used to writing business logics or code. I hope this article will help you deepen your understanding of configurations using Istio, that it could be useful when isolating the issue causes during troubleshooting, and facilitate smooth communication with infrastructure and network engineers. What is Istio? With how the architecture of microservices work, their processing span multiple services, resulting in the need of communication cost between these services. As application engineers, we often think that it doesn't matter as long as it connects, but infrastructure engineers would want to effectively control the network layer. That is why Istio was created with the aim to centralize declarative management of various settings such as network routing and security, similar to Kubernetes Manifests, and to provide integrated operational monitoring of network status. Because the network is structured like a mesh, these functions are collectively referred to as the service mesh. Istio Architecture: Data Plane and Control Plane First, it's essential to understand the architecture of Istio. Like Kubernetes, Istio is divided into a control plane and a data plane. Kubernetes is a control plane that receives API requests from Kubectl, etc., and controls resources such as pods, etc., and a data plane is the pod where the application actually runs. Istio’s data plane employs a network proxy called Envoy . If necessary, the control plane injects Envoy as a sidecar container next to the container where our code runs. Control Plane and Data Plane Why Do We Need Istio? Envoy is a network proxy application that can run independently. The configuration items are so varied that configuring a single Envoy instance as intended is not easy. (At least for non-infrastructure engineers! ) In a complex microservices architecture, the network is like a mesh connecting inside and outside the cluster, requiring the configuration of numerous Envoy Proxies. It is not difficult to imagine how difficult it would be to set up individually and make everything work the way you want it to. Resources Configurable in Istio The following features will be available by introducing Istio: Traffic management (service discovery, load balancing) Observability (logging, distributed tracing) Security such as authentication and authorization On the other hand, for backend application engineers, there have been many situations in our experience where each of them is a black box, not knowing what is actually configurable or which configuration file to look at when encountering unintended behavior. Let's take a look at some specifics of what Istio's configurable resources mean. Gateway There are two resources related to Kubernetes networking: Ingress and Egress. Istio intercepts communications with an Envoy proxy called gateway. It is literally a gateway to the Istio network. You can set it up in the following file: Although this file itself rarely contains detailed settings that application engineers should know, it is often referenced by other files in the form of gateways , so make sure that the Gateway is properly configured first. apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: test-gateway spec: selector: istio: ingressgateway # LoadBalancer service available by default when Istio is installed servers: - port: number: 80 # listening port name: http protocol: HTTP # allowed protocols hosts: - "*" # host name Virtual Service Kubernetes has a mechanism called Service that allow deployment and StatefulSet to be accessed from the intracluster network. On the other hand, Istio's Virtual Service defines the route to the Service. While this is powerful as it allows for the definition of a very large number of configuration values, caution must be taken to avoid duplication with other settings. If a request for the service is not received, there may be a mistake in the Virtual Service configuration The istioctl analyze command may tell you about configuration errors, so let's take a look. apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: test-virtualservice namespace: test spec: hosts: - "*" # specified host name. This means that the following rules apply when this host name is specified. If *, the rule applies to any host name gateways: - test-gateway # specify the gateway above Multiple specification allowed - mesh # define 'mesh' here to allow intracluster communication without Gateway http: - match: # rules can be written for filtering requests - uri: prefix: /service-a # URI pattern. Regex, etc., can be selected. route: - destination: host: service-a # destination service port: number: 80 - match: # multiple routing rules and connections can be defined - uri: prefix: /service-b route: - destination: host: service-b port: number: 80  exportTo: - . # where is this rule applied? Kubernetes namespaces.If (dot), only in the namespace where this rule is set Authorization Policy Communication between specific services can be controlled. Specifically, protocols, routing to specific paths, specification of HTTP methods, etc. can be modified in detail, so there may be many opportunities for application engineers to configure them. On the other hand, misconfigurations of rules and numerous unexpected pitfalls are common, so be sure to run tests after configuring. apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: access-allow-policy namespace: test spec: selector: matchLabels: app: some-application # label on the pod action: ALLOW # permission rule rules: - from: # define the source of the request - source: principals: - cluster.local/ns/test/sa/authorized-service-account # Kubernetes service account to: # request receiver definition - operation: methods: ["POST"] # HTTP methods allowed paths: - "/some-important-request" # Permitted endpoints --- apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: deny-policy namespace: test spec: selector: matchLabels: app: some-application action: DENY # example of denying a request rules: - to: - operation: paths: ["/forbidden-path"] Other Settings Destination Rule Service Entry Peer Authentication Envoy Filter and other configuration files, but I will omit the discussion here. Basically, just like the Kubernetes resources, each schema is defined with its own configuration items. If you have a resource that your team uses, it is a good idea to check the documentation once to see what items can be configured. Specific Examples of Common Debugging and Troubleshooting First of all, make sure there are no glitches in the configuration. If you run the istioctl analyze command, most misconfigurations will be reported as errors. If RBAC is enabled, such as in a production environment, and there are constraints on Istio-related resources, have an authorized infrastructure engineer perform them. If there is no misconfiguration that cause errors, check to see how far the request has reached. Let's look at the application or sidecar logs to see if communication is broken at the gateway or up to the application pods. If it appears to be passing through the gateway, it is a good idea to check the sidecar container logs on the namespace of the pod that should be accessed, such as kubectl logs pod <pod-name> -c istio-proxy -n <namespace> . For intracluster communication, you can run curl on a container, but since recent Docker base images often do not contain applications that are not needed to run container applications, attach a container for debugging such as k debug <pod-name> -n <namespace> -it --image=curlimages/curl:latest -- /bin/sh and see if you can resolve names in the cluster. If communication is being blocked, check the Virtual Service file. If there is a problem with authentication, refer to the Authorization Policy file to locate the misconfiguration. Routing and authentication are the areas where items configured in multiple layers are easily conflicted. You can list what authentication rules are applied to a pod with the istioctl x authz check <pod-name>.<namespace> command. In addition, what seems like a network error at first glance often turns out to be an implementation problem. At the same time, the implementation side should also review the network and authentication/authorization settings. The following is what I do when I run into network-related errors. Isolate the causes by running the istioctl analyze command or checking the logs to see if the Istio configurations are incorrect. Check the network communication from inside and outside of the cluster using curl and kubectl debug commands. Check the application configuration, such as whether the deployed application listens for requests at the port specified by the infrastructure layer. Check the request to see if the client application implements the required authentication and authorization mechanisms. These can also be checked for misconfiguration and communication status via GUI if the observability stack settings such as Kiali are enabled. Conclusion By learning about the specific configurable items and their meanings, I hope you gained insight into some of the functions that were black-boxed. Also, some of you may have realised that the configuration items are surprisingly simple. On the other hand, I believe the difficulty of Istio is not in the network configuration itself, but rather at the production operation phase, such as ensuring continuous stable operations (applying version patches and verifying the operations each time). As a backend application engineer, I would like to further understand the behavior of Istio and test the application's performance under actual operational conditions.
アバター
Introduction Hello. I am Ito, and I do backend development and operation of the KINTO FACTORY service (hereinafter, FACTORY) at KINTO Technologies. As part of the Advent Calendar series about FACTORY, I will write about how we improved its master data management. About the Master Data Management of KINTO FACTORY Various types of information are stored as master data, including vehicle models, products managed by KINTO FACTORY, and details of dealerships capable of handling vehicle modifications offered by KINTO FACTORY. *Product prices are as of December 11, 2023. Albeit only in Japanese at the release of this article, you can check the KINTO FACTORY website for the latest prices. The base information is provided by Toyota and its dealers in Japan, and the planning department enters it into Excel. After that, the Excel file is shared with the development team, converted to a CSV file, and registered in FACTORY. It's a pretty hard operation When it first started, there was a lot of frustration... Saving nearly ten Excel files as CSV files, converting newline characters, and deleting BOM was all done manually and took time and effort Excel functions were used to check the entered data, which made files heavy to work with... It was hard to make an Excel function for checking, so they needed to be checked by humans Item lists were long, some data was duplicated, and there were also input mistakes It required repeated checks and revisions in a checking environment, and it took a lot of workload Improvement was needed We made the following improvements to get rid those annoyances. Review of the Excel Input Format First, we reviewed the Excel format. Removed unnecessary items that were created for potential future uses Removed duplicates or items determined by other input values Added assisted input with Excel functions We reduced the burden of inputs by removing unnecessary items and reduced input errors by about 75% by using Excel functions and input rules. Automating the Excel-to-CSV conversion Next, we developed a tool to convert Excel files into CSV files in Golang. We Automated the Excel reading, checking, and converting to CSV The number of Excel functions was optimized by using a tool to do checks that were done by Excel functions The tool developed in the Go language supports minor revisions even when items are added to an Excel file By automating Excel-to-CSV conversions, we reduced the amount of effort needed and manual operation mistakes, and made it possible to complete tasks that used to take almost a day in just minutes. By making the tool do all of the work that we did mabually in Excel, we were finally free from having to dedicate our time into just being Excel experts! (Personally, this was my favorite part) Summary In this article, I shared about how we improved the master data management of FACTORY. We reduced out time spent reviewing Excel formats, automating conversions to CSV files, and reducing input mistakes. However, we still are facing issues. In particular, communication between planning and development takes up time no matter what we do, so we are thinking of changing the input-to-verification environment in order to streamline the checking process. We will continue to improve our master data management and provide an even better service. Conclusion KINTO FACTORY is looking for new partners. Please check the job listings below if you're interested! @ card @ card
アバター
はじめに こんにちは、KINTOテクノロジーズCSIRTの森野です。 2023年7月12日(水)~ 14日(金)の3日間、日本シーサート協議会が主催するTRANSITS Workshop 2023 Summerに参加してきました。 TRANSITS とは、CSIRTの設立や運用に関するヨーロッパ発のトレーニングコンテンツです。 今回のワークショップでは、組織、オペレーション、技術、法律の4つのモジュールを学びました。 CSIRTはComputer Security Incident Response Teamの略で、コンピュータセキュリティの事故対応を行うチームを指します。 コンピュータセキュリティの事故とは機密情報の流出、コンピュータシステムへの不正侵入、マルウエア感染などを指します。 組織モジュール 組織モジュールでは、CSIRTの役割や提供するサービス、チームの構成などについて学びました。 また、チームごとにCSIRTメンバや攻撃者などの人格を演じるインシデントシナリオ演習もありました。 この演習では、インシデント対応の流れやコミュニケーションの重要性を体感しました。 オペレーションモジュール オペレーションモジュールでは、インシデントレスポンスやインシデントハンドリングについて学びました。 インシデントレスポンスはインシデントの解析や封じ込めなどの対処を指し、 インシデントハンドリングはインシデント全体の対応を指します。 また、チームごとにインシデントハンドリングのプロセスについて検討する演習がありました。 この演習では、あらかじめインシデントを想定した対応手順を整えておくことの重要性を学びました。 技術モジュール 技術モジュールでは攻撃者の攻撃手法などについて学びました。 講義の中で、とあるセキュリティベンダで様々な組織で発生したインシデントの解析を携わっている方からお話がありました。 携わったほぼすべてのインシデントは、適切な監視が行われていれば攻撃を検知できたとのことでした。 また、セキュリティの基本として挙げられた下記の言葉も印象に残りました。 空けたら閉める 使ったら片づける 動かしたら管理する 法律モジュール 法律モジュールでは、サイバーセキュリティ関連の法律や規制について学びました。 特に、ログの取得や保存に関する法的な要件や注意点について詳しく説明されました。 また、警察との連携方法やeディスカバリーという制度についても紹介されました。 まとめ TRANSITS Workshop 2023 Summerは非常に有意義な経験でした。 講義でCSIRT関連の知識やスキルを深められるのはもちろんのこと、演習などを通して他の参加者と交流できた点が特に良かったです。 CSIRTを設立したり運用したりする方にはぜひおすすめしたいワークショップです。
アバター
Introduction Hello. I am Yamada, and I develop and operate in-house tools in the Platform Engineering Team of KINTO Technologies' (KTC) Platform Group. In this article, I will talk about the CMDB developed by the Platform Engineering team, its functions, the technology used, and how we made it in-house. What is a CMDB? A CMDB (Configuration Management Database) centrally manages the assets and configurations that are critical to delivering IT services. The primary role of a CMDB is to manage the lifecycles and information of assets (e.g., infrastructure required to deliver IT services, product information, product managers and other human resources). Why We Made the CMDB In-House Before we implemented a CMDB, as the number of products we had was increasing, everyone was working in silos with their asset information. Whenever there was an incident, it was difficult to determine who was in charge of a product or the extent of the impact. As a solution to these issues, we considered implementing a CMDB to centrally manage asset information in the company. There are several off-the-shelf CMDB software, but after considering installation and operation costs and customizability, we decided to make one in-house. The Features of Our CMDB Our company's CMDB includes fundamental functions like product and team management, and it's designed to seamlessly integrate with tools developed by other teams within the Platform Group. Some functionalities are still in development, but we are adding more every day so that anyone can view it and find the information they want. Product Management It manages basic information such as product names, affiliated departments, and management team. If a product malfunctions, you can easily find and contact the person responsible for it. For products that consist of multiple microservices, it can also manage which teams develop which functions, so you can accurately determine the right person in the event of a malfunction. Below is the product details screen, where you can check the team and domain information associated with a product. We plan to add more information such as which environment the product is in. There is also an item called "SID", which I will discuss later. Domain Management This manages domains associated with products. Team Management This manages team information associated with products. Manager Management This manages permissions for each user and group. DB Management This provides a mechanism to easily view all RDS information managed by KTC in the CMDB by linking with tools developed by the DBRE Team, which is also part of the Platform Group. In addition to basic RDS information, you check ER diagrams and DB designs according to the policy set by the DBRE team. Security Management Security management lets you manage the repository and its vulnerability information on the ECR. If a vulnerability is found in the weekly ECR repository scan, the MSP Team, which provides operational support, will work with the team that manages the repository. In that situation, it outputs an Excel file of the scan results and a CVS file that creates a Jira ticket for a response request to the person in charge. Scheduling Management This provides a scheduling management function that stops EC2, ECS, and RDS in the development environment for a certain period of time for the purpose of reducing AWS costs. By stopping services during late weekday nights and weekends when they are not required, it contributes to cost reduction. External Linking With external linking, you can link the AutoProvisioning system to the sandbox environment on AWS and manage the history. For more information, please read the article below! https://blog.kinto-technologies.com/posts/2023-05-30-AutoProvisioning/ SIDs To connect the data in the functions I have talked about up to now, KTC has the concept of SID . SID stands for Service ID and is a unique identifier for each product managed by KTC. For example, the SID of CMDB is set to kakazan . The name "Kakazan" comes from the mountain where the Monkey King was born in the novel Journey to the West. In fact, the name KINTO also comes from the Monkey King's story; it’s the name of his flying nimbus “Kinto'un”. So in the same way, it’s fun to see how a lot of the SIDs for KTC products are referencing Journey to the West. SIDs are used as product names and makes clear who is the owner of each product. This concept is spreading throughout KTC. In particular, AWS resource management uses ECS, RDS, S3, API Gateway, and many other AWS services for each product. The Tag setting is effective when determining which resources belong to which product. The resources are then linked to the products by attaching a SID tag to the resource. The CMDB uses this SID tag setting to link various information together. Technology Used I will briefly go over some technical elements used to develop the CMDB. The frontend is developed using React, while the backend is built with Spring Boot. Both utilize a shared framework for authentication, authorization, and utility classes. Additionally, there are three services—for the main service, DB management, and external linking—that are all dependent on the common framework. Batch processing was also developed with Spring Batch. I would like to write more about the system configuration another time. Future Plans We have more technologies to explore, and we plan to continually update features. Some are still in development, while others are on our agenda for future work. For example, we can try using EKS since KTC uses ECS as its container execution environment, or we can try using microfrontends (which are not necessary in terms of development scale), or we can implement PWAs (Progressive Web Apps) so the CMDB dashboard can be viewed from company smartphones, and so on. I think there are opportunities to explore only because the system was made in-house, so we will make good use of this system by trying out technologies that could be deployed in-house in the future. We also want to add functions to the common framework used to develop the CMDB, create a group of React components to suit the KINTO brand image, and implement them as a library to be used throughout the company. Conclusion In this article, I talked about the CMDB we developed at KTC, its background and functions, and our vision for the future. KTC s actively involved in the development of various systems alongside managing the services handled by KINTO I hope that this article has raised interest in KTC activities.
アバター
はじめに クリエイティブ室の杉本です。 今回は、オリジナルマスコットキャラクターができるまでの第二弾をお届けします。 第一弾は、キャラクター欲しいよねーという声を受けて形になるまででした。 1.全社員を巻き込みながら進めてきた道筋と、2.人気を集めたものを単純に開発するのではなく、ある程度、マスコットキャラクタープロジェクト(以下PJ)のメンバーが、KINTOのビジョンやブランドパーソナリティから選択の軸を決め、今後の展開とブランディングを含めて方向性を決めていったこと 3.社員の有志から集まったキャラクターアイデアから全社員にアンケートをとり、KINTOの社名の由来でもある“雲”をモチーフにしたアイデアに人気が集まったことをお話させていただきました。 具体的には、下記のキャラクターに人気が集まりました。左は、形を自由自在に変えられるという点に人気が集まり、右は雲をクルマ化?!させたところがチャームポイント。ちなみに、両方ともクリエイティブ室から選抜されたことは、マネージャーとして、ほっとひと安心。 こちらの2案に人気が集まりました。 雲モチーフに命を吹き込んでいく 1. インハウスでも、つくるべきではない制作物もある! 上記の2案を元に、次はイラスト化です。 時々、デザイナーは写真も撮影できて、動画制作もでき、イラストまで描けちゃうと思っていらっしゃる方がいます。 「外注費がないので、内製でできないですかね。」「AIでちゃちゃっと作れないですかね?」など、など色々と聞こえてきますが。。 社内デザイナーの中でも、もちろん、イラストが上手なメンバーはいます。ただ、餅は餅屋メソッド(「お餅はお餅屋さんでついたものがいちばん美味しいのだから、その分野のことはその道の専門家に任せたほうがうまくいく」という例え)が、ここは大事。キャラクターの命ですから! 上手に描くイラストと、命を吹き込むイラストは違います。やはり、イラストレーターやキャラクター制作に特化したクリエイターにお願いするのが、同じクリエイター同士へのリスペクトだと考えます。内製でできない、するべきではない制作物の例であるといえるでしょう。 2. ならどうする?イラストを外注 制作予算がある中でしたが、幸い、PJに入っているビジネス側の担当者は、「デザイナーだからイラストも描けるだろう」といった考えではなく、クリエイティブを尊重してくれるメンバーが揃っていたので、制作費をつくるべく尽力してくれました。外注先は、企業や商品、または地域などのブランディング及び企画デザインなどを得意とするクリエイティブカンパニー「 Steve* inc. 」さんに依頼することに。 PJが大切にしたいキャラクターへの想いに寄り添いながら、キャラクターにどんどん命を吹き込んでくれる物語をいっしょにつくっていってくれました。 私たちクリエイティブ室が「 Steve* inc. 」さんに注文させていただいたのは、例えばグッズをつくった際にも、大人でも持ちたくなるようなキャラクター。かわいい、愛くるしい、それだけではない大人が納得できるトーンにこだわり依頼しました。 そのこだわりをもとに、雲のモチーフキャラクターの案を3案つくってもらいました。A案「謎の生物K」B案「はぐれぐも」C案「くもりす」。彼らは全て、どこか俯瞰してるようでいて、少しかまってちゃんを感じる表情は、さすが「 Steve* inc. 」さん!PJメンバー全員、プレゼンをわくわくしながら聞かせてもらいました。次に、全社員にそれぞれの案の良いと思う点と懸念点を挙げてもらうアンケートを実施。アンケートを行うことで、多角的な視点で審査することで、かわいい!好き!それだけではないキャラクターの課題感が見えてきました。 そして、アンケートの結果、A案「謎の生き物K」に決定! 「謎の生き物K」って笑 これが名前?! このインパクトのあるネーミングを活かし、このまま名前や存在に「謎」感を残したプロモーションで進めていくのが面白いのでは?!ということで、マーケティングやSNS担当者とのミーティングも盛り上がりました。 さあ、フォルムが決まったので、次はブラッシュアップしてもらいます。さらに、「謎の生き物K」は、読みやすさと身近さを感じてもらえるよう、生き物をひらがなにということでこちらも地味に改名し「謎のいきものK」となりました。 「謎のいきものK」の形がどんどんできあがっていく! なんとなくとぼけた表情がグッドな「謎のいきものK」。ですが、長く愛されるようフォルムや顔立ちをブラッシュアップしていきました。 具体例: アルファベットの「K」感をもう少し出したい(ぱっと見て「K」を想起できないのではないかという意見が出ました。) もう若干、雲感を出したい(現状、ハンドソープの泡、マシュマロみたいで) 雲がモチーフなので、目とカラダのバランスを若干調整したい。(もう少し、雲が大きく見える初期のスティーブさんのイラストくらいのバランス感。) 3DのKの目の「白眼」と「雲」の違いをもう少し出したい(現状黒い部分のみが見えるので、ふちの線なのか、シャドウなのかを調整しもう少し2DのKの目のような可愛さを残したい。かつもうちょいマットな質感の方が良いかもと思いました) 3DのKのカラーをもう少しブランドカラーを入れたい(黒目部分と体の影など) 2Dイラストだけでなく、クルマの画像といっしょになったときにも、違和感がないように3Dイラストも制作することにしました。 さらに、形のモコモコはどうするか?イラストで描くぶんにはいいが、着ぐるみになったときにどう表すか、目の色はどうするか、口はないままで、かつセールストークはもちろん、何も話さないキャラクターにするか、性格や性質などを詰めていきました。 そして、現在のフォルムと表情に! ネーミングは2023年7月からお名前募集キャンペーンを行い、全部で932投稿をいただきました。 そのなかから、PJでキャラクターを決める際の軸( ブログ1を参照 )をもとに、ネーミング候補を選択。 雲のキントン くもびぃ 謎のいきものK K お客様(サブスクKINTOの契約者)の人気投票では、「雲のキントン」と「くもびぃ」がともに人気があったものの、年代別にみるとターゲット世代の10代〜30代に「くもびぃ」がダントツ人気になったことと、社内の投票結果が1位になったことで、 「くもびぃ」 に決定しました。 名前の由来として、雲=くもとモビリティが合体しているのもKINTOらしく、PJメンバーも納得。 こうして生まれた「くもびぃ」。これから会社のプロモーションに露出していく機会が増えると思います。どうぞよろしくお願いします。 ユニークな特徴の「くもびぃ」をチェックしてみてください! ▼ くもびぃストーリーはこちら ▼ @ card
アバター
Introduction Hello, my name is Numata, and I am part of the Project Promotion Group. I work hard every day as a backend engineer for KINTO FACTORY. In this article, I will talk about KINTO FACTORY services and the DX initiatives we did this summer. What is KINTO FACTORY? Many people in Japan think of KINTO as a subscription service, but KINTO FACTORY (hereinafter, FACTORY) offers various upgrade services so that you can ride your favorite vehicle over a longer period of time. To be more specific, you can customize your vehicle by updating its software, changing its interior and exterior such as seat replacement and wheel cap replacement; or improving the opening and closing speed of your doors. The range of available Toyota Group vehicle models (Toyota, Lexus, and GR), products, and areas where customizations are possible, is gradually expanding too. I always thought that once you buy a vehicle you do not really change any features until you switch to another vehicle, so I feel that the efforts of FACTORY and its approach to modularity are challenging and interesting. Modification Process FACTORY provides services not just through KINTO, but also in cooperation with Toyota and its dealer network throughout Japan. *The numbers in the image are for illustrative purposes and are not fixed. First, when a customer applies for a product on the FACTORY site, FACTORY orders the necessary parts from Toyota and shares the application details with the dealer of the customer's choice. After confirming the information in the application, the dealer sets up the arrival date with the customer. Once the delivery date is confirmed, the customer takes their vehicle to the dealer on the day of receipt, and the dealer carries out the modification with the delivered parts. As soon as the modification is completed, the dealer contacts the customer and delivers the vehicle to them. Specifics may vary depending on product and the desired modification, but that is the general process. DX of Modification Certificates Some of you may have never heard of modification certificates before (I learned about them after I joined the company). It is given in Japan to customers after a vehicle modification is completed, and written on it appears the details of what was modified, its date and time, the dealer where it was performed, along with other information. Before, the modification certificate was manually created by the dealer that delivered the vehicle to the customer, but since August, it has been possible to issue it on FACTORY. Process of Issuing a Modification Certificate Once the status of a purchased item changes to modification complete , you can issue a modification certificate from your purchase history on My Page (FACTORY refers to My Page as My Garage😃). When you click the modification certificate button, the certificate is displayed in a separate tab and can be downloaded as shown in the figure below. Currently, modification certificates can be issued for any products except for GR-related ones and event products. It also supports the invoice system that we implemented in October 2023, and payment statements can be issued from FACTORY. Architecture and Technology Stack FACTORY runs on AWS, and we use a microservice architecture like the one in the rough diagram above. The microservice that issues the modification certificate was developed using Go as programming language and uses the gopdf library to publish PDFs. The issued modification certificate is stored in S3. PDF Templates Since our company uses Office 365, we use Excel to manage PDF templates. We modify the Excel template and export it as a PDF whenever there is a change. Toyota Modification Certificate Lexus Modification Certificate We struggled with the fact that, not only the design of the modification certificate varies depending on the model, but the number of characters in the product name also varies, so it was difficult to decide on one layout that would not affect either of them. For convenience, we made it A5 just like the proofs of modification that were made manually. Side note: This was my first time handling PDFs with a program. I honestly did not think it was so straightforward. Beyond the Modification Certificate DX We can now provide a better experience for both customers and dealers by making it possible to easily generate modification certificates on FACTORY instead of having them made manually by dealers. Aside from modification certificates, there is still a lot of work that is done manually, and I think there is a lot of potential for DX in the automotive industry. FACTORY will keep working on various initiatives, to offer even better experiences in the future. Conclusion FACTORY is looking for new partners to liven up the company together. We do casual interviews, so feel free to apply! @ card
アバター
Introduction Hello, I am Aritome from the Development Support Division at KINTO Technologies Corporation. I am currently working mainly in the areas of organizational development, and education and training in order to address what is necessary for the company in a quick and agile manner. KTC holds a monthly Development and Organization Headquarters Meeting in which all employees (employees, contract employees, and temporary employees) participate. Today, I will talk about the twists and turns of the meeting. Some of you may be thinking, 'Hey, this is a Tech Blog, but this content isn't technical at all!' However, I want to assure you that I'm writing this article from our Osaka Tech Lab. So, even if the content might not seem technical, the place where I'm writing it is definitely tech-related! Also, I talk with various companies because of my work, and I feel that every company is worried about people and team building, including topics like building an organizational culture and retaining employees. I believe that making products means making people! I hope this will be a reference for those who are also struggling to build their organization. <What is a Development and Organization Headquarters Meeting?> KINTO Technologies Corporation's Development and Organization Headquarters Meetings started in July 2021, before I joined the company, with three departments announcing their respective initiatives in something similar to an in-house LT meeting. According to the minutes of the meeting at the time, there were about 160 participants... (We have grown considerably as a company and now have more than 330 employees.) The meeting has been held once a month since then. Each month, Kageyama, our Executive Vice President, gives a presentation, and two or three divisions talk about their activities in a LT (Lightning Talk) format. After that, one of the divisions gets a Kageyama Award. Kageyama gives a complimentary prize. <Why is the Development and Organization Headquarters Meeting Held in the First Place?> At first, we had a rigid culture in which the departments had a vertical structure and did not share information much, As we were in the business launch phase, we were very busy with practical work that we had to prioritize, and we put building a corporate culture on the back burner As the number of employees increased, so did the distance from Vice President Kageyama and the rest of employees. Due to the launch of the business during the COVID-19 pandemic, there were few chances to meet offline, and the company wanted everyone to communicate with each other at least once a month. Originally, the manager (Currently Mr. K, General Manager of the Development Support Division) was in charge of planning and managing, but when I joined the company, we started reviewing the meetings. We took over the operations of the Headquarters Meeting around April 2022, and have been improving it through trial and error for a year and a half. To prepare for the renovation, we identified the following three challenges and worked on them. (1) Improving communication We started entirely online using an LT meeting format, so at first, employees just listened to presentations one-sidedly instead of actively communicating with each other. I remember being surprised when a lot of employees attended halfheartedly, and I thought it felt like a management meeting. (2) Improving the Kageyama Award Also, I felt that it was a burden for employees in the workplace to make a 5-minute LT presentation even though they were busy. As the organization expanded, the number of managers other than Kageyama increased, so we thought, "We need to create a system that lets the board show the efforts of the members to more people." (3) Understanding other departments' work and sharing activities We received comments in the past such as “I don’t know what other departments are doing” in our questionnaires, so we wanted to use the Headquarters Meeting and other events to better understand what work and activities other departments were doing. (1) Improving communication We implemented a tool called Comment Screen , that displays emojis and comments on a screen in real time, and it encouraged more two-way communication. There were some who liked it because it was in real time, while some thought that it felt cheap, or that the presentations were hard to read. We kept experimenting, and now we communicate through Slack. All employees join the Headquarters Meeting Communication Channel when they join the company and use Slack to communicate in real time during the meeting every month. On each session, we added a friendly poll with questions such as, "What did you eat today for lunch?" By the way, there are a lot of restaurants with delicious food near our office, and a lot of members report going to lunch, but a there is also a handful who sadly say "Red Bull" or "I didn't eat..." lol But, just to be clear, our company is a place where everyone can take breaks easily! (Honestly, our company culture makes it easy to take breaks, and I think that is one of our company's good points) (2) Improving the Kageyama Award The purpose of the program was redefined as "managers should not miss the daily efforts of their members," and the style was changed so that managers recommend candidates, give the reason for their recommendation, and write an award speech. Before, Vice President Kageyama decided the winners, but they are now decided in a meeting with the managers in advance. With this system, team members no longer have to make tedious materials for the sake of being nominated and getting awards, and the managers were more motivated to pay attention to the members' daily efforts. I hope that the corporate culture changes so that people's daily efforts are assessed naturally. (3) Understanding other departments' work and sharing activities We made changes so that every month, the managers of each group take turns sharing information on projects that are being focused on and their activities. Kageyama also gives additional comments when necessary. Thanks to managers sharing information on activities and Kageyama's additional notes, the company's activities felt more concrete to employees, and they were more motivated to be informed. We also shake things up so that it’s not always the same announcements, and during the New Year period for example we introduce things such as the kanji of the year or the goals for next year. In addition, we post information on events from Twitter, announced activities related to the Tech Blog, and try to make the Headquarters Meeting an event where people can understand the company's activities. In addition to the above, the results of the previous month's questionnaire are announced at the start of each meeting, and we try to make communication during the meeting as open as possible. We are still making improvements, but the attendance rate of the Headquarters Meeting is gradually increasing. We have almost every employee (close to 300) attend every month, even as more employees join the company. The number of people participating online with their webcam on and making comments on Slack is also increasing gradually! We also get more happy comments through our questionnaires with each meeting. [Some Questionnaire Responses from our Employees (Examples)] It is really interesting to learn what each department is doing. It is also helpful to hear Mr. Kageyama's thoughts on each department! I like how the meeting is packed with information. Generally speaking, this kind of meeting tends to be light on content, or you can just read the materials afterward to get the information, but I think KTC's company-wide meetings have been different recently (in a good way). I can find out the status of departments that I normally don't have any connection with. I find that helpful. Conclusion What do you think? We will start taking on challenges such as announcing the 2024 kanji of the year and holding in-person events (holding the Headquarters Meeting offline). I think one of the good things about our company is that we are open to new initiatives and challenges. We can implement initiatives that are difficult for conventional large organizations and start them in a relatively quick and agile manner. Even if they fail, for better or for worse, they serve as precedents (and we don't get too mad?), and we can use the experience for our next actions. And of course, if you succeed, people will praise you (lol) Also, we have many employees who say, "I want to do it!" and lend us their strength. Please let us know about your company's initiatives when we meet at events! We will challenge ourselves so we won't lose!
アバター
はじめに KINTOテクノロジーズでmy routeのAndroid側を開発しているHand-Tomiと申します。 Android 14が2023年4月12日にリリースされてそろそろ1年になります。 しかし、新しく追加された「地域別の設定」についてまだ十分理解されていない方も多いと感じ、この記事を書くことにしました。 多言語対応のアプリケーション開発において「地域別の設定」を理解せずに進めると予期せぬバグが発生するリスクがあります。この記事を読んで、そうしたバグを予防できれば幸いです。 この記事で解説するもの Locale.getDefault() == Locale.JAPAN :::details コード解説 Locale : 言語、国、地域に基づく特定の文化的、地理的設定を表すクラス Locale.getDefault() : 現在のアプリケーションのデフォルトの Locale を返す Locale.JAPAN : 日本の言語( ja )と国( JP )の設定を表すLocaleのインスタンス ::: 上記のコードでは端末に「日本語(日本)」が設定されている場合、 true が出力されますか?それとも false が出力されますか? 正解は、Android 13以下では true であり、 Android 14以上の場合、これだけの情報では不明 です。 この記事では、 Android 14以上の場合、なぜ不明なのか を解説します! Androidでの Locale とは Locale は、言語、国、地域に基づいた文化的、地理的設定を表すクラスです。この情報を利用して、Androidアプリケーションは多様なユーザーに適応したアプリケーションを構成することができます。 Locale は主に言語や国を扱いますが、 LocalePreferences を使用することで、より多くのデータを抽出することが可能です。 val locale = Locale.getDefault() println("calendarType = ${LocalePreferences.getCalendarType(locale)}") println("firstDayOfWeek = ${LocalePreferences.getFirstDayOfWeek(locale)}") println("hourCycle = ${LocalePreferences.getHourCycle(locale)}") println("temperatureUnit = ${LocalePreferences.getTemperatureUnit(locale)}") 「日本語(日本)」の設定を持つ端末で上記のコードを実行すると、以下のようになります。 calendarType = gregorian : 暦法 = グレゴリオ暦 firstDayOfWeek = sun : 週最初の曜日 = 日曜日 hourCycle = h23 : 時間周期 = 0~23 temperatureUnit = celsius : 温度 = 摂氏 「地域別の設定」とは Android 14から導入される「地域別の設定」は、Locale(言語、国)で設定された「温度」や「週の最初の曜日」をカスタマイズできる機能です。 温度 デフォルトを使用 摂氏(℃) 華氏(°F) 週最初の曜日 デフォルトを使用 月曜日 ~ 日曜日 温度設定画面 週最初の曜日画面 :::details 設定画面に入る方法 「設定アプリ」内の「システム」→「言語」セクションから「地域別の設定」画面にアクセスできます。 ![setting](/assets/blog/authors/semyeong/2024-02-28-regional-preferences/setting.png =300x) ::: 「地域別の設定」がなぜ必要か? 「アメリカ🇺🇸」と「オランダ🇳🇱」では、共に英語を使用できますが、使用される「温度」の単位や「週の最初の曜日」が異なります。 アメリカ🇺🇸 オランダ🇳🇱 温度 華氏 摂氏 週最初の曜日 日曜日 月曜日 「アメリカ🇺🇸」に住んでいる「オランダ人🇳🇱」が摂氏に慣れており、 温度のみ を摂氏に変更したい場合は、「地域別の設定」を使用して、 温度のみ を変更することが可能です。 「地域別の設定」を設定すると、どのような変化があるのか Locale.getDefault().toString() 設定値を確認するために、上記のコードを使用しながら各設定を変更してみましょう。 言語 温度 週最初の曜日 結果 日本語(日本) デフォルト デフォルト ja_JP 日本語(日本) 華氏 デフォルト ja_JP_#u-mu-fahrenhe 日本語(日本) デフォルト 月曜日 ja_JP_#u-fw-sun 日本語(日本) 華氏 月曜日 ja_JP_#u-fw-sun-mu-fahrenhe 「温度」や「週の最初の曜日」を設定した結果、 #u や mu-fahrenhe 、 fw-sun など理解しにくいテキストが出力されましたが、これらは Locale のメンバー変数であり、 localeExtensions の値です。このように localeExtensions に値が設定された場合、 Locale の hashCode や equals() の結果も変わり、 Locale.JAPAN と比較しても true にはなりません。 では、どのようにして言語を確認するか? Locale.getDefault() == Locale.JAPAN // X Locale.getDefault().language == Locale.JAPANESE.language // O 言語を確認したい場合、 Locale に含まれる language プロパティで比較してください。 この方法を用いれば、「地域別の設定」を変更しても影響を受けず、求めている結果を得られると思います。 最後に Android 14からこっそり追加された「地域別の設定」機能によって、突然以前動いていたコードが動かなくなっても、この変更を検知することはかなり難しいですね。 ほとんどの方は問題ないと思いますが、もしLocaleインスタンスで言語を比較している場合は、確認してみてください。 一人でも多くの方がこのようなバグを早く発見し、解決できれば、この記事は大成功と言えるでしょう! また、myrouteのメンバーが執筆した他の記事もぜひご覧ください! Structured Concurrency with Kotlin coroutines myroute Android AppでのJetpack Compose Compose超初心者のPreview感動体験 ここまで読んでいただき、ありがとうございました。 ※Android ロボットは、Google が作成および提供している作品から複製または変更したものであり、 クリエイティブ・コモンズ 表示 3.0 ライセンスに記載された条件に従って使用しています。
アバター
Hey there! 👋 We're Az, Moji, and Ai—part of the UI/UX team in the Global Product Management Group at KINTO. Today, let's dive into the fascinating world of diversity and inclusivity in UI/UX design! What Does It Mean to Design for ‘Diversity and Inclusivity’? According to Nielson Norman Group , inclusive design describes methodologies to create products that understand and enable people of all backgrounds and abilities. Okay, let’s dive into some examples to get a better understanding of inclusive design. Clear examples can be seen in architecture – ramps for wheelchairs, tactile paving, even bicycle lanes, it’s all about making spaces welcoming for everyone. Examples of inclusive design in everyday life Examples in UI/UX Design Now that you (hopefully) have a clearer understanding of inclusive design, let's delve into specific examples within UI/UX design: (from left to right) Alt text, keyboard navigation, Apple's accessibility For those familiar with HTML/CSS, ever wondered the purpose of for images? It's not just a fallback for when images don't load; it's also the key to providing image descriptions for those visually impaired navigating websites with screen readers. Ensuring that your website is navigable using only a keyboard is crucial. Keyboard accessibility not only enhances the experience for keyboard-only users but also benefits other groups, including screen reader users, individuals with low vision, those with motor impairments or cognitive disabilities, and users who prefer keyboard shortcuts or alternative keyboards. Apple has excelled in incorporating accessibility into its design, with a user interface and experience that cater to individuals with diverse impairments. Notable features include the ability to easily adjust font sizes for improved legibility, the option to tap words for spoken feedback, voice control tailored for those with physical impairments, and a range of other inclusive design elements. You can explore all these features here . These examples represent just a few instances of inclusive design within UI/UX. The Web Content Accessibility Guidelines (WCAG) outline the principles and techniques for enhancing the accessibility of web content, ensuring it is more accommodating to individuals with disabilities. Now that we've explored the fundamentals of inclusive design, let's take a deeper dive into its application in mobility platforms, a core focus of our company. Moji, over to you. Ai has set the stage with the ins and outs of inclusivity, and now it's my turn to zoom in on how we make that happen in the world of moving around. Hi, I'm Moji , and and I'm all about making sure our designs help everyone get where they're going, no matter who they are. I believe as designers, we have the capability, and responsibility, to ensure the products and solutions we develop cater to a wide spectrum of users - in terms of ethnicity, language, age, gender, physical ability, and cultural background. Looking into how the big players nail this isn't just interesting, it helps us do our job better, and it helps us figure out better ways to design more inclusive tech products. Take Google Maps as an example. This app is a daily go-to for many of us for getting around. How Google Maps Sets the Standard for Accessible App Design Not only does Google Maps offer real-time GPS and transit info, it's also designed to cater to a wide-reaching audience. For those with sight impairments , Google Maps has a voice-guided navigation system . It'll tell you when you're about to make a turn, if there's heavy traffic ahead and any disruptions that might mess up your journey. This spoken assist feature makes life easier for anyone who needs audio cues. Google Maps' latest update brings some new features specifically aimed at making the app more accessible and inclusive. The Immersive View for Routes gives a detailed look at the route you’ll be travelling, whether that’s via car, foot or on a bike. Awesome for those with mobility challenges. And, because Google Maps is used all over the world, they’ve made sure it’s available in over 40 languages. This not only makes the app more accessible globally, but also boosts user satisfaction, since people prefer info in their native tongue. Challenges of Creating Globally Accessible App with RTL Language Support Transitioning to a more focused exploration of language and locale considerations in app design, I'll hand the reins over to our teammate Az. She's been at the forefront of tackling the ground-level challenges of designing a globally-accessible app, particularly when it comes to ensuring seamless compatibility for RTL (Right-to-Left) language speakers like those who speak Arabic. Over to you Az. Hi, now it’s my turn; I’m Az from the UI/UX team. While working on RTL (Right To Left) design for a project, I noticed something. And that is: To Promote Diversity, It's Crucial to Remain Mindful of Aspects One May Not Be Familiar With It is important to pick up on details of what one would ‘take for granted' rather than focusing on creating the unprecedented. I discovered many points that were previously unknown to me or learned about them for the first time in this project. The term RTL stands for “Right To Left”, referring to languages that are read from right to left. As the text direction is different from what we are used to in Japanese or even English, the way the eyes move also differs. The layout will also be adjusted to align from right to left. Nested components such as the position of icons and texts, action buttons’ direction, the badge position are also inverted. However, the icons for "the headset" and "the location" are not inverted, as they are physical items and a universal design concept. Not only the display but also the layout itself needs to be inverted. The order of the indicators changes according to the direction. There are some exceptions even in form-related elements. When a numerical sequence has a specific meaning, such as a phone number or a credit card number, it should not be inverted. A proper noun such as “KINTO” will not be inverted We have introduced you to examples in KTC, but you can find additional concrete examples in the Apple Human Interface Guideline and the Google Material Design . I think you noticed from this article that the members in our UIUX team come from diverse backgrounds. That’s why I can improve my knowledge, perspectives, and insights that one may not notice alone. Ai mentioned the necessity of “diversity” through comparison with real-world spaces based on her architectural knowledge. Moji, with her strong research skills and extensive knowledge, provided insights into what is happening in familiar services. Tim, who makes an appearance on another article, is also a reliable member capable of handling a wide range of tasks from project execution to frontend development. By building upon the "taken for granted" knowledge that each of us possess, we will continue to develop services that everyone can comfortably use in the future.
アバター
Flutter Webで単体テストしてますか? こんにちは。Woven Payment Solution開発グループの大杉です。 私たちのチームでは、 Woven by Toyota において Toyota Woven City で使われる決済システムの開発を行っており、普段はKotlin/Ktorでバックエンド開発とFlutterによるWeb/モバイルのフロントエンド開発をしています。 Flutter Webでは、Web固有のパッケージを使用しているとテスト実行でエラーになってしまうことがあります。 そのため、今回の記事ではFlutter Webのコードをテスタブルな状態に維持するために工夫していることを、特に単体テストにフォーカスしてまとめたいと思います。 なお、これまでのフロントエンド開発ストーリーについては過去の記事を参照していただけると幸いです。 KotlinエンジニアがFlutterに入門して1ヶ月でWebアプリケーションを作った話 バックエンドエンジニアたちが複数のFlutterアプリを並行開発していく中で見つけたベストプラクティス Flutter Webとは 初めに、Googleによって開発が進められているクロスプラットフォーム開発のフレームワークであるFlutterの内、 Webアプリ開発に特化したフレームワーク のことです。 Flutterの開発言語であるDartは、ソースコードを事前にJavaScriptに変換し、HTML、Canvas、CSSを使用して描画処理を行うことができるので、モバイルアプリで開発したコードをそのままWebアプリに移植することができます。 Flutter Webの実装方法 基本的な実装は、モバイルアプリ開発と同じ方法で実装できます。 一方で、DOM操作やブラウザAPIにアクセスしたい場合はどうすればいいでしょうか? これもDartの組み込みパッケージで dart:html などのWebプラットフォーム向けのパッケージが用意されています ^1 。例えば、ファイルダウンロード機能もJSによる一般的なWebアプリ開発と同じように実装することができます。 :::message 記事執筆時のSDKバージョンは、Flutter v3.16, Dart v3.2を対象としています。 ::: 下記のWidgetは、カウントアップした数値をテキストファイルとしてダウンロードするという何に使うかわからない機能を持ったサンプルアプリです。Floating Buttonをクリックするとテキストファイルのダウンロードが行われます。 import 'dart:html'; import 'package:flutter/material.dart'; class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'You have pushed the button this many times:', ), Text( '$_counter', style: Theme.of(context).textTheme.headlineMedium, ), IconButton( onPressed: _incrementCounter, icon: const Icon(Icons.add), ) ], ), ), floatingActionButton: FloatingActionButton( onPressed: () { AnchorElement(href: 'data:text/plain;charset=utf-8,$_counter') ..setAttribute('download', 'counter.txt') ..click(); }, tooltip: 'Download', child: const Icon(Icons.download), ), ); } } Flutter Webのコードを単体テストする 先ほどのサンプルコードのテストコードを以下のように用意しました(ほとんど flutter create して出力されたときのままです)。 import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:sample_web/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { await tester.pumpWidget(const MyApp()); expect(find.text('0'), findsOneWidget); expect(find.text('1'), findsNothing); await tester.tap(find.byIcon(Icons.add)); await tester.pump(); expect(find.text('0'), findsNothing); expect(find.text('1'), findsOneWidget); }); } 次のテストコマンドを実行するかVS CodeのTestingタブから上記のテストコードを実行してみましょう。 $ flutter test このままテストを実行すると、次のようなエラーが出るかと思います。 Error: Dart library 'dart:html' is not available on this platform. // 省略 lib/utils/src/html_util.dart:4:3: Error: Method not found: 'AnchorElement'. AnchorElement(href: 'data:text/plain;charset=utf-8,$data') どうやら dart:html のインポートに何か問題があるようです。 プラットフォームごとのDartコンパイラ 公式ドキュメント を確認すると、Dartコンパイラの実行には、 JITコンパイラを行うDart VMとマシンコードを生成するAOTコンパイラの Nativeプラットフォーム DartコードをJSにトランスパイルする Webプラットフォーム の2つがあることがわかります。また、それぞれのプラットフォームで利用できるパッケージが一部異なるようです。 プラットフォーム 利用できるパッケージ Native dart:ffi, dart:io, dart:isolate Web dart:html, dart:js, dart:js_interopなど つまり、前述のテストはVM上で実行されていたため、 dart:html を利用できなかったということがわかりました。 Webプラットフォームパッケージのインポートエラーを回避する方法として、テスト実行時にプラットフォームを指定する方法があります。 下記のオプションをつけてコマンド実行することで、テストをChrome上で(つまり、Webとして)実行することを指定できます ^2 。 $ flutter test --platform chrome :::message オプションなしテストがVM上であることは、 flutter test --help --verbose で確認できました。 --platform Selects the test backend. [chrome] (deprecated) Run tests using the Google Chrome web browser. This value is intended for testing the Flutter framework itself and may be removed at any time. [tester] (default) Run tests using the VM-based test environment. ::: Flutter WebのテストコードはChromeで実行すべきか? ブラウザAPIの利用はWebアプリを開発する上で避けられないことだと思いますが、Flutter WebのテストコードはChrome上で実行すべきなのでしょうか? 個人的な意見ですが、なるべくChromeを使わない方が良いというのが私の考えです。 理由としては、 テスト実行の際にバックグラウンドでChromeを起動する必要があるため、テストの起動時間が増大してしまう CI環境にChromeをインストールする必要があり、CI環境のコンテナサイズが大きくなる。または、コンテナのセットアップに時間がかかってしまう ことが想像でき、CI環境の金銭的コストがかなり増えてしまうことが考えられます(もちろん、ローカルでささっと確認する程度や富豪な方でしたら問題ないです)。 実際に、オプションでプラットフォームを指定しない標準ケース(Native)とChromeを指定したケース(Web)を比較したローカル環境の実行結果を載せました。 プラットフォーム プログラム実行時間(秒) トータルテスト実行時間(秒) Native 2.0 2.5 Web 2.5 9.0 上記表から、Webの方は実際にテストの起動に大幅に時間がかかるようになりました。さらに、テスト実行時間も25%ほど増大していることもわかるかと思います。 ![tester](/assets/blog/authors/osugi/20240301/annoying.png =400x) Webプラットフォーム依存のコードは分離しよう Webプラットフォームを指定しないで前述のエラーを回避するにはどうしたら良いでしょうか? 実は、Dartにはパッケージを条件でインポート・エクスポートする方法と、プラットフォームがWebかNativeかを判定するためのフラグも用意されています ^3 。 フラグ 説明 dart.library.html Webプラットフォームかどうか dart.library.io Nativeプラットフォームかどうか これらを駆使することでエラーを回避することができます。 まずは、以下のようにしてWeb用・Native用のダウンロード機能モジュールを用意し、前述のWebパッケージ使用箇所をテスト対象のコードから分離しましょう。 import 'dart:html'; void download(String fileName, String data) { AnchorElement(href: 'data:text/plain;charset=utf-8,$data') ..setAttribute('download', fileName) ..click(); } void download(String fileName, String data) => throw UnsupportedError('Not support this platform'); そして、上記モジュールのインポートをプラットフォームごとに切り替える方法は以下のようになります。 import 'package:flutter/material.dart'; - import 'dart:html' + import './utils/util_io.dart' + if (dart.library.html) './utils/util_html.dart'; class MyHomePage extends StatefulWidget { // 省略 } class _MyHomePageState extends State<MyHomePage> { // 省略 @override Widget build(BuildContext context) { return Scaffold( // 省略 floatingActionButton: FloatingActionButton( onPressed: () { - AnchorElement(href: 'data:text/plain;charset=utf-8,$_counter') - ..setAttribute('download', 'counter.txt') - ..click(); + download('counter.txt', _counter.toString()); }, tooltip: 'Download', child: const Icon(Icons.download), ), ); } } エクスポートをする場合は、別途 util.dart などの仲介ファイルを用意してWidget側からインポートすることになると思います(ここでは省略します)。 export './utils/util_io.dart' if (dart.library.html) './utils/util_html.dart'; 以上で、Web依存のコードによるエラーを回避してNativeプラットフォーム上でテストを実行することができるようになりました。 Webプラットフォーム依存の外部パッケージにはNativeプラットフォーム用のスタブも作ろう 私たちのシステムは認証基盤にKeycloakを採用しています。 Flutter Webアプリ上でKeycloakの認証をするために以下のパッケージを使用しています。 @ card リンクを開いてもらえるとわかると思いますが、このパッケージはWebのみをサポートしています。 このパッケージのおかげで楽に認証処理を実装することができたのですが、認証モジュールという特性上そのインターフェースは色々なところで利用されるため、APIコールなど認証情報を必要とするようなWidgetがすべてWebプラットフォーム依存となってしまい、CIでテストできなくなる状況になってしまったことがありました(この間はローカルで --platform chrome オプションでテストして全PassしたらOKという性善説運用をしていました)。 ちなみに、このパッケージをインポートすると以下のエラーがテスト実行時に発生します。 Error: Dart library 'dart:js_util' is not available on this platform. そこで、前述のインポート分離と同様な処置を外部パッケージにも行っていくのですが、ここではエクスポートを使ったパターンで実践していきたいと思います。手順は以下となります。 1. 仲介パッケージの作成 ここでは例として inter_lib というパッケージをサンプルコードのパッケージ内に作成しています。 flutter create inter_lib --template=package 実際のプロダクトコードでは、外部パッケージに準じたコードをプロダクトコード内に混入させないため、プロダクトとは別のパッケージを作成して外部パッケージを仲介させています。 Melos を使うと簡単にマルチパッケージ開発ができるのでおすすめです。 2. Nativeプラットフォーム用のスタブの作成 keycloak_flutter のスタブを作るため、Githubのリポジトリを参照してインターフェースを模擬します(ライセンスの確認は適宜お願いします)。 プロダクトコード上で使用しているクラスやメソッドはすべてが必要になります。 @ card 作成したファイルは以下のようになっています。 src ディレクトリ以下の stub_ のプレフィックスがついているものが外部パッケージのインターフェースを模擬したものです。 inter_lib ├── lib │ ├── keycloak.dart │ └── src │ ├── stub_keycloak.dart │ ├── stub_keycloak_flutter.dart │ └── entry_point.dart また、 entry_point.dart は実際の外部パッケージと同じものをエクスポートするように定義しました(実際にはプロダクトコード内で使用しているインターフェースだけで十分です)。 export './stub_keycloak.dart' show KeycloakConfig, KeycloakInitOptions, KeycloakLogoutOptions, KeycloakLoginOptions, KeycloakProfile; export './stub_keycloak_flutter.dart'; この inter_lib をパッケージとして内部公開するため、以下のようにエクスポートの設定をします。 library inter_lib; export './src/entry_point.dart' if (dart.library.html) 'package:keycloak_flutter/keycloak_flutter.dart'; 3. 仲介パッケージを pubspec.yaml の dependencies へ追加 pubspec.yaml に inter_lib への相対パスを追加します。 // 省略 dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 + inter_lib: + path: './inter_lib' // 省略 そして、元々外部パッケージを参照していたところを inter_lib に置き換えます。 - import 'package:keycloak_flutter/keycloak_flutter.dart'; + import 'package:inter_lib/keycloak.dart'; import 'package:flutter/material.dart'; import 'package:sample_web/my_home_page.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); final keycloakService = KeycloakService( KeycloakConfig( url: 'XXXXXXXXXXXXXXXXXXXXXX', realm: 'XXXXXXXXXXXXXXXXXXXXXX', clientId: 'XXXXXXXXXXXXXXXXXXXXXX', ), ); await keycloakService.init( initOptions: KeycloakInitOptions( onLoad: 'login-required', enableLogging: true, checkLoginIframe: false, ), ); runApp( const MyApp(), ); } 以上、Webプラットフォーム依存パッケージのNativeプラットフォーム用スタブの作成フローでした。これでテストをVM上で実行できるようになります。 この方法は今回の例として用いたkeycloak_flutter以外にももちろん適用できます。 ![successful people](/assets/blog/authors/osugi/20240301/success.png =480x) まとめ 今回の記事では、Flutter Webのコードをテスタブルな状態に維持するために単体テストで工夫していることをまとめました。 Dartの実行環境には、WebプラットフォームとNativeプラットフォームがある flutter test はNativeプラットフォーム実行であり、 dart:html などのWebプラットフォーム用パッケージを使っているとエラーとなってしまう dart.library.io , dart/library/html のフラグを活用して、プラットフォームごとに実パッケージとスタブを切り替える実装をすると幸せになれる
アバター
Hello, I am _awache ( @_awache ), and I do DBRE at KINTO Technologies (KTC from now onwards). KTC operates a large number of databases such as Amazon Aurora on Amazon Web Services (hereinafter abbreviated as AWS) as a foundation for providing mobility services. It established the Database Reliability Engineering (hereinafter abbreviated as DBRE) organization and is implementing initiatives to balance business agility and governance. In this article, I will talk about why KTC needs DBRE. About Database Reliability Engineering (DBRE) DBRE stands for Database Reliability Engineering. It is responsible for using an approach that combines the best practices of software engineering and database management. Our main jobs are: Defining and measuring SLO/SLI and making an approach to a development organization accordingly Increasing productivity through automation and autonomy Increasing the uptime of backup, restore, and other services Database security guarantee and governance control Cross-functional collaboration with specialists from other disciplines These roles can be summed up as ensuring the reliability of services by using specialized knowledge and decisions on databases. Do Companies Need DBRE? The term "DBRE" may seem very appealing to some people. However, it is difficult to achieve sustainable results without thinking the reasons why it is necessary in an organization. The rapid growth of AWS and other public cloud services, the evolution and widespread acceptance of DevOps and SRE principles, coupled with the progress in AI technology, have collectively established a robust foundation. This foundation empowers individuals to address problems up to a certain complexity level through Cloud utilization. Consequently, the demand for specialized knowledge in database engineering is diminishing. On the other hand, the basic approach to databases has not changed even now. Separate environment Manage configuration Measure performance Backup/Restore Security guarantee, etc. Simply put, it can be said that it's the environment surrounding databases that has changed . You might also want to consider introducing DBRE at your company if you decide it is necessary given the changes in the times. Why KTC Needs DBRE Here's an explanation of why KTC is adopting DBRE practices. The relationship between software engineers and database administrators had changed The roles of software engineers and database administrators are clearly separated in this age When the company still focused on on-premises configurations, software engineers and database administrators generally had distinct roles and worked in their respective areas of expertise. For example, I think there were classifications like these: Software Engineering Maintaining service uptime and accelerating its growth Extracting necessary data at users' requests Tuning that does not require changes to the database DDL such as query changes Adapting to application according to requests from database administrators Database Administration Maintaining database uptime The major difference between the two is the speed and expertise in responding to requests and users' needs. Because software engineers are closer to the service provider side, they need to respond as quickly as possible to meet needs. Since database administrators focus on the database rather than on services, they use their expertise to solve various issues at the latest even if they respond more slowly. It is like the following figure. ![Relationship1](/assets/blog/authors/_awache/20231211/関係性1.jpg =500x) In an organization like this, the database administrator finds issues throughout the organization and solves them. The rise of public cloud services has decreased work done by database administrator and expanded the area of software engineers The rise of public cloud services such as AWS has drastically changed the roles of both sides. It can be said that the role of the database administrator has been drastically reduced because public cloud services can maintain database uptime. On the other hand, some of the jobs that database administrators were responsible for are done by database administrators and software engineers, specifically: Separate environment Manage configuration Measure performance Backup/Restore Security and Governance Control Software engineers in the workplace are now required to do these things. Because of that, there are times when the database does not get enough attention. ![Relationship2](/assets/blog/authors/_awache/20231211/関係性2.jpg =500x) KTC started facing issues in this regard. In order to keep accelerating business growth, software engineers must be able to focus on business growth. In today's world of cloud utilization, DBRE must be a hub with public cloud services in order for software engineers to focus on business activities. The Key Roles Required of DBRE Maintaining service uptime using databases Making engineers in the workplace more productive Handling database security Protecting the database from internal and external factors By fulfilling these roles, DBRE accelerates the continued growth of the company. ![Relationship3](/assets/blog/authors/_awache/20231211/関係性3.jpg =500x) The following chapters provide more information on each role. The Roles of DBRE in the Cloud Era Maintaining service uptime using databases Generally, a properly functioning database is required for a service to run properly. In other words, database downtime directly leads to service downtime. In order to maintain service uptime, the database must be restored correctly, appropriately, and quickly. So what DBRE needs is the skills to keep the database running on the cloud. king engineers in the workplace more productive Promoting standardized operation of a database can significantly contribute to companies. Examples include using a platform that provides company guidelines, automatically generating database documents such as ER diagrams, and automating routine operations. DBRE also plays an important role in validating new features and applying them to the company, addressing application bottlenecks such as slow queries, and troubleshooting. These do not scale even if only DBRE does them. DBRE has to work with much less resources than software engineers. It is important to note that outputs from DBRE go back to the software engineers and can be handled by anyone. Handling database security The database becomes more important as the business grows. When the database becomes more valuable, it is constantly targeted. A data leak can cause financial losses and tarnish the company's reputation. It is necessary to protect the database from risks like that for the company to keep growing. For that reason, it is important that DBRE implements database security measures as a business unit. ![ChangeinTimeandsValue](/assets/blog/authors/_awache/20231211/時間と価値の変化.png =500x) Protecting the database from internal and external factors Data is easily influenced by changes in external factors. Because of that, database operation requirements become more strict over time. In particular, companies have to address changes in governments, regulations, public opinion, and other factor outside of the company's or people's control. For example, the Personal Information Protection Act and other laws get revised regularly, and the penalties tend to get more strict each time. If each service individually addresses influences by external factors, it presents financial risks, the risk of a leak, and other risks. DBRE is required to properly understand the risks of external factors and implement optimal governance control across all databases in the company. KTC DBRE's vision At KTC, DBRE is a cross-functional organization. It provides value by having our outputs reflected on the business. I think that having a cross-functional organization without knowing how to leverage it is the same as paying taxes and not understanding where your money goes. It is important to know how to positively affect the business. These days, businesses change too fast to be handled with just rules and reviews. It is important that DBRE uses its knowledge of databases to contribute to engineers in the workplace and maintain the reliability of KTC as a company. For that reason, we try to solve database issues through engineering to the best of our abilities. We implement governance control in services and positively impact the business by working together with engineers in the workplace and quickly solving issues without being restricted by rules. Conclusion The Roles of KTC DBRE Provide an environment in which engineers in the workplace can focus on growing the business. The Key Roles Required of KTC DBRE Maintaining service uptime using databases Making engineers in the workplace more productive Handling database security Protecting the database from internal and external factors By fulfilling these roles, DBRE accelerates the continued growth of KTC. It is required to positively influence the business by working together with engineers in the workplace and quickly solving issues by focusing on these roles without being bound by rules. Do you want to discuss DBRE with us? We have just starting doing DBRE. We are still doing trial and error to see why we are doing DBRE, what we want to accomplish, and we will do it. By having frank discussions on what we are doing and what we want to do, we can expand our horizons. We also want to talk about our efforts to receive a lot of input. If you are interested, please send us a DM on Twitter. We are Hiring I think recruiting DBRE team members is a huge challenge. If you are interested in our activities, do not hesitate to send your application through our recruitment page . We're also open to casual conversations with anyone who wants to chat with us. We're also planning to organize events such as DBRE meetups and collaborate with companies that follow DBRE practices. We look forward to you joining us when that happens!
アバター