Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Progate_PathにおけるNew_Relic連携と活用事例
Search
Naoya Uda
October 08, 2024
100
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Progate_PathにおけるNew_Relic連携と活用事例
NRUG (New Relic User Group) 名古屋 Vol.0 の登壇資料です
Naoya Uda
October 08, 2024
Featured
See All Featured
Why Our Code Smells
bkeepers
PRO
340
58k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
440
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Navigating Team Friction
lara
192
16k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
300
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
120
120k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
480
Marketing to machines
jonoalderson
1
5.7k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4.2k
Transcript
Progate PathにおけるNew Relic連携と活用事例 2024/10/04 @NRUG (New Relic User Group) 名古屋
Vol.0 株式会社Progate Path Group ソフトウェアエンジニア 宇多直也
宇多直也 Progate Pathチームでソフトウェアエ ンジニアをしています Progate Pathチーム内ではアプリ ケーション領域全域(バックエンド、フ ロントエンド) +インフラをを主に触っ ています
自己紹介 2
• ProgateとProgate Pathについて • New Relicを用いて実施していること 今日のおしながき 3
ProgateとProgate Pathについて
Progateは2023年06月に世界累計ユーザー数300万人を突破。 しかし、本気でエンジニアを目指したい人にとっては『実務感が不足している』という課題も明確に。 エンジニアとしての第一歩! エンジニアとして活躍! Progateだけだと現場に出るにはスキルが不足している … Progateの後、何をやったらいいかわからない… 300万人以上の人に 一歩目を提供できた! 『初めての実務経験』に辿り着くまでには
高いハードルがある… これまでのProgate 5
Progate Path の紹介 6 • Progate Pathはプロダクト開発ができる人になってもらう学習サービス 実装 企画 設計
実際に作り上げる 評価 まずはここがきちんと1人でできるかが問われる 仮 説 実 行 検 証 どうやって 実現するか考える 欲しいものを 考える 欲しかったものがで きたかを 確認する
実際のサービスが動いている様子 7
• メンバー ◦ エンジニア 2人 ▪ ふたりともバックエンドメインで、フロントエンドなどは何とか頑張っている ◦ 他ロールのメンバー =インフラメインで面倒を見ている人はいない
Pathチームのメンバー構成 8
• 新規事業のため、アプリケーションの新規開発を優先したい • インフラの改善等にたくさん人をアサインしたり時間が掛けられるわけではない • ただ、クリティカルなエラーや性能劣化は正しく観測できるようにしたい • New Relicを用いてアプリケーション全域を観測し、上記の問題が発生したときに適 切に解決/改善できるようにしている
Path内でのNew Relicの活用方針 9
New Relicを用いて実施していること 10
Progate Pathのアーキテクチャ 11 API(gRPC) server Front(Next.js app router) server
• Errorのトリアージ及び調査 ◦ チーム内でerror確認当番を決めて、週一でローテーションしている ◦ Alertをslackに流しているので、担当者は対応の優先度を決める ▪ クリティカルなものはすぐに対応開始 ▪ 優先度低い場合は一時対応して終わる
• タスクだけ起票 • 何もしない • etc New Relicを用いて実施していること 12
• Transaction • Logs In Context • Session Replay Error調査時に役立っているもの
13
あるrequestが開始してからresponseを返すまでに発生した処理を確認できる Error調査時に役立っているもの : Transaction 14
• Path apiはgo + gRPCを利用しているため、New Relic公式のintegrationを用いて RPCごとにtransactionを可視化している • https://github.com/newrelic/go-agent のgRPC
Interceptorを噛ませることで簡単 にtransactionを可視化できる server := grpc.NewServer( grpc.UnaryInterceptor(nrgrpc.UnaryServerInterceptor(app, nrgrpc.WithStatusHandler(codes.OK, nrgrpc.ErrorInterceptorStatusHandler), grpc.StreamInterceptor(nrgrpc.StreamServerInterceptor(app)), ) Error調査時に役立っているもの : Transaction 15
• DBやRedisに対するアクセスも簡単に追跡できる client := redis.NewClient(redisOptions) client.AddHook(nrredis.NewHook(redisOptions)) import ( _ "github.com/newrelic/go-agent/v3/integrations/nrmysql"
// blank import ) db, err := sql.Open("nrmysql", "dsn") Error調査時に役立っているもの : Transaction 16
• 一連の処理で発生したlogを紐づけることができる ◦ 他にもユーザーIDなどをLogに埋め込める • これを実現するため、go-grpcのlogrusのmiddlewareとNew Relic公式の integrationを組み合わせている ◦ https://pkg.go.dev/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus
◦ https://pkg.go.dev/github.com/newrelic/go-agent/_integrations/logcontext/nrlogrusplugin Error調査時に役立っているもの : Logs In Context 17
logger := logrus.New() nrApp, err := newrelic.NewApplication() // newrelicのapplicationを作る if
err != nil { logger.Fatalf("unable to create New Relic Application: %s", err) } // loggerのformatterをnewrelicのformatterに変更することで、logしたときにnewrelicにもログが送信されるようになる logger.SetFormatter(nrlogrus.NewFormatter(nrApp, &logrus.JSONFormatter{})) // loggerをentryに変換し、request-scoped contextに埋め込む interceptor := grpc_logrus.UnaryServerInterceptor(logrus.NewEntry(logger)) ステップ1: ContextにNew Relicに対応した Loggerを仕込む 18
func CreateLoggingFieldsUnaryServerInterceptor() grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{}, info
*grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { user := auth.UserInfoContext(ctx) if !user.Anonymous { // context内のLog entryにaccountSubject(user id)を仕込む ctxlogrus.AddFields(ctx, logrus.Fields{ "accountSubject": user.AccountSubject, }) } return handler(ctx, req) } } ステップ2: Request発生時にinterceptorでユーザー情報を Context内Log Entryに埋め込む 19
func contextLogger(ctx context.Context) *logrus.Entry { // context内からfieldを埋め込んだloggerを取り出して、改めてcontextを詰めて返す return ctxlogrus.Extract(ctx).WithContext(ctx) }
func SomeRequest(ctx context.Context, req *SomeRequest) (resp *SomeResponse, err error) { something, err := something(req) if err != nil { // withErrorでerrorを渡すとerror自体がlogに出力される ContextLogger(ctx).WithError(err).Error("some error happened") } } ステップ3: ContextからLoggerを取り出して logする 20
Errors Inbox などからlogが紐づいていることが見える 21
Log内部にtraceidやuser id(accountSubject)が入っている 22
• frontendでerrorが発生したときに、ユーザーさんのintaractionの一部始終を録画 することができる • 録画をみることでどのような操作でerrorになったかより把握しやすくなる Error調査時に役立っているもの : Session Replay 23
Error調査時に役立っているもの : Session Replay 24
• Path frontendはSPA Pro agentを利用している • New Relicのapplication設定画面でSession Replayの有効化を設定して、sinippet をCopyすることで利用できる
Session Replayの有効化 25
• Synthetic Monitoringによる外形監視 • やっていること ◦ シンプルなpingによるhealthcheck ◦ サービスに対するログインができるかチェック ▪
JavaScriptでコードを書ける ▪ WebDriver + seleniumを使ったブラウザ操作を書いて動かしている New Relicを用いて実施していること 26
await $webDriver.get('https://app.path.progate.com') const email = await $webDriver.findElement($selenium.By.css('input[type="email"]')) await email.sendKeys('
[email protected]
') const
password = await $webDriver.findElement($selenium.By.css('input[type="password"]')) await password.sendKeys('password') const submitButton = await $webDriver.findElement($selenium.By.css('button[type="submit"]') await submitButton.click() await $webDriver.wait($selenium.until.urlIs('https://app.path.progate.com/dashboard')) JavaScriptで動作を書ける 27
• チーム内で週一回APMを確認する会を実施 ◦ 一週間分のAPM内の指標を確認して、異常があるか確認する ◦ あった場合、対応を決める ▪ 根本的な問題解消 ▪ より詳細にlogやsegment(後述)を仕込む
▪ なにもしない、など New Relicを用いて実施していること 28
• Summary ◦ 見たい情報(Golden signalsやApdex score)が概ね表示されている ◦ Golden Signals ▪
Response time ▪ Throughput ▪ Error Rate ◦ Apdex score ▪ request全体に対するユーザーの満足度 • Transaction ◦ 主にWeb Transaction(requestが始まってからresponseを返すまで) • ECSコンテナ(主にapi)のmemory/cpu使用率 主にAPMで確認しているもの 29
• より細かく処理のボトルネックを計測したい場合、segmentを使う ◦ ある処理から別の処理までの一連の区間を計測できる Transaction内部の処理をより細かく計測する 30
func Something(ctx context.Context, req *SomeRequest) (resp *SomeResponse, err error) {
// contextからnew rewlicのrequestのtransactionを取り出す txn := newrelic.FromContext(ctx) fooSegment := txn.StartSegment("foo segment start") foo() fooSegment.End() barSegment := txn.StartSegment("bar segment start") bar() barSegment.End() buzSegment := txn.StartSegment("buz segment start") buz() buzSegment.End() } Request(Transaction)の中にsegmentを埋め込む 31
今日お話したことを手元で試せます! 32
New Relic とのコラボタスクがあります 33
Progate Pathでエンジニアとしての一歩を踏み出しましょう! 一緒に働くメンバーも募集してます! 34