TECH PLAY

株匏䌚瀟゚ブリヌ

株匏䌚瀟゚ブリヌ の技術ブログ

å…š450ä»¶

はじめに こんにちは トモニテ でバック゚ンド呚りの開発を行っおいる rymiyamoto です。 トモニテ ではこれたで構成を AWS の EKS を䜿っおきたしたが、2 月の初旬に ECS に移行したのでその内容を玹介しおいきたす。 本内容のスラむドverはこちら↓ speakerdeck.com 経緯 移行を決断したのは最倧の理由は、珟状のメンバヌで kubernetes(以䞋 k8s) のをメンテナンスしおいくコストが高すぎるためです。 k8s 自䜓が高頻床にアップデヌトが進んでおり、日々の業務を進めがらのキャッチアップが難しく、いざアップデヌトするのは EKS のサポヌトが切れる間際になっおしたい埌手に回っおいたした。 (倧䜓幎 1 回ぐらいのペヌスでやっおいたした) 察応をすすめる際もバヌゞョンが倧きく飛んでしたうため、リリヌスノヌトを远っおちゃんずアップデヌトを完了するにはだいたい 1 メンバヌ 1 ヶ月ぐらいはかかっおしたいたす。 かかる工数がもったいなく、たた瀟内の別プロダクトで ECS の運甚実瞟がしっかりずあるので合わせるこずずなりたした。 移行たでのロヌドマップ 基本的には EKS 郚分を ECS に乗り換えるに止め、党䜓的なアヌキテクチャの倉曎はしない方向で進めたした。 理由ずしおは諞事情により察応期間があたり取れなかったためです。 実際進めおいったずきのロヌドマップは以䞋のようになりたす。 AWS コン゜ヌル䞊で ECS 環境を甚意 ECS 環境の IaC 化 & CI/CD の敎備 ECS 環境に切り替え 本番移行も移行 EKS 環境の砎棄 AWS コン゜ヌル䞊で ECS 環境を甚意 たずは ECS に乗り換えおアプリケヌションレベルので修正が必芁かを確認するために、DEV 環境のコン゜ヌル䞊から環境を構築しおいきたした。 クラスタヌの䜜成 API server やら web 等をタスク定矩 タスク定矩をもずに ECS のサヌビスを Fargate で䜜成 これらに䌎う role や policy の䜜成/倉曎 ECS 環境の IaC 化 & CI/CD の敎備 アプリケヌション偎の調敎が枈み次第、terraform におこし反映しおいきたす。 ただ ECS のタスク定矩は初回の生成移行それぞれのサヌビスで環境倉数やコンテナむメヌゞを管理したいため、それぞれの repository で json ファむルずしお管理するようになりたした。 タスク定矩(task-definition.json) { " taskDefinition ": { " containerDefinitions ": [ { " name ": " api-server ", " image ": " 111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/api-server:develop ", " cpu ": 0 , " portMappings ": [ { " containerPort ": 1323 , " hostPort ": 1323 , " protocol ": " tcp " } ] , " essential ": true , " command ": [ " /bin/sh ", " -c ", " './run.sh' " ] , // 起動コマンド、スクリプトあるのでそれを実行 " linuxParameters ": { " initProcessEnabled ": true } , " environment ": [ // more... ] , " ulimits ": [ { " name ": " nofile ", " softLimit ": 1024 , " hardLimit ": 4096 } ] , " mountPoints ": [] , " volumesFrom ": [] , " secrets ": [ // more... ] , " logConfiguration ": { " logDriver ": " awslogs ", " options ": { " awslogs-create-group ": " true ", " awslogs-group ": " /ecs/api-server ", " awslogs-region ": " ap-northeast-1 ", " awslogs-stream-prefix ": " ecs " } } } ] , " family ": " api-server ", " taskRoleArn ": " arn:aws:iam::111111111111:role/server-ecs-task-role ", " executionRoleArn ": " arn:aws:iam::111111111111:role/ecsTaskExecutionRole ", " networkMode ": " awsvpc ", " volumes ": [] , " placementConstraints ": [] , " requiresCompatibilities ": [ " FARGATE " ] , " cpu ": " 256 ", " memory ": " 512 ", " runtimePlatform ": { " cpuArchitecture ": " X86_64 ", " operatingSystemFamily ": " LINUX " } , " tags ": [] } } サヌビス関連 今回は別プロダクトでも運甚しおいる ecs-deploy を利甚したした。 (こちらは珟圚メンテナンスモヌドで機胜远加はありたせんが保守は滞りなく進んでいるようです) 先皋のパヌトで䜜成したタスク定矩の json を枡すこずで簡単にデプロむするこずができたす。 # ecs-deployの甚意 curl -sL https://github.com/silinternational/ecs-deploy/archive/ 3 . 10 . 7 .tar.gz | tar zxvf - mv ecs-deploy-3. 10 . 7 ecs-deploy chmod +x ecs-deploy/ecs-deploy # 途䞭でdocker image 䜜成やECRぞのアップロヌド等の凊理 # 省略... # サヌビスぞデプロむ ecs-deploy/ecs-deploy --cluster ecs-cluster \ --task-definition-file task-definition.json \ --service-name api-server \ --region ap-northeast-1 \ --timeout 600 \ --image 111111111111 .dkr.ecr.ap-northeast-1.amazonaws.com/api-server:develop 䜙談ですが ecspresso の採甚も芖野にありたしたが、今回は察応できる期間も短く瀟内で運甚実瞟ないため採甚は芋送りずなっおいたす。 バッチ関連 これたで k8s 䞊では定期実行を cronjob、ショット実行で job を甚いおおり、たたバッチの docker image は党おたずめおいたした。 (バッチが増えるたびに image を ECR ぞ登録しおいくのは面倒なので) そのためそのたた AWS CLI で䜜成するず CloudWatch のロググルヌプがひずたずめになり芋づらくなっおしたう + ショット実行の方法が面倒になっおしたいたす。 今回は scheduled task を管理するために ecschedule で反映するようにしたした。理由ずしおは、スケゞュヌル、override 含めお yaml で管理可胜なずころず run での即時実行にも察応しおいたためです。 共通化できる郚分は yaml のテンプレヌト化したいので ytt を採甚しおいたす。 構成むメヌゞずしおは以䞋のようになりたす。 . ├── base-task-def.jsonテンプレヌトずなるタスク定矩 ├── config.yamlecsscheduleで䜿う蚭定ファむル ├── tasks各batchの蚭定ファむル ├── batch-hoge.yaml └── batch-fuga.yaml └── more... base-task-def.json { " executionRoleArn ": " arn:aws:iam::111111111111:role/ecsTaskExecutionRole ", " containerDefinitions ": [ { " logConfiguration ": { " logDriver ": " awslogs ", " options ": { " awslogs-group ": " /ecs/server-batch ", " awslogs-region ": " ap-northeast-1 ", " awslogs-stream-prefix ": $job_name } } , " entryPoint ": [] , " portMappings ": [] , " command ": [] , " cpu ": 0 , " environment ": [ // more... ] , " mountPoints ": [] , " secrets ": [ // more... ] , " volumesFrom ": [] , " image ": " 111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/server-batch:develop ", " name ": " server-batch " } ] , " placementConstraints ": [] , " memory ": " 1024 ", " taskRoleArn ": " arn:aws:iam::111111111111:role/scheduled-task ", " family ": $job_name, " requiresCompatibilities ": [ " FARGATE " ] , " networkMode ": " awsvpc ", " runtimePlatform ": { " operatingSystemFamily ": " LINUX " } , " cpu ": " 512 ", " volumes ": [] } config.yaml #@ load("@ytt:data", "data") region : ap-northeast-1 cluster : ecs-cluster rules : #@ data.values.rules batch-hoge.yaml #@data/values --- rules : - name : batch-hoge scheduleExpression : cron(0 0 * * ? *) taskDefinition : batch-hoge containerOverrides : - name : server-batch command : - ./exec environment : # more... launch_type : FARGATE platform_version : LATEST network_configuration : aws_vpc_configuration : subnets : - subnet-hoge - subnet-fuga - subnet-foo security_groups : - sg-hoge assign_public_ip : DISABLED disabled : false この構成のもずに CI 偎でタスク定矩ず scheduled task の登録を行っおいたす。 # tasks配䞋のbatchをもずにタスク定矩 for item in ` ls tasks` do job = `basename ${item} .yaml` new_task_definition = $( jq -n --argjson job_name " \" $job \" " -f " base-task-def.json " ) aws ecs register-task-definition --cli-input-json " $new_task_definition " done # yttでecscheduleで反映させるためのyaml生成 ytt -f " config.yaml " -f " tasks " --file-mark ' config.yaml:exclusive-for-output=true ' > " ecschedule.yaml " # 生成したyamlを元に反映 ecschedule -conf " ecschedule.yaml " apply -all たた䜙談ですがこの構成のずきショット実行の際は以䞋のように実行できたす。 # ショット実行したいタスク item = " batch-hoge.yaml " job = `basename ${item} .yaml` # yttでecscheduleで反映させるためのyaml生成 ytt -f " config.yaml " -f " tasks/ ${job} " --file-mark ' config.yaml:exclusive-for-output=true ' > " ecschedule.yaml " # 生成したyamlを元に反映 ecschedule -conf " ecschedule.yaml " run -rule $job ECS 環境に切り替え 䞀気に新環境に切り替えおいくのは、䞍枬の事態があったずきに察応が倧倉になるので、Route53 で新環境ぞ加重を数日かけお少しず増やしおいきたした。 たた batch 系は 二重で走らないように EKS 偎を停止した状態でスケゞュヌルタスクを active に倉曎しお反映させおいたす。 EKS 環境の砎棄 䞍芁になった EKS 向けの CI/CD や関連する aws リ゜ヌスの削陀を進めおいきたした。 䞀気に terraform で関連リ゜ヌスを削陀しようずするず、郜合䞊䟝存するず別のリ゜ヌスたで圱響しおしたいたす。 そのため信頌関係を芋぀぀地道にモゞュヌル削陀を進めおいきたした。 移行しおみお よかったずころ k8s の頃に比べおサヌビスやバッチの構成をマニュフェストで管理するよりはシンプルな構造になりたした。 たた最倧の課題であった EKS のアップデヌト䜜業からの開攟でよりサヌビス開発に重きを降るこずができるようになったず感じたす。 倧倉だったこず EKS on EC2 で運甚しおいたものを ECS Fargate に倉えたこずで厳密にリ゜ヌスの管理をしないずいけないので、これたで芋えおいなかったメモリリヌクが起きおいたこずに気付かされたした。 (この察応の話は以䞋の蚘事で玹介しおいたす) tech.every.tv たた k8s 自䜓が掻発なコミュニティ故にツヌルが豊富でしたが、ECS は AWS に瞛られる圢ずなるのでデファクトスタンダヌドず呌べるデプロむ方法が芋圓たらず䜕かず創意工倫が必芁ずなっおしたいたした。 最埌に 䞖間的の逆の流れを行く察応ずなっおいたすが、k8s を採甚する堎合はサヌビスず組織の芏暡感を意識しおおかないず埌々のメンテナンスが蟛くなっおしたいたす。 もちろん k8s を正しく䜿いこなせるず様々な機胜の恩恵を受けれるので、䜓制的にちゃんず面倒を芋れるかどうかを刀断しおずり入れるのは問題ないず思いたす。 EKS(k8s)ず ECS をどっちですすめるか迷っおいる方や、同じように ECS ぞの移行を怜蚎しおいる方の手助けになれば幞いです。
はじめに こんにちは。MAMADAYS開発郚でiOS゚ンゞニアをやっおる國吉です。 この床、MAMADAYSから姉効アプリ第䞀匟ずなる”陣痛カりンタヌ”をリリヌスしたした。 MAMADAYSアプリはスヌパヌアプリになっおいお機胜数も倚く長く利甚しお頂くナヌザさんも倚いアプリです。䞀方で、陣痛時の利甚ずいう利甚期間が短い甚途のものは小さいアプリに切り出しお機胜特化するこずでシンプルで䜿いやすい戊略を取っおいたす。 そしおタむトルにも曞いおある通り、陣痛カりンタヌはSwift Package Managerを採甚しおいたす。採甚理由は䞋蚘で、お詊しで導入するには最適だず考え、導入に至りたした。 - アプリ自䜓の芏暡が小さい - 前からSwift Package Managerを䜿っおみたかった - 䜿甚するラむブラリ数が少ない 今回はそんなSwift Package Managerに぀いおお話ししおいきたす。 陣痛カりンタヌ 本題に入る前に少し陣痛カりンタヌアプリに぀いお宣䌝をさせおください。 陣痛カりンタヌは機胜・デザむン共にシンプルですごく䜿いやすいたた、オフラむン状態でも動䜜したす 陣痛がきたかなず感じたら”きたかも”ボタンをタップし、時間蚈枬を始めたす。陣痛が治たったら”おさたったかも”ボタンをタップしお蚈枬を終了したす。 それらデヌタを履歎ずしお衚瀺しお、陣痛間隔が䞀定の間隔より䞋回ったらお知らせする。ずいったアプリです 実際の䜿い勝手などは実際にむンストヌルしお䜿っおみおください是非呚りに出産を控える劊婊さんがいたら玹介しお頂けるず嬉しいです。   陣痛カりンタヌ - すぐ蚈枬できる陣痛アプリ・陣痛タむマヌ every, Inc. メディカル 無料 apps.apple.com Swift Package Manager さお、本題のSwift Package Manager(以䞋”SPM”ず略)のお話をしおいきたす。 SPMはApple公匏から提䟛されおいるパッケヌゞマネヌゞャヌになっおおり、Xcode9以降から䜿うこずができたす。 SPMに察応しおいるか調査 たず、アプリに入れようずしおいるラむブラリがSPMに察応しおいるのか調べる必芁がありたす。 ラむブラリ偎がSPMに察応しおいなかった堎合は、SPMは䜿えたせん。 調べ方はすごく簡単で、ラむブラリのディレクトリ内に「Package.swift」ずいうファむルがあるかどうかを芋るだけです。 䟋:nuke https://github.com/kean/Nuke 1. ラむブラリのディレクトリが確認できるペヌゞを開きたす。 2. ディレクトリ内を確認するずPackage.swiftがあるのが確認できたす。 3. これでnukeはSPM察応されおいるこずがわかりたす。 次にアプリ偎でラむブラリ䜿えるようにしおいきたす。  [File] -> [Add Packages ...]  Search or Enter Package URL のサヌチ゚リアでラむブラリのリポゞトリURLを入力し怜玢をかけたす。 するず、このようにnukeがサゞェストされたす。 Dependency Ruleで導入したいバヌゞョン指定を行い、[Add Package]をクリックするず、ダりンロヌドが開始されたす。 耇数パッケヌゞが存圚する堎合は、どのパッケヌゞを導入するか遞択する画面がでるので、任意のパッケヌゞを遞択しダりンロヌドしたしょう。 ダりンロヌドが完了すればラむブラリが䜿えるようになりたす。CocoaPodsず同様にimportしお䜿っおください。  実態はどこに ここたででSPMを甚いおラむブラリを远加しおきたしたが、蚭定ファむルや実態はどこにいるんだチヌム開発をしおいるからメンバヌにはどうやっお共有されるんだ ずいう疑問が生じたした。調べた結果䞋蚘の堎所に蚭定ファむルや実態がありたした。 䟝存関係を解決した結果や各ラむブラリのバヌゞョンが”Package.resolved”ずいうファむルに曞き出されるので、これを他メンバヌに共有されるこずでラむブラリのバヌゞョンを揃えるこずができたす。  # ラむブラリ矀 > /Library/Developer/Xcode/DerivedData/{projectID}/SourcePackages/checkouts/ # Package.resolved蚭定ファむル > /{project}.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved CocoaPodsずの比范 Xcodeのみでラむブラリの远加/削陀が簡単にでき、バヌゞョン確認等々も完結できたす。 "pod init"や"pod install"ずかしなくおいいので、結果的に操䜜する箇所が枛っお楜になりたした。 SPMはApple公匏が出しおいるパッケヌゞマネヌゞャヌなので、安心感はありたす。Xcode13以降ようやく動䜜も安定しおきたようです。  SPM導入で苊劎したこず 陣痛カりンタヌはFirebaseのCrashlyticsを䜿甚しおいたす。 fastlaneでFirebaseにdSYMを䞊げおいるんですが、実行しおも「upload-symbolsが存圚したせん」ず゚ラヌが吐かれたした。 CocoaPodsでラむブラリ管理をしおいるずPodsフォルダ配䞋にupload-symbolsずいうスクリプトファむルが存圚したすが、 SPMはラむブラリの実態がプロゞェクトのディレクトリ配䞋にはいないので、参照できないずいうこずでした。 回避策ずしお、Firebase公匏のペヌゞからupload-symbolsをダりンロヌドし、fastlaneではそのスクリプトファむルを動かすように察応したした。 導入しおみた感想 結論、この芏暡感のアプリにはSPMは適しおいるず思いたした。 たず、CocoaPodsずの比范セクションでも觊れたしたがラむブラリの远加/削陀がXcode内で簡単にできるのが䞀番倧きいメリットです。 Pod関連のファむルも無くなるので、ディレクトリの芋通しも良くなりたす。 Crashlyticsずか独自の察応を行いたしたが、䞀床察応しおおけば䜿い回すこずができるので、最初だけ我慢したしょう。 ただ、陣痛カりンタヌのような小芏暡なアプリに適しおいるず感じおいるだけで、䞭芏暡以䞊のアプリには䞍適切かもしれたせん。 あず、既にCocoaPodsで実装を進めおしたっおいる堎合も、CocoaPodsのたたでいいず思いたす。珟状、移行するコストを払うほどのメリットは無いず感じおいたす。 たた叀いラむブラリはSPMに察応しおいないケヌスも倚々あるので、導入前に远加予定のラむブラリがSPMに察応しおいるかの調査はすごく倧事です。その䞭で1぀でもSPM察応されおいないラむブラリがあるのであれば、手間が増えるだけなのでCocoaPodsにした方がいいです。 最埌に ここたで読んでくださりありがずうございたした。 SPMに぀いお觊りぐらいは䌝わったでしょうかこの蚘事がSPM導入の手助けになるこずがあれば嬉しいず思いたす
DELISH KITCHENの定期賌読 こんにちは、DELISH KITCHEN開発郚でバック゚ンド開発を担圓しおいる南です。 䞻にDELISH KITCHENのプレミアムナヌザヌ向けの機胜の開発を行っおおりたす。 DELISH KITCHENでは、人気順怜玢、プレミアムレシピダむ゚ット、ヘルスケア、矎容・健康、䜜りおき、 プレミアム献立など、さたざたな機胜を提䟛するプレミアムサヌビスずいう定期賌読サブスクリプション商品を販売しおおりたす。 プレミアムサヌビスは、おもにiOSやAndroidのプラットフォヌム䞊で管理、販売されおおりDELISH KITCHENアプリ内から賌入できたす。 ここではiOSの課金をIAP(In-App-Purchase), Androidの課金をIAB(In-App-Billing)ず呌んで区別したいず思いたす。 IAPずIABずDELISH KITCHEN iOSやAndroidのプラットフォヌムに察しおAPIを実行するこずでそれぞれ課金状態を衚したレシヌトを取埗できたす。 IAPレシヌトもIABレシヌトも課金状態を衚珟するものずいう点では共通しおいるのですが、 衚珟の仕方がこずなるためDELISH KITCHENのサヌバヌ偎で違いを吞収する必芁がありたす。 IAPずIABの課金状態に぀いお IAPもIABもレシヌトが衚珟する課金状態はほが同じですが、IABにのみ䞀時停止ずいう状態がありたす。 課金状態名ず、それがDELISH KITCHENにおいお、どのような状態かを説明した衚です。 AndroidのIABレシヌト IABレシヌトの構造はシンプルで、珟時点の賌読状態のみ返したす。 賌読が曎新されれば、 expiryTimeMillis の日時が増加し、支払いに関しお倉化がおきたら paymentState の倀が倉化したす。 { " kind ": " xxxxxxx ", " startTimeMillis ": 1111111111111 , " expiryTimeMillis ": 2222222222222 , " autoRenewing ": true , " priceCurrencyCode ": " JPY ", " priceAmountMicros ": 480000000 , " countryCode ": " JP ", " developerPayload ": "", " paymentState ": 1 , " cancelReason ": 0 , " userCancellationTimeMillis ": 0 , " orderId ": " GPA.0000-0000-0000-0000 ", " linkedPurchaseToken ": "", " purchaseType ": 0 } IABレシヌトずナヌザヌ状態 レシヌトの倀からナヌザヌの課金状態を把握する必芁がありたす。 IABは返す情報がシンプルで、情報ず状態を結び぀ける資料も敎備されおいるので刀別するこずが簡単です。 䞀方で履歎のような過去の情報が䞀切ないため、状態の倉遷をAPIから知る方法がありたせん。 Google Play の課金システム > 定期賌入を販売する (*) 䞀時停止状態ずはナヌザヌがPlayストアの定期賌読䞀芧から指定した期間だけ賌読を䞭断しお、期間がすぎたら再び自動再開する仕組みです。 AppleStoreのIAPレシヌト 䞀方でIAPレシヌトは、IABレシヌトず比べるず構造が耇雑で情報も倚めです。 latest_receipt_info には定期賌読商品の賌入履歎が含たれおいたす。 履歎の1぀1぀には、「どんな商品を賌入したか」、「䜕時賌入したか」、「䜕時期限切れになるか」ずいった倉化しない情報が含たれおいたす。 䟋倖ずしお返金キャンセルが発生するず履歎の倀が倉化したす たた状況に応じお刻々ず倀が倉わる pending_renewal_info ずいう項目がありたす。 pending_renewal_info からは「次回の曎新で賌入する予定の情報」、「定期賌読を継続するか吊か」、「期限切れになった理由」、ずいった状況に応じお倉化する情報が含たれおいたす。 { ... " latest_receipt_info ": [ { " quantity ": " 1 ", " product_id ": " delishkitchen ", " transaction_id ": " 111111111111111 ", " original_transaction_id ": " 111111111111111 ", " purchase_date_ms ": " 1629307052000 ", " purchase_date ": " 2022-02-01 07:00:00 Etc/GMT ", " purchase_date_pst ": " 2021-02-01 00:00:00 America/Los_Angeles ", " original_purchase_date_ms ": " 1643698800000 ", " expires_date_ms ": " 1646118000000 ", " expires_date ": " 2021-03-01 07:00:00 Etc/GMT ", " expires_date_pst ": " 2021-03-01 00:00:00 America/Los_Angeles ", " cancellation_date_ms ": " 0 ", " cancellation_date ": 0 , " cancellation_date_pst ": 0 , " web_order_line_item_id ": " 333333333333333 ", " is_trial_period ": " true ", " is_in_intro_offer_period ": " false ", " promotional_offer_id ": "" } , { " quantity ": " 1 ", " product_id ": " delishkitchen ", " transaction_id ": " 222222222222222 ", " original_transaction_id ": " 111111111111111 ", " purchase_date_ms ": " 1646118000000 ", " purchase_date ": " 2022-03-01 07:00:00 Etc/GMT ", " purchase_date_pst ": " 2021-03-01 00:00:00 America/Los_Angeles ", " original_purchase_date_ms ": " 1629307053000 ", " expires_date_ms ": " 1648796400000 ", " expires_date ": " 2022-04-01 07:00:00 Etc/GMT ", " expires_date_pst ": " 2021-04-01 00:00:00 America/Los_Angeles ", " cancellation_date_ms ": " 0 ", " cancellation_date ": 0 , " cancellation_date_pst ": 0 , " web_order_line_item_id ": " 444444444444444 ", " is_trial_period ": " false ", " is_in_intro_offer_period ": " false ", " promotional_offer_id ": "" } ] , " pending_renewal_info ": [ { " expiration_intent ": "", " auto_renew_product_id ": " delishkitchen ", " original_transaction_id ": " 111111111111111 ", " is_in_billing_retry_period ": "", " product_id ": " delishkitchen ", " auto_renew_status ": " 1 " } ] } IAPレシヌトずナヌザヌ状態 IAPレシヌトは情報が倚めですが、レシヌトからナヌザヌの状態を把握する際は以䞋の情報を甚いおいたす。 latest_receipt_infoの最新のレシヌト is_trial_period: 無料トラむアルか吊か expires_date_ms: 有効期限の日時 cancellation_date_ms: 返金した日時 pending_renewal_info auto_renew_status: 賌読を継続するか吊かを衚す。 expiration_intent : レシヌトが期限切れになった理由を衚す。期限内は垞に空 is_in_billing_retry_period: 支払いリトラむ䞭か吊かを衚す。ExpirationIntent=2以倖のずきは空 grace_period_expiration_date: 猶予期間の期限 auto_renew_product_id: 次回の曎新に賌入するプロダクトID 課金状態ず泚意点 猶予期間 ず 保留䞭(支払いリトラむ状態) ず 䞀時停止 の扱いは気を぀けないずいけたせん。 猶予期間 期限が切れたナヌザヌを匕き続き課金状態ずしお扱うため、IABでは expiryTimeMillis の日時が自動的に䌞びたす。 䞀方IAPでは、latest_receipt_infoの expires_date_ms は䌞びたせん。代わりに、 grace_period_expiration_date_ms に猶予期間の日時が入りたす。 保留䞭支払いリトラむ状態 猶予期間埌も支払いに倱敗し぀づけおいる状態です。 期限切れになり無料ナヌザヌ状態ずなりたすが、䞀定期間デフォルトでiOSは60日間、Androidは30日間支払いをリトラむし続けたす。 リトラむによっお支払いが成功するず賌読状態に戻りたすが、䞀定期間以䞊倱敗し続けるず、プラットフォヌムが自動的に解玄状態にしおリトラむをやめたす。 たた支払いリトラむ期間䞭に解玄するこずもできたす。 䞀時停止 IAB特有のナヌザヌ状態です。こちらも䞀床期限が切れるため、䞀芋解玄したように芋えたす。 しかし指定した期間をすぎるず䜕事も無かったかのように賌読を再開するため、䞀時停止状態䞭だず刀別できおいないず解玄したナヌザヌが再び戻っおきたかのように芋えおしたいたす。 たた定期賌読䞀時停止䞭に解玄するこずもできたす。 定期賌読ず状態管理 Choosing a Receipt Validation Technique こちらで述べられおいる通り定期賌読状態を適切に扱うにはサヌバヌで賌読状態を管理し、同期する必芁がありたす。 ですが、これだけでは䞋蚘のようなナヌザヌの行動の倉遷を远うこずはできたせん。 ナヌザヌ状態をず経緯を正確に刀断するためにも、レシヌトの履歎をサヌビスのサヌバヌ偎で保存するこずも倧切です。 ナヌザヌが猶予期間䞭になっおいたか 保留䞭から戻ったのか、それずもキャンセルしたのか 䞀時停止から戻ったのか、それずもキャンセルしたのか たずめ 定期賌読の難しいずころ でも述べられおおりたすが、 䞀芋単玔そうにみえる定期賌読ですが、正しくやろうずするず実は面倒なこずが倚いです。 たたIAP、IABの仕様远加にも远埓しおいく必芁がありサヌバヌ偎の保守コストがかかりたす。 ですがDELISH KITCHENのプレミアム機胜を倚くの方に提䟛し続けるためにも定期賌読の管理・アップデヌトを続けおいきたいず思っおおりたす。 参考資料 Google Play の課金システム > 定期賌入を販売する App Store Receipt Data Types Choosing a Receipt Validation Technique Question About Ios Receipt Fields Addition on July 19 2017 App Store の In-App Purchase の Grace Period察応 アップルはApp Storeのサブスク期限切れに「猶予期間」を導入 Engineering Subscriptions(WWDC 2018) Auto Renewing Subscriptions for iOS Apps
こんにちは。TIMELINE開発郚の霊藀です。奜きな゚ディタはEmacsです。瀟内の䞀郚゚ンゞニアからは珍獣扱いされおたすが、Emacsは最匷の゚ディタなので20幎近く愛甚しおいたす 1 。 さお、皆様は日頃のサヌビス運甚に、瀟内向けの管理サむトなどを䜜っおいるかず思われたすが、匊瀟でもご倚分に挏れず管理サむトを甚意しお、日々の運甚を行なっおおりたす。 この管理サむトの出来䞍出来によっおは、運甚コストも倧きく倉わったりするので、案倖重芁なものだったりするのですが、䜜るのは正盎めんどくさいです。 ナヌザさんにお芋せするサむトず異なり、MAUは䞀桁ぐらいですし、いいものを䜜っおも誰かに誉められるこずも少ないので、正盎めんどくさいです倧事なこずなのでry なので、めんどうなこずは少しでも楜をし぀぀、それでいお運甚事故/コストを少しでも枛らせられるようにがんばっおいたりしたす。 序文 私が所属しおいるTIMELINE開発郚では、「au payマヌケット」アプリで提䟛しおいる「ラむブTV」の運甚/開発などを䞻に担圓しおいたす。 コロナ犍でラむブコマヌスがEC垂堎で再燃。耇数のプラットフォヌムで配信できる『TIMELINE』ならではの匷みずは 元々、匊瀟ではCHECKずいうラむブコマヌスサヌビスを運甚しおいたした。 ラむブTVはその時の資産を利甚しおおり、管理サむトなども数幎前のリリヌス時に私が䜜ったのがそのたた利甚されおいたりしたす。 圓時は䜕も考えなしに䜜っおたのですが、TIMELINEに合流しお改めお芋るず、あちらこちらでめんどくせヌっおずころが散芋されたため、そこらぞんを修正しおいったあれやこれやを玹介させおいただきたす。 ビルドの自前管理がめんどくさい webpackを甚いおビルドしおいるのですが、元々はそのコンフィグファむルを自前管理しおいたした。 圓時は「 grunt に比べおなんお楜なんだろう...」ず感動しお䜿っおいたのですが、久々に昔曞いたコンフィグファむルを眺めおいるず、「こんなん管理するずかムリヌ」っおいう感情に溢れおしたうほどめんどくさいものでした。 そこで、MAMADAYSで採甚しおいた Next.js ぞ党面的に茉せ替えるこずにしたした。 Next.js の利点ずしお SSR/SSGによるものがよく挙げられたすが、管理サむトのフレヌムワヌクずしお採甚する利点はそこではなく、「ビルド管理をNext.js に任せられる。たた、それに䌎う各皮恩恵(埌述)に䞎れる」ずころです。 もちろん茉せ替える手間はありたす。しかし、今埌発生するであろうめんどくささず比べたら埮々たるものですし、元々が React で曞いおいたので最䜎限の修正だけで茉せ替えるこずができたした。 これにより next build するだけでビルドしおくれたす。コンフィグを自前管理しなくおもいい 2 だなんお、神 さらには、開発時のホットリロヌドも独自で曞いおたのですが、それすらも next dev するだけでやっおくれたす。至れり尜くせりすぎる 開発効率は栌段に䞊がり、现かい修正ずかぞのストレスもだいぶ軜枛されたした。 ルヌティングがめんどくさい 元々は react-router-dom を䜿っお、䞋蚘のような方法でルヌティングを行っおいたした。 import { HashRouter, Switch, Route } from 'react-router-dom'; import Index from './containers/Index'; import Hoge from './containers/Hoge'; const routes = [ { path: '/', exact: true, component: Index, }, { path: '/hoges, exact: true, component: Hoge, }, ]; export default class App extends Component { render() { return ( <HashRouter> <Switch> {routes.map(({ path, exact, component }) => ( <Route key={path} path={path} exact={exact} component={component} /> ))} <Route render={(props) => <NoMatch {...props} /> } /> </Switch> </HashRouter> ); } } 教科曞どおりな react-router-dom の䜿い方ですし、NestedRouteing などの考えはものすごく良いのですが、管理サむトでそこたでやるメリットが思い぀きたせんでした。 むしろ、これだずペヌゞを远加するたびに routes を修正しないずいけないし、path ずファむル名が䞀臎しないケヌスがあったりず、めんどくささが満茉です。 ですが、Next.js に茉せ替えたため、pages 以䞋にファむルを眮くだけで、ルヌティングをよしなにしおくれたす。 だいぶめんどくささが軜枛されたしたし、path ずファむル名が䞀臎しおるだけで、ものすごく気分が楜になりたす。 コンポヌネント名を芚えるのがめんどくさい JavaScript は型がなく厳密な曞き方をせずずも動くので楜っちゃ楜なのですが、型がないがゆえに補完をうたくしおくれたせん。 そのため、ファむル名や䜍眮ずかをある皋床、脳内メモリに栌玍した䞊で開発しないずいけないわけですが、私も本厄を迎える歳ずなっおしたい现かい蚘憶力に心配がでおくるようになっおきたした。 TypeScript であれば、最匷の゚ディタであるEmacsがよしなに補完しおくれる 3 し、import ずかも気にせずに枈むんですが...。 ずいう悩みも、Next.js に茉せ替えたこずにより、 tsconfig.json を眮くだけでTypeScript化は完了です。 無事に加霢による衰えをシステムでフォロヌしおくれようになり、高霢化察策も䞇党です デザむンがめんどくさい cssが苊手です。曞きたくないです。レスポンシブデザむンずかになるず、めんどくささに溢れおたす。 なので、管理サむトは基本的に Bootstrap を䜿っおデザむンしおたす。 ただそれでもクラス名を芚えるのがめんどくさいので、 ReactBootstrap を䜿っおたす。 もちろんReactBootstrapのコンポヌネント名ずかもEmacsが補完しおくれたす 4 。 たた、どうしおもcssを曞かなきゃいけない個所であっおも、Next.js が Sass に察応しおくれるので、生でcssを曞くよりも栌段に楜ができたす。 バリデヌションがめんどくさい 元々は䞋蚘のように各項目ごずにバリデヌションを曞いおいたした。 const [form, setForm] = useState({ name: '', state: 0 }); const isValidName = () => { if (form.name.length < 5) { return false; } if (form.name.length > 10) { return false; } return true; }; const isValidState = () => { if ([0, 1].includes(form.state)) { return false; } return true; }; const onSubmit = (e) => { e.preventDefault(); if (!isValidName() || !isValidState()) { // ゚ラヌハンドリング return; } // 正垞凊理 }; たヌ、めんどくさい。しかも、挏れも生じたくる。入皿しおくれる方の職人芞もあり぀぀の、事故回避でした。 そこで zod を甚いるこずにしたした。 zodに関しおは uttkさんのこの蚘事 が秀逞です。めちゃくちゃ参考にしたした。 䞊蚘の䟋をzodを䜿っお曞き盎すず const schema = z.object({ name: z.string().min(5).max(10), state: z.union([z.literal(0), z.literal(1)]), }); const [form, setForm] = useState({ name: '', state: 0 }); const onSubmit = (e) => { e.preventDefault(); try { f = schema.parse(form); } catch (e) { // ゚ラヌハンドリング return; } // 正垞凊理 }; 意識するのはzodの定矩のみで、非垞にわかりやすくなりたした。 しかも、zodからTypeScriptの型も吐き出せたす type IForm = z.infer<typeof schema>; // IForm = type { // name: string, // state: 0 | 1, // } なので、䞀石二鳥䜿わない手はないです。 フォヌムがめんどくさい 運甚の倧郚分を占めるのが入皿䜜業だず思いたす。 これも元々はお芋せするのも恥ずかしいレベルのオレオレフォヌムを䜜っおいたのですが、 useForm を䜿うようにしたした。 zodず組み合わせるずすげヌ䟿利ですし、すっきりさせるこずができたした。 const methods = useForm<IForm>({ resolver: zodResolver(schema), defaultValues: { name: '', state: 0, }, }); const onSubmit: SubmitHanlder<IForm> = (data) => { // 正垞凊理 }; 跋文 こんな感じで手を抜けるずころは抜いお、それでいお運甚コストを少しでも䞋げられるような改善を日々行っおいたす。 たた、手を抜くこずにより、理解する箇所を極限たで枛らしおいくこずにも぀ながるので、普段フロント゚ンドを曞いおいない゚ンゞニアでも、運甚サむトの曎新ができるずいう面もあったりしたす。 Emacsは ゚ディタではなくOSである ずいう方もおられたすが、ここでぱディタずしお扱わせおいただきたす ↩ もちろん现かい蚭定をいじりたいずきは修正する必芁がありたすが、そうだずしおも栌段に管理が楜になりたした ↩ だいたいの゚ディタでやっおくれたす… ↩ だいたいの゚ディタでやっおくれたす… ↩
はじめに こんにちはMAMADAYSバック゚ンドチヌムのrymiyamotoです。最近゚ルデンリングを遊び倒しおいたす。 MAMADAYSではアプリずWebで利甚しおいるAPI(golang)の仕様をドキュメント化するためにSwaggerを利甚しおいたす。 導入をしおから3幎以䞊経過したため、APIの開発運甚を進める䞭で出おきた課題点ぞの斜策を綎っおいこうず思いたす。 そもそもSwaggerずは SwaggerはOpenAPIずいうRESTful APIの仕様を蚘述するためのフォヌマットを䜿甚したツヌルで、仕様が文章化されるこずで開発者や関係者での認識が取りやすくなりたす。 動䜜環境 MAMADAYSではSwaggerの利甚にあたっお以䞋のツヌルを䜿っおいたす。 ツヌル名 甹途 バヌゞョン swag ドキュメントの自動生成 v1.8.0 echo-swagger Swagger UIの衚瀺で利甚(ドキュメントの可芖化) v1.3.0 Swaggerをそのたた䜿う分にはyamlを衚蚘するだけですが、MAMADAYSではドキュメントを自動生成するための swag を䜿っおいたす。 swag では定矩したstructの型に合わせおドキュメントを生成するのでyamlを盎接手で倉曎する必芁がなく楜です。 たた生成されたドキュメントのたただず芖芚的に分かりにくいため、Swagger UIを衚瀺できるように echo-swagger を利甚しおいたす。 以䞋MAMADAYSので衚蚘に合わせた簡易的な䟋です。 (goのバヌゞョンは1.17.8です) package main import ( "net/http" _ "github.com/rymiyamoto/swagger-test/docs" "github.com/labstack/echo/v4" echoSwagger "github.com/swaggo/echo-swagger" ) type ( Response struct { Int64 int64 `json:"int64"` String string `json:"string"` World *Item `json:"world"` } Item struct { Text string `json:"text"` } ) // @title example // @version 1.0 // @license.name rymiyamoto // @BasePath / func main() { e := echo.New() e.GET( "/swagger/*" , echoSwagger.WrapHandler) e.GET( "/" , hello) e.Logger.Fatal(e.Start( ":1323" )) } // hello godoc // @Summary Hello World ! // @ID HelloWorldIndex // @Tags HelloWorld // @Produce json // @Success 200 {object} Response // @Router / [get] func hello(c echo.Context) error { return c.JSON(http.StatusOK, &Response{ Int64: 1 , String: "example" , World: &Item{ Text: "hello world !" , }, }) } ※go.modずgo.sumは省略しおいたす $ go install github.com/swaggo/swag/cmd/swag@v1. 8 . 0 $ swag init $ go mod tidy $ go run main.go NULL蚱容の倀を衚珟する sql.NullString や sql.NullInt64 などのNULL倀を含むデヌタをそのたた䜿うこずができないため swaggertype:"XXX" で察象のキヌに衚珟したい型を定矩するかず思いたす。 しかしこのたただずNULL蚱容であるかどうかがわかりたせん。 方法ずしおは2皮類あるので玹介したす。 descriptionを远加する 察象のキヌにコメントずしお曞くこずでdescriptionが远加でき、ここでNULL蚱容であるかどうかを衚珟しおたす。 Hello struct { NullInt64 sql.NullInt64 `json:"null_int64" swaggertype:"integer"` // nullable NullString sql.NullString `json:"null_string" swaggertype:"string"` // nullable } extensionsで任意の远加情報を付䞎する(echo-swagger v1.3.0では非察応) extensions:"x-XXX" で任意の远加情報を付䞎するこずが可胜です。 NULL蚱容を衚珟するにあたっおは extensions:"x-nullable" で指定するこずにしたす。 Add extension info to struct field Hello struct { NullInt64 sql.NullInt64 `json:"null_int64" swaggertype:"integer" extensions:"x-nullable"` NullString sql.NullString `json:"null_string" swaggertype:"string" extensions:"x-nullable"` } ただし echo-swagger(v1.3.0) 䞊では衚瀺できないため、出力されたyamlを Suwagger Editor 䞊で確認する人向けです。 (衚瀺がうたくいかないのは、䟝存packageである swaggo/files の内郚で保持しおいるファむルが叀そうです) 同䞀リ゜ヌス名を扱う 同䞀リポゞトリ内でAppやWeb・Dashboard等でAPIを䜜成しおいる堎合、リ゜ヌス名が重耇したす。 このずき swag 偎で党䜓のパスを含めた構造䜓名に倉曎しおくれたすが、その衚蚘が長く冗長になっおしたいたす。 単玔に1぀しかSwaggerを利甚しなければ気にするこずはありたせんが、衚蚘が長くならないようにそれぞれprefixを足しお芋通しを良くしおいたす。 // DashboardHoge 内郚向けDashboard甹 DashboardHoge struct { Text string `json:"text"` StartAT time.Time `json:"start_at"` EndAT time.Time `json:"end_at"` } // Hoge App甹 Hoge struct { Text string `json:"text"` } structでリク゚ストのbodyを衚珟する bodyを扱う堎合に各APIのコメントに以䞋のように蚘茉すればよいです。 // post godoc // @Summary Hello World ! // @ID HelloWorldPost // @Tags HelloWorld // @Produce json // @Param title body string true "タむトル" // @Param description body string false "説明" // @Success 200 {object} Response // @Router / [post] func post(c echo.Context) error { // ... } しかしこの状態だず パラメヌタヌが増えるず定矩が面倒 リク゚ストの定矩ずコントロヌラヌの定矩を別階局で管理しおいるず抜け挏れが発生しやすくなる 同䞀のリク゚ストを䜿いたわしおいるず修正が冗長になっおしたう ずなっおしたいたす。 その察策ずしお、bodyには定矩しおいるformのstructを枡すようにしおいたす。 こうするこずで、form郚分の修正のみで察応するAPIのbodyも䞀括で倉曎できるため管理が簡単になりたす。 // post godoc // @Summary Hello World ! // @ID HelloWorldPost // @Tags HelloWorld // @Produce json // @Param body body Form true "request body" // @Success 200 {object} Response // @Router / [post] func post(c echo.Context) error { // ... } Form struct { Title string `json:"title"` // require Description string `json:"description"` // option } 終わりに swag を䜿い続けお3幎も経過するず色々ず気になるずころが出おくるので、利甚ルヌルの制定倚くなっおきたした。 理想を蚀えばその郚分も定矩できればより汎甚性が出そうです。 しかし適期的にアップデヌト内容を確認しおきたしたが、少しず぀Open API 3.0の蚘法も䜿えるようになっおきおいるのでしばらくは䜿っおいこうず思いたす。 皆様良きSwaggerラむフを
tl;dr Fargate ではホストが隠蔜されおいお、EC2 のように SSH でコン゜ヌルに入っお怜蚌するこずができない ECS Exec は十分に SSH の代甚ずなる ECS Exec の導入に必芁なこずは このセクション を参照 DELISH KITCHEN on ECS 匊瀟では DELISH KITCHEN ずいうサヌビスを運甚しおおり、䞻なアプリケヌションサヌバは ECS の䞊に構築しおいたす。 ECS には EC2 によるものず、Fargate によるものの2぀の環境が存圚したすが、珟時点ではほが党おのアプリケヌションサヌバが EC2 の環境です。 ECS は、十分な機胜を備えながらシンプルで柔軟に運甚できる優れたコンテナオヌケストレヌションサヌビスです。 しかしながら、EC2 環境においおは垞にホストずなる EC2 むンスタンスをメンテナンスする必芁がありたす。 それほど頻繁に発生する䜜業ではありたせんが、定期的に AMI を曎新しなければなりたせんし、ECS 以倖にホストで動䜜させおいるものがあれば、新しい AMI でも同様に動䜜するかの怜蚌が必芁になりたす。 たた、EC2 の定期メンテナンスを行なっおも、基本的にサヌビスぞの圱響がないこずも、どのタむミングでメンテナンスを行うべきかの刀断を難しくさせたす。 同じだけ人員ず工数をかけるのであれば、サヌビスにずっおプラスになるタスクを優先したいずいうのは圓然の考えです。 必然的にこのようなタスクは埌回しになりたすが、䜕らかの理由で倚くの堎合はセキュリティに起因したす本圓に䜜業が必芁になった時には、それたでに積み重なっおいた問題を䞀床に解決しなくおはいけないような状況に陥るこずすらありたす。 DELISH KITCHEN on Fargate Fargate ずは、ECS 䞊でコンテナのホストずなる EC2 の管理を䞍芁にし、ECS タスクの管理に集䞭するこずができるサヌビスです。 DELISH KITCHEN で Fargate を採甚できれば、前述したようなむンスタンスの管理に必芁なタスクが削枛でき、よりサヌビスの開発に泚力できるようになりたす。 これは 2022幎 ゚ブリヌの開発組織の抱負 にある 事業にこだわる開発組織 にもマッチしおおり、導入に向けお怜蚌を進めるこずになりたした。 怜蚌を進めおいく䞭で、䞀番ネックになったのはホストに SSH ができないこずです。 埓来の EC2 環境ではホストに SSH 埌、docker exec 経由でコンテナの内郚の調査ができたのですが、Fargate ではホストも docker も隠蔜されおおり、通垞はアクセスするこずができたせん。 最初は原始的にアプリケヌション自䜓に printf デバッグを仕蟌んだりしおいたのですが、あたりに効率が悪いため、 ECS Exec を導入したした。 ECS Exec の評䟡 ECS Exec では以䞋のようなコマンドで shell を実行できたす aws ecs execute-command --cluster "$CLUSTER" --task "$TASK_ID" --container "$CONTAINER_NAME" --interactive --command sh shell だけ䜿うならほずんど SSH ず䜿い勝手は倉わりたせん。匷いお蚀うならタむムアりトが 20 分ずやや短いのず、その蚭定がグロヌバルでしか蚭定できないずころが䜿い勝手が悪いでしょうか。 scp でファむルの送受信ができないこずも困るタむミングがありたすが、s3 を経由するのが䞀般的な解決法のようです。 port forwarding は ECS Exec では提䟛されたせんが、倧元の SSM では 提䟛されおいたす 。 targetに ecs:{CLUSTER}_{TASK_ID}_{CONTAINER_NAME} を指定すれば Fargate で起動しおいるタスクぞのセッションが開始できたす。 䟋えばコンテナ内の nginx に port forwarding するなら aws ssm start-session \ --target "ecs:${CLUSTER}_${TASK_ID}_${CONTAINER_NAME}" \ --document-name AWS-StartPortForwardingSession \ --parameters '{"portNumber":["80"], "localPortNumber":["$LOCAL_PORT"]}' のようにしたす。 Fargate ぞの道 このように、倚少の制限はあるものの、Fargate でも埓来の䜿い勝手に近い圢でアプリケヌションの調査ができるこずが確認できたした。 珟圚は匕き続き Fargate の評䟡ず移行準備を行なっおおり、次回があればその話をできれば良いず考えおいたす。 たた、ECS Exec を有効化するのにいく぀か戞惑った点があったため、最埌にドキュメントず共に補足ずしおたずめおおきたした。参考になれば幞いです。 ECS Exec の有効化 ECS Exec を利甚するためには、事前にいく぀かの準備が必芁になりたす。 公匏のドキュメント の通りにすれば良いのですが、セッションマネヌゞャヌプラグむンのむンストヌルを芋萜ずしやすいため、泚意が必芁です。 こちらのドキュメントではプラグむンのむンストヌルに関するリンク先が英語のみですが、 こちら にほが同様のものの日本語版がありたす。 以䞋にドキュメントの各セクションに぀いお補足の説明を蚘茉したす。 ECS Exec を䜿甚するための考慮事項 このセクションでは特に以䞋の点に泚意すれば良いでしょう ECS Exec は linux でしか動䜜しない 既存のタスクは倉曎できない蚭定埌に新しく配眮されたタスクから有効になる コマンドは root からのものになる デフォルトのセッションタむムアりトは 20 分 ECS Exec を䜿甚するための前提条件 aws cli は䜙皋叀いバヌゞョンを䜿っおいない限り問題にならないでしょう。 前述の通り、プラグむンのむンストヌルが必芁になりたす。aws cli のセットアップ埌、 ドキュメント に埓っお各自の環境に合わせたプラグむンをむンストヌルしたしょう。 Fargate のバヌゞョンも、最近䜜られたサヌビスなら問題にならないず思いたすが、2021/03/19 より以前に䜜られたものの堎合、泚意が必芁です。 ECS Exec の有効化ず䜿甚 最䜎限 IAM の蚭定ずサヌビスないしタスクの蚭定をすれば ECS Exec を䜿甚できるようになりたす。 察象がサヌビスの堎合、蚭定だけでなく、タスクの再配眮が必芁になりたす。りェブコン゜ヌルからの堎合、"サヌビスの曎新"から"新しいデプロむの匷制"を有効にするず蚭定を倉えずにタスクを再配眮するこずができたす。 珟時点ではりェブコン゜ヌルからはサヌビスやタスクに぀いお、ECS Execを有効にするための機胜は提䟛されおいたせん。ドキュメントに埓い、--enable-execute-command 匕数を䜿っお aws cli から蚭定する必芁がありたす。 aws ecs execute-command で SessionManagerPlugin is not found ずいう゚ラヌが出る堎合、セッションマネヌゞャヌプラグむンが認識されおいたせん。初回の蚭定埌、シェルやマシンの再起動などが必芁な堎合がありたす。
こんにちは。MAMADAYSバック゚ンドチヌムのsa9sha9です。最近Diablo3にハマりたした。 MAMADAYSでは怜玢基盀ずしおElasticsearch(以䞋ES)を利甚しおいたすが、時たた再起動を実斜したいケヌスがありたす。 本蚘事では、れロダりンタむムでのESの再起動を実珟するための泚意点を実際のフロヌに沿っおたずめたいず思いたす。 MAMADAYSのアヌキテクチャに぀いおは以前のTechBlogをご参照ください。 tech.every.tv おこずわり 本蚘事でご玹介する手順に぀いおは必ずしもご自身の環境ずマッチするか保蚌しかねたす。 バヌゞョンごずの差異に぀いおは、しっかりず公匏ドキュメントにおご確認ください。 安盎に再起動ができない理由 ESを利甚する堎合には耇数台のクラスタ構成にするのが垞かず思いたすが、ESクラスタを安盎に再起動しおしたうずダりンタむムが発生しおしたいたす。 怜玢機胜が䞻機胜なサヌビスの堎合には臎呜的な障害ずなっおしたうでしょう。 MAMADAYSでは3台のノヌドでクラスタを構成しおいたすが、それぞれのノヌドを台ず぀再起動するこずでれロダりンタむムでの再起動を目指したす。 再起動の準備䜓操 1. ヘルスチェック 必ずはじめにヘルスチェックを行いたしょう。 ここでステヌタスが yellow / red だった堎合 は必ず settings や shards の状態を確認し、 green ステヌタスにしおから再起動に臚みたしょう。 GET _cat/health // 結果 epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent 1645172581 08:23:01 mamadays-es-cluster green 3 3 xxx xxx 0 0 0 0 - 100.0% 2. ノヌド䞀芧の確認 珟時点でどのノヌドが master node になっおいるかを確認したしょう。 そしお再起動する際には、 master node は最埌に再起動したしょう。 ずいうのも master node が停止した堎合、別のノヌドが master node に成り代わるわけですが、最初に master node を停止するず master node の移動が最䜎でも2回行われおしたいたす。 master node の再起動を最埌に行うこずで master node の移動は必ず1回になるので、䜙蚈な移動を避けられたす。 GET _cat/nodes?v // 結果 ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name 192.168.1.95 37 88 1 0.11 0.07 0.02 dilm - ip-192-168-1-95 192.168.2.238 27 89 1 0.00 0.00 0.00 dilm - ip-192-168-2-238 192.168.3.72 24 89 1 0.04 0.01 0.00 dilm * ip-192-168-3-72 3. むンデックスの状態を確認 再起動埌にデヌタの欠萜がないか確認するため、 docs.count を控えおおきたしょう。 GET _cat/indices/index_01?v // 結果 health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open index_01 xxxxxxxxxxxxxxxxxxxxxx 3 1 x 0 x.xmb xxx.xkb 4. 自動アロケヌション機胜を無効化 ESは replica shards の存圚が確認できないず、別ノヌドに新たな replica shards が䜜成されたす。ノヌドの再起動をかけた際に䞀時的に replica shards が確認できなくなるためこの凊理が実行されたす。 ただし、すぐに耇補を開始するわけではなく、 デフォルトでは分間埅機 しおから耇補を開始したす。 再起動だけなのでほが1分以内にノヌドは埩旧するはずですが、䜕らかの理由で1分を超えおしたうず䞍芁な耇補凊理が行われ膚倧なI/Oが発生しおしたうため、 䜜業䞭は自動耇補を停止 しおおきたしょう。 ただし、 primaries を指定しお primary shards を他のノヌドぞ再配眮するこずは蚱可しおおきたしょう。 PUT _cluster/settings { "persistent": { "cluster.routing.allocation.enable": "primaries" } } // 結果 { "acknowledged" : true, "persistent" : { "cluster" : { "routing" : { "allocation" : { "enable" : "primaries" } } } }, "transient" : { } } 5. 機械孊習機胜が有効になっおいる堎合は停止 もし機械孊習機胜を䜿っおいるなら、䞀時的に停止したしょう。 MAMADAYSでは䜿っおいないのでこの手順はスキップしたす。 これで再起動準備は敎いたした いざ、再起動 1. 各ノヌドに入っおプロセスを再起動 sudo systemctl restart elasticsearch.service 必須ではありたせんが、この時に他の生きおいるESノヌドに1sごずに _cat/shards APIでシャヌド状態を確認するず、 primary shard の再配眮の動きが肌で感じられおずおも良いです。 2. (1぀目のノヌドの再起動を行った埌に) 詊しにヘルスチェック 1぀目のノヌドを再起動したタむミングでヘルスチェックを行うず、ステヌタスが yellow になっおいるかず思いたす。 これは replica shards が䞀時的に切り離されたこずによるもので、怜玢機胜に圱響はありたせん。 GET _cat/health // 結果 epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent 1645170501 07:48:21 mamadays-es-cluster yellow 3 3 xxx xxx 0 0 xxx 0 - 66.7% 3. (党ノヌドの再起動を行った埌に) ノヌドずむンデックスの確認 master nodeの䜍眮が倉わっおいるはずです。 GET _cat/nodes?v // 結果 ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name 192.168.1.95 37 88 1 0.11 0.07 0.02 dilm * ip-192-168-1-95 192.168.2.238 27 89 1 0.00 0.00 0.00 dilm - ip-192-168-2-238 192.168.3.72 24 89 1 0.04 0.01 0.00 dilm - ip-192-168-3-72 GET _cat/indices/index_01?v // 結果 health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open index_01 xxxxxxxxxxxxxxxxxxxxxx 3 1 x 0 x.xmb xxx.xkb 4. 埌凊理 自動アロケヌション機胜を有効化 PUT _cluster/settings { "persistent": { "cluster.routing.allocation.enable": null } } // 結果 { "acknowledged" : true, "persistent" : { }, "transient" : { } } 5. (必芁なら) 機械孊習機胜を有効化 MAMADAYSでは䜿っおいないのでスキップ。 6. 各方面のチェック WebやAppから怜玢機胜が䜿えるかどうかなどを確認したしょう。 これにお、ESクラスタの再起動は完了です。 困った点 ロヌドバランサヌが再起動䞭のESノヌドにも疎通させおしたい䞀定の確率で接続できなくなる MAMADAYSではESの前面にロヌドバランサヌを眮いおいるのですが、ロヌドバランサヌはESノヌドの死掻状態を即時に怜知しないため、ESノヌドの再起動の劂䜕にかかわらず䞀定の確率で疎通させおしたいたす。 ESノヌドの再起動䞭はもちろん応答ができないため゚ラヌを返しおしたい、結果ずしおダりンタむムが発生するこずになりたす。 そのため、ロヌドバランサヌのタヌゲットグルヌプから再起動させるESノヌドを予め陀倖し、再起動䞭は疎通させないようにしおおく必芁がありたす。 kibanaのアクセス先のESノヌドが萜ちるず、その間だけ状態確認ができなくなる 再起動䞭にも _nodes APIなどで状態を確認したい堎合は、curl で他のESノヌドのAPIを呌びたしょう。 理想はkibanaが自動で障害怜知しお他のESノヌドぞ接続しおくれるず良いんですが、どうにもそれができなかったので今回はやむなく䞊蚘の方法で察凊したした。 Sniffing がそういった機胜を有しおいるらしいのですが、うたく動䜜せず今回は芋送りたした。詳しい方がいればぜひ入瀟しお欲しいです。 切り戻しに぀いお 䞇が䞀䜕らかの障害が発生しお、むンデックスデヌタなどを倱っおしたった堎合に備えおsnapshotを取っおおきたしょう。 本蚘事では詳しい説明は省略したすが、バヌゞョン違いによる互換性などは必ず確認するこずをお勧めしたす。 Snapshot and restore | Elasticsearch Guide [8.0] | Elastic 最埌に 本来はこのような トむル は自動化すべきなのですが、本件が緊急察応ずいうこずもあっお手動で行うこずになりたした。 今埌は、誰でも簡単か぀迅速か぀安党に実斜できるようにAnsible化を行おうず考えおいたす。 参考文献 https://www.elastic.co/guide/en/elasticsearch/reference/current/restart-cluster.html#restart-cluster-rolling
少し遅くなりたしたが、あけたしおおめでずうございたす。゚ブリヌのCTO今井です。 早速ですが、2021幎の振り返りず今幎の抱負に぀いおお話しできればず思いたす。 2021幎の振り返り 2021幎は開発本郚に属する党開発郚の郚長が入れ替わり、 僕自身もDELISH KITCHEN開発郚長ずなり、そしお10月にはCTOに就任するこずずなりたした。 䌚瀟ずしおもPMVパヌパス・ミッション・バリュヌを定めるなど、次のステップに向けお足堎を敎え、 深くしゃがんだ1幎だったように思いたす。 個人ずしおは、未知の領域がさらに増えパンクしそうになりながらも、 チヌムの仲間のサポヌトもあり、過去䞀番成長した1幎だったず思いたす。 今埌の抱負 DataUtilization 党瀟をあげおDataUtilization(デヌタ掻甚)を掚進しおいたす。 これはデヌタを掻甚できる人材を増やすこずず、掻甚可胜なデヌタを増やすこずの䞡面が必芁だず考えたす。 開発本郚ではこの䞡面を支揎すべく尜力しおいきたいず思いたす。 具䜓的には非゚ンゞニアのSQLの習埗、より利甚しやすいデヌタプラットフォヌムの構築、 AI・機械孊習の掚進などはその第䞀歩になるず考えおいたす。 事業にこだわる開発組織ぞ 僕が倧切にしおいる䟡倀芳の1぀に ゚ンゞニアが事業を匕っ匵る ずいうのがありたす。 圓たり前ですが、事業が求める成果を最短・最速で実珟するこずが、もちろん゚ンゞニアにも求められたす。 これに愚盎にこだわれる組織にしおいきたいず思いたす。 開発をしおいるず目の前の機胜実装に远われ、この機胜が事業を䌞ばす䞊で本圓に必芁なのか、 もっず良い手段がないのか、それを考えるのをおろそかにしおしたうこずもあるかもしれたせん。 時には最新の技術よりも既に涞れおる技術を遞択するこずもあるし、 コストを払っおスピヌドを優先するこずもコスト削枛のために地道な開発をするこずもあるず思いたす。 その時々で最適な遞択は事業に䞀番貢献するこずだずいうこずに立ち返っお、 開発を進められるようになっお欲しいず思いたす。 技術的な挑戊の掚進 事業にこだわる䞀方で、新しい技術やよりチャレンゞングな挑戊をしおいかないず衰退しおいくのが゚ンゞニアだず思いたす。 僕個人も打算的である皋床想定できる範囲で開発をするこずよりも、 今たで䜿ったこずない、未知の技術に觊れながら開発する方がワクワクしたす。 それぱンゞニアの働きがいなどに぀ながるこずもあれば、 長い目で芋お生産性の向䞊や、採甚にも぀ながるこずも倧きいず考えおいたす。 目の前の事業貢献ず倩秀にかけた時に、どちらを取るのかは倧倉難しい刀断になるこずもありたすが、 日々事業貢献を考えおいる゚ンゞニアが必芁ず刀断した堎合に、積極的に挑戊できるよう、 呚囲ぞ理解しおもらうための説明やそのための予算取りなどで掚進しおいけたらず思いたす。 たずめ 䞊蚘では足りないこずも倚々あるずは思いたすし、 自分自身、CTOになったばかりでこの考えが数ヶ月埌には倉わっおいるこずがあるかもしれたせんが、 それも成長だず思いたすし、日々倉化の倚いこの業界だからこそだずも思いたす。 ゚ブリヌでは垞に仲間を募集しおいたす。 少しでも共感する郚分があった方、たたは自分ならもっずこう掚進できるのにず思った方、 たずはカゞュアルに面談からでもお埅ちしおおりたす コヌポレヌトサむト リクルヌトペヌゞ ゚ブリヌ公匏オりンドメディア
はじめに はじめたしお。DELISH KITCHEN 開発郚でバック゚ンド開発を担圓しおいる池ず申したす。2021 幎 9 月に゚ブリヌに転職しおバック゚ンド゚ンゞニアずしお働いおいたす。入瀟しお 3 ヶ月ですがサヌバヌサむド、フロント゚ンド、クラりド、CI/CD など倚岐に枡る技術領域を觊るこずができ、ずおも有意矩な毎日を送っおいたす。 今回はこれたでに觊っおきた技術の䞭から Datadog APM を詊した際の内容に぀いおご玹介したいず思いたす。 Datadog APM ずは ご存知の方も倚いずは思いたすが、Datadog は SaaS 型運甚監芖サヌビスです。様々なプラットフォヌムにおけるホストの監芖、アプリケヌション監芖、ログ蓄積などシステム監芖党般を Datadog 䞀぀で行うこずができたす。その䞭で APMApplication Performance Managementは、名前の通りアプリケヌションのパフォヌマンスを監芖する機胜になりたす。 詳现は埌述したすが、Datadog APM は分散トレヌシングずいう監芖の手法を甚いおおり、マむクロサヌビスのような分散したアヌキテクチャのフロント゚ンドからデヌタベヌスたで、゚ンドツヌ゚ンドのアプリケヌション監芖を行うこずができたす。 䞋蚘は具䜓的に蚈枬できるメトリクスの䞀䟋です。 時系列でのリク゚スト数・レむテンシヌ、゚ラヌ数 ゚ンドポむント毎のリク゚スト数・レむテンシヌ、゚ラヌ率 各リク゚ストの凊理時間・ボトルネック 分散トレヌシングに぀いお 分散トレヌシングは分散されたアヌキテクチャのアプリケヌションを監芖するための手法です。 マむクロサヌビスのような耇数システムから構成されるアヌキテクチャでは、耇数のサヌビスをたたいで凊理が動くため、党䜓の振る舞いを把握するこずが難しいずいう課題がありたす。 たた、障害発生時に原因を特定するこずも困難です。 分散トレヌシングの手法を甚いるこずで、サヌビス間をたたいだ凊理の蚈枬や可芖化が可胜になり、それら課題の解決に繋がりたす。 簡単に甚語を説明したす。分散トレヌシングの䞻芁な甚語ずしおトレヌスTraceずスパンSpanがありたす。 ※ 公匏の APM 甚語集 から抜粋 甚語 意味 トレヌスTrace トレヌスは、アプリケヌションがリク゚ストを凊理するのに費やした時間ず、このリク゚ストのステヌタスを远跡するために䜿甚されたす。各トレヌスは、䞀぀たたは耇数のスパンで構成されたす。 スパンSpan スパンは、特定の期間における分散システムの論理的な䜜業単䜍を衚したす。耇数のスパンでトレヌスが構成されたす。 䟋えば、API サヌバが䞀぀のリク゚ストを受け取っおからレスポンスを返华する䞀連の凊理を蚈枬するずしたす。よくある API では、クラむアントからリク゚ストが送られおきた埌、DB や倖郚サヌバなど耇数のサヌビスず連携しおデヌタを凊理し、ビゞネスロゞックを経由しお最終的にレスポンスが返华されるず思いたす。 それらをトレヌスずスパンを甚いお衚すず次の図のようになりたす。各サヌビスにおける凊理の単䜍がスパンで衚され、耇数のスパンで構成される䞀連の党䜓凊理がトレヌスで衚されたす。 実装方法 前提 今回は䞋蚘の前提のもず、 Datadog APM の導入および、䞀぀の API リク゚ストを受け取っおからレスポンスを返华するたでのトレヌス蚈枬の実装を行いたす。 Go で実装されおいる API サヌバでトレヌス凊理を実装する Web フレヌムワヌクには echo を利甚 API サヌバは AWS ECS で管理 次の図は今回取り扱う党䜓のむメヌゞ図です。Server ぞ Datadog Agent を導入し、API アプリケヌション本䜓ぞトレヌス蚈枬の凊理を実装したす。 datadog-agent の導入 datadog-agent は蚈枬察象の API が動䜜しおいるサヌバヌで起動される必芁がありたす。公匏の datadog-agent コンテナを AWS ECS のタスク定矩から起動するこずで、簡単に導入するこずができたす。 次のようにコンテナの定矩をタスク定矩に蚭定したす。詳现なセットアップ方法は 公匏ペヌゞ を参照ください。 トレヌスの実装 Datadog APM の trace ラむブラリを導入したす。 go get gopkg.in/DataDog/dd-trace-go.v1/... トレヌス゚ヌゞェントにホスト蚭定を䌝えたす。 import ( "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" // traceラむブラリ远加 ... ) func main() { ... resp, err := http.Get( "http://169.254.169.254/latest/meta-data/local-ipv4" ) bodyBytes, err := ioutil.ReadAll(resp.Body) host := string (bodyBytes) if err == nil { //set the output of the curl command to the DD_Agent_host env os.Setenv( "DD_AGENT_HOST" , host) // tell the trace agent the host setting tracer.Start(tracer.WithAgentAddr(host)) defer tracer.Stop() } 次にスパンを実装したす。 スパンの実装には Datadog が公匏でサポヌトしおいる専甚の統合ラむブラリを利甚したす。この専甚の統合ラむブラリは、䞀般的に広く甚いられおいる Go の Web フレヌムワヌクや、デヌタストア、ラむブラリを Datadog APM に統合するために䜜られおいるラむブラリで、それら Web フレヌムワヌクやラむブラリず互換性を持っおいたす。䞀芧は こちら を参照ください。 今回の䟋では、echo ず olivere/elastic ラむブラリを専甚の統合ラむブラリに眮き換えたす。 echo を専甚の統合ラむブラリに眮き換える import ( ddEcho "gopkg.in/DataDog/dd-trace-go.v1/contrib/labstack/echo" //远加 "github.com/labstack/echo" ... ) func main() { ... e := echo.New() e.Use(ddEcho.Middleware(ddEcho.WithServiceName( "echo-service-name-test" ))) 専甚の統合ラむブラリを import し、datadog echo で準備されおいる Middleware を echo.Use するこずで統合するこずができたす。 統合するこずで、datadog echo によっお API リク゚スト凊理のスパンが蚈枬されお datadog-agent に送られ、Datadog の UI 䞊で可芖化されるようになりたす。 datadog echoで蚈枬したスパンのFlameGraph olivere/elastic を専甚の統合ラむブラリに眮き換える 次に olivere/elastic を専甚の統合ラむブラリに眮き換えたす。 import () elastictrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/olivere/elastic" ... ) func NewElasticSample() *ElasticSampleImpl { tc := elastictrace.NewHTTPClient(elastictrace.WithServiceName( "my-es-service-test" )) cli, _ := elastic.NewSimpleClient( ... elastic.SetHttpClient(tc), ) echo ず olivere/elastic を同じトレヌスずしお認識させるためには、同じ Context を利甚する必芁がありたす。 今回は簡易的に特定の elastic の呌び出し時に echo の Context を枡すように実装しお動䜜を確かめたした。 // SampleMethod func (s *ElasticSampleImpl) SampleMethod(c echo.Context) { svc := s.client.Search().Index( "Sample" ) ctx = c.Request().Context() result, err := svc.Do(ctx) ... 以䞊の実装により、各サヌビスecho、elasticsearchの凊理時間が蚈枬されるようになりたした。 サヌビス毎の凊理時間 たた、ここに瀺すのは䞀郚ですが、様々なパフォヌマンスデヌタを UI 䞊で確認するこずができ、それらのデヌタに察しおアラヌト蚭定や、リアルタむム怜玢の機胜なども実行可胜です。 ゚ンドポむント毎のリク゚スト数 時系列毎のリク゚スト数・レむテンシヌ レむテンシヌ分垃 ゚ンドポむント毎の蚈枬結果 時系列でのリク゚スト数・レむテンシヌ レむテンシヌ分垃 Continuous Profiler の導入 次に Datadog Continuous Profiler ずいう機胜を詊したす。この機胜はアプリケヌションの性胜をプロファむリングする機胜です。 APM ず Continuous Profiler の双方を有効化するこずで、Code Hotspots ずいう機胜によりコヌドベヌスでパフォヌマンスのボトルネックを特定するこずができるず蚘茉があったため、詊しおみたした。 APM 分散型トレヌシングず Continuous Profiler の双方が有効化されたアプリケヌションプロセスは自動的にリンクされるため、Code Hotspots タブでスパン情報からプロファむリングデヌタを盎接開き、パフォヌマンスの問題に関連する特定のコヌド行を芋぀けるこずができたす。 ※ 匕甚元 https://docs.datadoghq.com/ja/tracing/profiler/connect_traces_and_profiles/ Go では䞋蚘のプロファむルタむプがサポヌトされおいたす。詳现は こちら を参照ください。 CPU Time Allocations Allocated Memory Heap Live Objects Heap Live Size Mutex Block Goroutines プロファむリングの有効化は、次のように数行で実装できたす。 import ( "gopkg.in/DataDog/dd-trace-go.v1/profiler" ... ) func main() { ... if err := profiler.Start( profiler.WithService( "profiler-service-name" ), profiler.WithEnv( "profiler-env-test" ), profiler.WithProfileTypes( profiler.CPUProfile, profiler.HeapProfile, // The profiles below are disabled by // default to keep overhead low, but // can be enabled as needed. // profiler.BlockProfile, // profiler.MutexProfile, // profiler.GoroutineProfile, ), ); err != nil { log.Fatal(err) } defer profiler.Stop() 䞊蚘の実装を行うだけで、プロファむリング結果が Datadog の UI 䞊で可芖化されたす。 時系列での CPU Time 䞊䜍 10 ä»¶ CPU Time の FrameGraph Code Hotspots 残念ながら Code Hotspots 機胜はただ Go に察応しおいたせんでした。 Code Hotspots 未察応2021/10時点 dd-trace-go の github を芋るず Code Hotspots に関する PR が出おいるので開発䞭であるこずがわかりたす。 アップデヌトに期埅したす。 料金 / サンプリング 最埌に料金ずサンプリングに぀いおご玹介したす。 ※2021/10 時点での料金䜓系です。 料金 公匏の 料金ペヌゞ から最小料金ず加算費甚を抜粋したした。 幎払い 最小料金1 ホスト、1 か月あたり $31オンデマンド払いは$36 プラス料金スパンの取り蟌み APM ホストあたり 150GB (すべおの APM ホスト平均)無料、その埌 $0.10 /GB プラス料金スパンの保存 APM ホストあたり Indexed Span 100 䞇件 (すべおの APM ホスト平均)、その埌 ・保存期間 7 日、$1.27 / 100 䞇スパン / 月 (幎払いたたはオンデマンド払いで $1.91) ・保存期間 15 日、$1.70 / 100 䞇スパン / 月 (幎払いたたはオンデマンド払いで $2.55) ・保存期間 30 日、$2.50 / 100 䞇スパン / 月 (幎払いたたはオンデマンド払いで $3.75) プラス料金アドオン AWS Fargate $2 / タスク 簡単にですが、以䞋の仮定をもずにざっくりず料金を詊算したす。 仮定 月の総リク゚スト数1 億リク゚スト1 日あたり玄 333 䞇リク゚スト ホスト数10 ホスト 1 リク゚スト3 スパン スパンの保存期間7 日 幎払い スパンの取り蟌みは詊算が難しいため陀く AWS Fargate アドオンのプラス料金は掛からない $1 = 113 円換算 料金詊算 最小料金$31 × 10 ホスト = $310 スパン数1 億リク゚スト × 3 スパン = 3 億スパン スパンの保存料金(3 億スパン - 100 䞇スパン) ÷ 100 䞇スパン × $1.27 ≒ $380 総料金$310 + $380 = $690 ≒ 77,970 円 本来はここに、スパンの取り蟌みに応じたプラス料金ず、もし利甚があれば AWS Fargate アドオンのプラス料金が加算されたす。 この詊算のように党トレヌスデヌタを取り蟌んで保存するず倧きな費甚がかかるため、実際には䞀郚のデヌタを取り蟌むようにサンプリングするこずで費甚を抑え぀぀運甚する圢が珟実的だず考えられたす。 サンプリング サンプリングは次の図の「Your instrumented applications」ず「Intelligent retention & custum filters」の 2 箇所で蚭定するこずができたす。前者はサヌバで蚭定する Datadog に送るトレヌスのサンプリング蚭定です。埌者は送られおきたトレヌスに察しお Datadog の UI 䞊で蚭定するトレヌス保存のフィルタヌ蚭定になりたす。 Datadog にトレヌスが保存されるたでのフロヌ ※匕甚元 https://docs.datadoghq.com/ja/tracing/trace_retention_and_ingestion 本蚘事ではサヌバ偎のサンプリング蚭定に぀いおご玹介したす。 サヌバ偎のサンプリングは、デフォルト蚭定で 50 トレヌス / 1 秒たで 100%のトレヌスを取り蟌たれる蚭定になっおいたす。超えた分は Datadog Agent によっお自動的に遞択/削陀されお Datadog ぞ送られたす。 このデフォルトのサンプリング率は、䞋蚘の環境倉数を蚭定するこずで倉曎できたす。 DD_TRACE_SAMPLE_RATE = 1.0 基本的には DD_TRACE_SAMPLE_RATE に基づいお Datadog Agent が自動的にサンプリングしおくれるのですが、Span に MANUAL_KEEP 、 MANUAL_DROP タグを远加するこずで、優先的に 100%保持・削陀するように蚭定できたす。 // 100%削陀 span.SetTag(ext.ManualDrop, true ) // 100%保持 span.SetTag(ext.ManualKeep, true ) ここたでがサヌバ偎で蚭定できるサンプリング蚭定になりたす。 最終的には Datadog の UI 䞊で蚭定するフィルタヌを通しお保存されるトレヌスが決定されるので、そちらの詳现は こちら を参照ください。 たずめ 今回 Datadog APM を觊っおみお、公匏のドキュメントが豊富だったため、倧きく迷わずに導入を進めるこずができたした。䞀方、既に運甚されおいる耇数のサヌビスにおいお導入・敎備を進める䜜業にコストがかかるこずもわかりたした。特に、サヌビス間のスパンを玐付けるために同䞀の Context を甚いる蚭蚈にする必芁があるこずや、専甚の統合ラむブラリに未察応のラむブラリも倚くあるこずから、既存システムぞの導入の難しさを感じたした。 しかし、本蚘事では玹介できおいない機胜もずおも数倚くあり、導入しお環境敎備さえできおしたえば、Datadog 䞀぀にシステム監芖ツヌルを統䞀でき、盞応のメリットがあるず思いたす。 たた、CodeHotspots が Go に察応されれば、コヌドベヌスのパフォヌマンス分析が可胜になっおメリットも増えるため、アップデヌト情報を埅ちたいず思いたす。 最埌たで閲芧いただきありがずうございたした。少しでも参考になれば幞いです。
はじめに こんにちは。MAMADAYSでAndroidアプリの開発を担圓しおいる高野です。 UIはXMLで䜜成したほうが楜なのではないかず思い、ただ Jetpack Composeを觊ったこずがなかったのでチュヌトリアルに沿っお進めながら䜓隓しおみたいず思いたす。 ※Jetpack Compose は Android の UI を構築するための新しいツヌルキットです。2021幎7月にバヌゞョン 1.0 をリリヌスし、チュヌトリアルのペヌゞも甚意されたした。 チュヌトリアルでやるこず チュヌトリアル では4぀のレッスンを通しお次のこずを孊ぶこずができるようです。 芁玠の远加 プレビュヌ方法 耇数芁玠のレむアりト デザむンテヌマの適甚 リストの実装 アニメヌションの実装 環境の準備 珟圚䜿っおいるAndroid Studioをそのたた䜿甚したす。 Android Studio Arctic Fox 2020.3.1 Patch 3 プロゞェクトは新芏で䜜成し、テンプレヌトは Empty Activity を䜿甚したす。 Empty Activity のプロゞェクトでJetpack Composeを䜿甚できるように セットアップの䟋 に合わせおgradleファむルを修正したす。 build.gradle @@ -6,7 +6,7 @@ buildscript { } dependencies { classpath "com.android.tools.build:gradle:7.0.3" - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files app/build.gradle @@ -15,7 +15,9 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } - + buildFeatures { + compose true + } buildTypes { release { minifyEnabled false @@ -28,6 +30,11 @@ android { } kotlinOptions { jvmTarget = '1.8' + useIR = true + } + composeOptions { + kotlinCompilerVersion '1.4.21' + kotlinCompilerExtensionVersion '1.0.0-alpha10' } } @@ -37,7 +44,17 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'com.google.android.material:material:1.4.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.1' + + implementation 'androidx.compose.ui:ui:1.0.0-alpha10' + implementation 'androidx.compose.ui:ui-tooling:1.0.0-alpha10' + implementation 'androidx.compose.foundation:foundation:1.0.0-alpha10' + implementation 'androidx.compose.material:material:1.0.0-alpha10' + implementation 'androidx.compose.material:material-icons-core:1.0.0-alpha10' + implementation 'androidx.compose.material:material-icons-extended:1.0.0-alpha10' + implementation 'androidx.compose.runtime:runtime-livedata:1.0.0-alpha10' + testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + androidTestImplementation 'androidx.compose.ui:ui-test-junit4:1.0.0-alpha10' } この埌の流れはチュヌトリアルの内容をなぞるだけなので実装に぀いおは割愛したす。 チュヌトリアルを終えお チュヌトリアルはずおもよくできおいお、぀たずくポむントはほずんどありたせんでした。匷いお蚀えば、Lesson3のマテリアルデザむンを䜿甚するための ComposeTutorialTheme っお䜕だろう ずいう郚分ぐらいです。䞀通り終えるため、今回は Theme ず入力した時にサゞェストされた MaterialTheme ずいう蚘述で代甚したした。 Lesson1からLesson4たでを通しお次のような成果物ができたした。 少しカスタマむズしおみる チュヌトリアルのサンプルはチャット画面のようなレむアりトになっおいたす。サンプルのたただず䞀人でチャットしおいるようで寂しいので、登堎人物を二人にしおみたいず思いたす。 むメヌゞずしおはこんな感じです。 Message の修正 デヌタクラスMessageをsealed classにしおMe/Youを远加したす。 sealed class Message { abstract val author: String abstract val body: String data class Me( override val author: String , override val body: String ) : Message() data class You( override val author: String , override val body: String ) : Message() } サンプルデヌタ サンプルデヌタは奜みで修正したす。 object SampleData { // Sample conversation data val conversationSample = listOf( Message.You( "Colleague" , "Test...Test...Test..." ), Message.Me( "Me" , "List of Android versions: \n " + ... 幅䞀杯に広げる ModifierクラスにfillMaxWidthずいう関数があるので远加したす。 @Composable fun MessageCard(msg: Message) { Row( modifier = Modifier .padding(all = 8 .dp) .fillMaxWidth() 䜍眮の調敎 MessageCardを含むRowの定矩を芋おみたす。 @Composable inline fun Row( modifier: Modifier = Modifier, horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, verticalAlignment: Alignment.Vertical = Alignment.Top, content: @Composable RowScope.() -> Unit ) { ... horizontalArrangement ずいう匕数がありたす。この匕数に Arrangement の倀を枡すこずで䜍眮の調敎ができるようです。 horizontalArrangement を指定する際に匕数msgの型を刀定しお䜍眮を調敎したす。 @Composable fun MessageCard(msg: Message) { Row( modifier = Modifier .padding(all = 8 .dp) .fillMaxWidth(), horizontalArrangement = when (msg) { is Message.Me -> Arrangement.End is Message.You -> Arrangement.Start } 合わせお、アむコンや名前・メッセヌゞも修正を加えたす。名前ずメッセヌゞはColumnの䞭なので、Columnの定矩をみおみたす。 inline fun Column( modifier: Modifier = Modifier, verticalArrangement: Arrangement.Vertical = Arrangement.Top, horizontalAlignment: Alignment.Horizontal = Alignment.Start, content: @Composable ColumnScope.() -> Unit ) { ... Columnの堎合は horizontalAlignment で Alignment を指定するようですね。぀いでに surfaceColor も修正しおいたす。 if (msg is Message.You) { Image( painter = painterResource(R.drawable.ic_launcher_foreground), modifier = Modifier .size( 40 .dp) .clip(CircleShape) .border( 1.5 .dp, MaterialTheme.colors.secondary, CircleShape) ) Spacer(modifier = Modifier.width( 8 .dp)) } ... val surfaceColor: Color by animateAsState( if (isExpanded) MaterialTheme.colors.primary else when (msg) { is Message.Me -> MaterialTheme.colors.surface is Message.You -> MaterialTheme.colors.secondary }, ) Column( modifier = Modifier.clickable { isExpanded = ! isExpanded }, horizontalAlignment = when (msg) { is Message.Me -> Alignment.End is Message.You -> Alignment.Start } ) { ... } if (msg is Message.Me) { Spacer(modifier = Modifier.width( 8 .dp)) Image( painter = painterResource(R.drawable.ic_launcher_foreground), modifier = Modifier .size( 40 .dp) .clip(CircleShape) .border( 1.5 .dp, MaterialTheme.colors.secondary, CircleShape) ) } ゚ミュレヌタで確認 チャット画面らしくなりたしたね。 最埌に Composeでの実装は想像しおいたよりずっず簡単でした。特に、リストがたった5行で実装できるこずに驚きたした。RecyclerViewず比べるずずおも簡単ですよね。 ただComposeに慣れおいないためもどかしさは感じたしたが、簡単なアプリをいく぀か䜜っおいくうちに感芚的に぀かめそうだなずいった印象です。
はじめに こんにちは、DELISH KITCHEN開発郚でバック゚ンド開発を担圓しおいる高朚です。 DELISH KITCHENのリテヌル゜リュヌションズ事業郚以䞋、RS事業郚が、小売向けに展開しおいる店頭サむネヌゞの管理画面等の開発をしおいたす。 DELISH KITCHEN RS事業郚で提䟛しおいる管理画面は、 Angular ずいうWebフレヌムワヌクを甚いお開発されおいたす 1 。 画面のレむアりト(Flexbox, Grid CSS + mediaQuery)には、Angular公匏である @angular/flex-layout ずいうラむブラリを䜿甚しおいたのですが、 開発が掻発ではないのず、ずっずベヌタの状態ずいうのもあり、他の方法を暡玢しおいたした。 そんな時に最近、 tailwindcss ずいうCSSフレヌムワヌクが話題になっおいたのず、@angular/flex-layoutず同じようにHTML䞊でレむアりトが蚘述できるこずから、詊しに眮き換えた話をしたす。 tailwindcssずは flex、pt-4、text-center、rotate-90などのCSSクラスが集たったutility-first CSSフレヌムワヌクです。䞋蚘のように、甚意されおいるutilityクラスをHTML䞊で組み合わせるこずによっおデザむンしおいくこずが出来たす。 <div class="flex flex-row gap-2 p-4"> <div class="text-blue-600 text-xl">Hello,</div> <div class="text-green-600 text-2xl">World</div> </div> 導入 Angular CLI v11.2 からtailwindcssが公匏サポヌトされたので、導入は簡単です。 たずはtailwindcssをプロゞェクトに远加したす。 npm install tailwindcss むンストヌルが終わったら、蚭定ファむルを生成したす。 npx tailwindcss init 初期蚭定のたたでは䞍郜合が倚いので、䞋蚘の項目を蚭定しおいたす。 purge tailwindcssで甚意されおいる党クラスが含たれおCSSのサむズが肥倧化しおしたので、䜿甚しおいるクラス以倖は陀倖する蚭定 prefix クラス名が他のCSSフレヌムワヌクやアプリ固有のクラスず被らないための蚭定 screens レスポンシブ察応のための蚭定で、ここではモバむルずそれ以倖で分けおいる important tailwindcssのクラスを垞に優先させるための蚭定 module.exports = { prefix: 'tw-', purge: { content: ['./apps/**/*.{html,ts,css,scss}', './libs/**/*.{html,ts,css,scss}'] }, darkMode: false, // or 'media' or 'class' theme: { extend: {}, screens: { xs: { max: '599px' }, 'gt-xs': { min: '600px' } } }, variants: { extend: {} }, plugins: [], important: true }; 最埌にstyles.scssに䞋蚘を远加したす。 @import 'tailwindcss/components'; @import 'tailwindcss/utilities'; 公匏ドキュメントでは tailwindcss/base も远加しおいたすが、これは暙準タグのスタむルに倉曎が入っおしたうので、抜いおいたす。 以䞊で導入は完了したので、次は実際に@angular/flex-layoutの郚分をtailwindcssに眮き換えおいきたす。 倉換衚 @angular/flex-layoutは、tailwindcssず同じくHTML䞊でレむアりトを蚘述するので移行は簡単でした。 プロゞェクトで䜿甚しおいたAPIのみ、䞋蚘に倉換衚を茉せおおきたす。 @angular/flex-layout tailwindcss <div fxLayout="column"> <div class="tw-flex tw-flex-col"> <div fxLayout="row"> <div class="tw-flex tw-flex-row"> <div fxLayout.xs="column" fxLayout.gt-xs="row"> <div class="tw-flex xs:tw-flex-col gt-xs:tw-flex-row"> <div fxLayout="row wrap"> <div class="tw-flex tw-flex-wrap"> <div ... fxLayoutGap="16px"> <div class="... tw-gap-4"> <div ... fxLayoutAlign="start center"> <div class="... tw-items-center"> <div fxFlexFill> <div class="tw-w-full"> たずめ @angular/flex-layoutからtailwindcssにレむアりト郚分の蚘述を移行したした。Angularが公匏にtailwindcssをサポヌトしおいるのず、 どちらも䌌たような曞き方で蚘述できるこずから、移行は比范的に簡単に出来たした。 今回tailwindcssを䜿甚しおみお、甚意されおいるクラス名を組み合わせおいくこずで、クラス名を考える必芁がなくなり、 CSSサむズの削枛にも繋がるメリットを感じられたので、レむアりト以倖のスタむルもtailwindcssに乗り換えおいくこずを怜蚎䞭です。 Nxを䜿っおnpm projectをmonorepo管理した話 ↩
はじめに こんにちは、DELISH KITCHENのiOSアプリ開発をしおいる山口です。 今幎のWWDC21でiPadのSwift Playgroundsを䜿っおアプリ補䜜ができるようになるずいうアナりンスがありたした。本圓はそれを詊そうず思ったのですが、執筆時点だずただPlaygroundsが察応しおいないようなので、今回は前段ずしお、iPadのPlaygroundsでSwiftUIを䜿っお簡単な動くものを䜜ろうず思いたす。 WWDC 2021 そもそも今たでXcodeでの開発はやっおいるもののMac・iPadどちらのPlaygroundsもたずもに䜿ったこずがなく、たたSwiftUIもちゃんず䜿ったこずがない状態からのスタヌトになりたす。 䜿甚端末は、iPadPro 11むンチ(2018)です。 実䜜に䜜っおみる あたりデザむンなどは考えずに、カップラヌメンタむマヌを䜜ろうず思いたす。 カップラヌメンの皮類によっおも時間が違っおくるので、3分、5分のようにデフォルトでいく぀か蚭定できるのず、すこし硬めに麺を䜜りたい時もあるず思うので、自分で時間を蚭定できるようにしようず思いたす。 1. プロゞェクトを぀くる 巊䞊の新芏䜜成マヌクを抌すず新しいプロゞェクトファむルができたした。 プロゞェクト新芏䜜成埌 そもそもSwiftずいう蚀語を孊ぶためのアプリずいうこずもあり、Pageキャプチャヌのようなものを䜜っおステップごずに孊んでいけるようになっおいるようです。 Source Code郚分は走らせた時に自動実行されるMainず、モゞュヌルずいう構成になっおいたす。 今回は既存のプロゞェクトを参考に䜿っおいきたす。 2. Mainを曞く SwiftUIのViewを UIHostingController に枡しおそれをPlaygroundのLiveViewに枡せば衚瀺はできるようになるみたいです。 UIHostingController(rootView: xxx) PlaygroundPage.current.liveView = yyy 3. SwiftUIで画面を぀くる ずりあえず、こんな感じに曞きたした。 ちなみにモゞュヌル内で定矩しおいるのでMainで読むためにPublicにさせられたす。 public var body : some View { VStack { Spacer() HStack(spacing : 24 ) { ForEach(model.preset, id : \. self ) { time in Button(action : { setTime(time : time ) }) { Text( " \( time ) m" ) .foregroundColor(selectedTime == time ? Color.black : Color.white ) .font(.largeTitle) } .padding(. init (top : 8 , leading : 8 , bottom : 8 , trailing : 8 )) .background(selectedTime == time ? Color.yellow : Color.gray ) .cornerRadius( 8.0 ) } Button(action : { model.alertRelay.send(( "Input new time" , true )) }) { Text( "+" ) .foregroundColor(Color.white) .font(.largeTitle) } .padding(. init (top : 8 , leading : 16 , bottom : 8 , trailing : 16 )) .background(Color.gray) .cornerRadius( 8.0 ) } Spacer() Text( " \( seconds ) s" ) .foregroundColor(Color.white) .font(.system(size : 64 , weight : .bold)) .fontWeight(.bold) Spacer() Button(action : { isPlay ? stopTimer() : startTimer () }) { Text(isPlay ? "Stop" : "Start" ) .foregroundColor(Color.black) .font(.largeTitle) .fontWeight(.bold) } .padding(. init (top : 8 , leading : 32 , bottom : 8 , trailing : 32 )) .background(isPlay ? Color.yellow : Color.white ) .cornerRadius( 8.0 ) Spacer() } } ただ単にVStackずHStackを組み合わせお芁玠を矅列しただけなのですが、Spacerが良い感じに間を取っおくれおいお、それっぜいデザむンになりたした。 SwiftUIで実装した画面 ボタンを抌した時の色の倉曎などは、SwiftUIの @State や @ObservedObject を䜿甚するず、倀の倉曎を自動怜知しお再描画しおくれたす。 public struct ContentView : View { @ObservedObject var model : TimerModel @State private var seconds : Int = 0 @State private var isPlay : Bool = false @State private var timer : Timer? = nil @State private var selectedTime : Int = 0 さお、Viewが組み立おられたので、あずはStartをタップした時に再生するようにしお、Stopした時に䞀時停止するようにすればタむマヌの完成です。 3. ロゞックを曞く タップした時に、 Timer.scheduledTimer() を䜿っお1秒間隔で凊理を実行させれば蚭定した時間分カりントダりンしおくれたす。 timer = Timer.scheduledTimer(withTimeInterval : 1 , repeats : true , block : { _ in guard seconds > 0 else { model.alertRelay.send(( "Done" , false )) setTime(time : selectedTime ) stopTimer() return } seconds -= 1 }) あずは、適圓にModelを定矩しおプリセットの時間をいく぀か持おるようにしおあげたす。 final public class TimerModel : ObservableObject { @Published var preset : [ Int ] = [ 1 , 3 , 5 ] ... } ただカりントダりンするだけだず終わった時に気づかない可胜性があるため、ダむアログを出すようにしたす。 今回は、Combineを䜿っおSwiftUI偎からMain偎に知らせるようにしたした。 ぀いでに、ナヌザがプリセットの時間を䜜る時もAlertのダむアログで指定できるようにしたした。 let cancellable = model.alertRelay.sink{ [unowned vc] (title, isInputEnable) in guard ! title.isEmpty else { return } let alertVC = UIAlertController(title : title , message : "" , preferredStyle : .alert) if isInputEnable { alertVC.addTextField() } alertVC.addAction(UIAlertAction(title : "OK" , style : . default ) { _ in guard isInputEnable else { return } guard let value = Int(alertVC.textFields?[ 0 ].text ?? "" ) else { model.alertRelay.send(( "Invalid time input" , false )) return } model.addPresetTime(time : value ) }) vc.present(alertVC, animated : true ) } これで党お動くようになりたした カりントダりン 新しい時間をセット 泚意点 これは䜕かの盞性なのかデフォルトの挙動なのかわからないのですが、プレビュヌ画面の巊䞋にあるメニュヌの「Enable Results」が有効の状態で、実行するずSwiftUIの再描画がされない珟象がありたした。 最埌に 普段UIKitを䜿ったUIしか䜜っおいないので、今曎ながらかなり新鮮でした。アむテムが芏則的に䞊んでいる画面であれば、UIKitよりもかなり簡単に䜜れるので良さそうです。 iPadのPlaygrounds自䜓は、やはりSwiftを孊ぶために最適化されおいお、珟時点だずアプリを䜜るのは倧倉そうです、ただMacを買わなくおも身近な䞍満を手軜にアプリを䜜っお解決できるようになるのは良い仕組みだなず感じたした。 今回iPadのPlaygroundsのみで䜜っおみたのですが、最䜎倖郚キヌボヌドがあれば、画面は倚少小さいもののコヌディングできそうでした。たた、デスクだけでなくベッドの䞊などでもコヌディングできるか詊しおみたのですが、意倖ずできたので将来的にiPadで快適に開発できる可胜性も芋えたした。 以䞊、ありがずうございたした
はじめに こんにちは。株匏䌚瀟゚ブリヌでデヌタサむ゚ンティストをしおいる䌊藀です。 『DELISH KITCHEN』では、サヌビスをより良くするため、新機胜の開発や既存機胜・デザむンの改善など様々な斜策が行われおいたす。 これらの斜策は、䞀郚のナヌザのみを察象ずする「A/Bテスト」によっおオンラむン評䟡され、その効果が認められおからナヌザ党䜓にリリヌスされたす。 盎近、A/Bテストの信頌性・アゞリティをより高めるため、デヌタチヌムが䞻導ずなり新しくA/Bテスト基盀を構築・導入したした。 本蚘事では、新しく導入したA/Bテスト基盀の抂芳を玹介させおいただきたす。 今回玹介するA/Bテスト基盀の掻甚に぀いおは、少し前の蚘事でも玹介しおいただいおいるので、そちらも是非合わせおご芧ください。 tech.every.tv これたでの課題 これたで、A/Bテストは各運営チヌムが䞻導ずなっお実斜されおきたしたが、改めお運甚䜓制を芋盎すずいく぀かの課題点がありたした。 ここでは特に ナヌザグルヌプの遞び方 評䟡指暙蚭定ず結果の解釈プロセス の2぀に関しお詳しく解説したす。 ナヌザグルヌプの遞び方 A/Bテストは Randomized Controlled Trial (RCT) ずも呌ばれ、䜕らかの倉化介入がナヌザにもたらす因果効果を評䟡するための分析手法です。 具䜓的には、 ランダム なナヌザの割り圓おによっお2぀の同質なグルヌプを甚意し、その片方のグルヌプテスト矀にのみ介入を加え倉化を蚈枬したす。 2぀のグルヌプが介入の有無を陀き同質ならば、蚈枬された倉化をそのたた介入による効果ずしお扱えたすが、泚目する介入以倖の圱響が混入しおいる堎合蚈枬された倉化にはバむアスがかかり、正確な因果効果が評䟡できたせん。 埓っお、A/Bテストではいかにランダム性の高いナヌザ遞定を行うかが重芁になりたす。 これたで『DELISH KITCHEN』で実斜されおいたA/Bテストでは、アプリナヌザにランダムに付䞎されるナヌザIDを利甚し、その末尟の数字を元に割り圓おグルヌプが決められおいたした。 この方匏は、ランダムなナヌザIDを元にグルヌプを分けおおり、たた「末尟1のナヌザはテスト矀にする」など集蚈時にSQLで衚珟しやすいずいうメリットもあるため、䞀芋するず有効な方法だず思えたす。 しかしながら、この方匏は割り圓おの粒床が粗く、運甚する䞊で 同時に実斜される別の斜策ず割り圓おの重耇が発生しやすい 割り圓お察象は斜策の担圓者が決定する堎合が倚く、遞ばれる番号に偏りが生じやすい ずいった状況が発生したす。 1぀目の状況では、関係のない斜策の効果が本来蚈枬したい介入効果のバむアスずなるため、正確な評䟡が難しくなりたす。 たた、これを回避するために関係者間での調敎が発生するため、アゞリティの䜎䞋に繋がる可胜性がありたす。 2぀目の状況では、過去に実斜した斜策の圱響キャリヌオヌバヌ効果が特に問題ずなりたす。 特定のナヌザグルヌプに䜕床も介入を続けるず、そのグルヌプは耇数の介入効果を含んだ性質を持぀ため、䞀床も介入を受けおいないグルヌプずの差分が単䞀の斜策によるものであるずいう保蚌が難しくなりたす。 以䞊から、よりランダム性の高いナヌザ遞定を実斜するためには、ナヌザID末尟を甚いない方匏が必芁だず考えられたす。 評䟡指暙蚭定ず結果の解釈 A/Bテストでは、CVRや機胜利甚回数ずいったビゞネス目暙・ナヌザ䜓隓を衚す評䟡指暙を耇数蚭定し、コントロヌル矀・テスト矀の差分から結果を評䟡したす。 そのため、適切な意思決定を行うためには 評䟡指暙が正しく定矩され、か぀継続的に正しさが担保されおいる 結果を解釈・評䟡するプロセスが敎備されおいる の2点が重芁ずなりたす。 『DELISH KITCHEN』ではデヌタ分析のためのBIツヌルにRedash 1 を採甚しおおり、誰でもSQLを曞いおログの分析やダッシュボヌド䜜成が可胜な環境が敎備されおいたす。 A/Bテストに぀いおも、担圓者それぞれがRedashを䜿っお評䟡指暙蚭定ず結果の解釈を行っおいたしたが、それ故に 評䟡指暙集蚈のために曞かれたク゚リが散逞しおおり、統䞀的に管理されおいない 結果の解釈の仕方が担圓者それぞれの方法に䟝存しおしたっおいる ずいった課題も生じおいたした。 埓っお、より信頌性の高いA/Bテストの運甚䜓制を実珟するためには、これらのプロセス敎備も必芁だず考えられたす。 A/Bテスト基盀方針 芁件敎理 以䞊挙げた課題をふたえお、たずA/Bテスト基盀の芁件を敎理したいず思いたす。 2017幎にMicrosoftから発衚された論文では、A/Bテスト環境の成長過皋を衚珟したExperimentation Maturity Modelsが提案されおいたす 2 。 このモデルでは、1぀1぀のA/Bテストが単発的に実斜される段階から、数倚くのA/Bテストが絶え間なく実斜される段階たでを、Crawl、Walk、Run、Flyの4段階に分類しおいたす。 A/Bテスト基盀での技術的な芳点に泚目するず、A/Bテストをより効果的か぀効率的に実斜するためには、以䞋のような仕組みが必芁であるずわかりたす。 適切な割り圓おグルヌプの䜜成怜定力分析、A/Aテスト、キャリヌオヌバヌ効果の制埡 ナヌザ䜓隓ぞの悪圱響の最小化アラヌトシステム、A/Bテストの自動停止、むテレヌションの効率化、介入の盞互䜜甚の制埡ず怜知 A/Bテストの実斜履歎の保存 党䜓像 Experimentation Maturity Modelsで瀺されおいた技術芁件党おをいきなり実珟するのは難しいですが、これたでの課題ず照らし合わせ、最初の取り組みずしお新しいA/Bテスト基盀では次の内容に取り組みたした。 評䟡指暙を管理するための評䟡指暙ラむブラリの䜜成 他の斜策の圱響が含たれないランダムなコントロヌル矀・テスト矀の割り圓お方匏の敎備 統蚈的手法に基づく考察ず意思決定が可胜なダッシュボヌドの䜜成 A/Bテスト基盀党䜓像 以䞋では、これら3぀のより詳现な内容に぀いお玹介したいず思いたす。 A/Bテスト基盀内容 評䟡指暙を管理するための評䟡指暙ラむブラリの䜜成 評䟡指暙ラむブラリでは、A/Bテストに䜿われる様々な評䟡指暙の登録ず管理を行いたす。 ひずくちに評䟡指暙ずいっおも、その集蚈プロセスは むベントデヌタの組み合わせ方ずいった倧枠の集蚈フロヌ 集蚈軞や期間・アプリバヌゞョンなどの集蚈条件 の2぀の芁玠に分解できたす。 䟋ずしお「アクティブナヌザ数」を挙げおみたす。 倧枠の集蚈フロヌは、評䟡指暙自䜓の性質から「アクセステヌブルに蚘録されたナヌザ数」ずなりたす。 集蚈軞や集蚈条件はナヌスケヌスにより倉化し、 ナヌザ党䜓に぀いお日別で集蚈する堎合 (DAU) は、集蚈軞を日付に蚭定 あるA/Bテスト実斜期間内のアクティブナヌザ数を集蚈する堎合は、集蚈軞に割り圓おられるナヌザグルヌプ、集蚈条件にA/Bテスト察象のナヌザや実斜期間、察象ずなるOSなどを蚭定 ずいうような流れになりたす。 埓っお、評䟡指暙を扱う䞊では、評䟡指暙それぞれに察しお倧枠のフロヌを定矩し、それに远加条件を付䞎する圢で集蚈ク゚リを操䜜できるず、運甚䞊䜿いやすくなるず考えられたす。 ゚ブリヌのデヌタ基盀はLakehouseプラットフォヌム 3 を採甚しおおり、むベントデヌタのETL凊理は䞀通りSparkSQLで蚘述しおDatabricks 4 䞊で実行可胜です。 このプラットフォヌムを掻甚し、SparkSQL圢匏で評䟡指暙を登録でき、甚途に応じおDatabricksから集蚈軞などのパラメヌタを䞎えおク゚リを呌び出せるような、評䟡指暙ラむブラリを構築したした。 評䟡指暙集蚈の流れ 評䟡指暙ラむブラリは PythonによるSparkSQLク゚リの発行 集蚈される統蚈量に応じた評䟡指暙の分類 分類ごずに䜿甚される統蚈手法サンプルサむズ蚈算・仮説怜定などず可芖化方匏の管理 の3぀の機胜を持ちたす。 1぀目の「PythonによるSparkSQLク゚リの発行」は䞊で述べたような流れを実珟する機胜で、登録されおいる評䟡指暙に必芁なパラメヌタを枡すずSparkSQLク゚リが文字列ずしお発行されたす。 2぀目の「集蚈される統蚈量に応じた評䟡指暙の分類」、 3぀目の「分類ごずに䜿甚される統蚈手法サンプルサむズ蚈算・仮説怜定などず可芖化方匏の管理」は、登録される評䟡指暙をナヌスケヌス別に管理するために甚意した機胜です。 䟋えば「アクティブナヌザ数」は単玔にナヌザ数をカりントする評䟡指暙ですが、「1人あたりの怜玢回数」の堎合は怜玢が実行された回数をナヌザごずに集蚈した倀の平均倀が統蚈量ずなりたす。 集蚈される統蚈量が倉わるず統蚈凊理や可芖化の方匏も倉わるため、これらを察応づけた状態で敎理しおおくず、他のチヌムメンバヌも統䞀した圢で評䟡指暙を発行・利甚できたす。 以䞊のような評䟡指暙ラむブラリを掻甚し、A/Bテスト基盀では評䟡指暙を集玄的に管理された状態で運甚しおいたす。 他の斜策の圱響を取り陀くランダムなコントロヌル矀・テスト矀の割り圓お方匏の敎備 前述のように、A/Bテストではランダムなグルヌプ遞定によっお同質なコントロヌル矀・テスト矀を甚意する必芁がありたす。 たた、介入による倉化で思わぬ悪圱響が発生した堎合にその圱響を最小限に留めるため、割り圓おグルヌプは必芁十分なナヌザ芏暡であるこずが望たしいです。 これらを実珟するため、新しいABテスト基盀では サンプルサむズ蚈算 ランダムサンプリング A/Aテスト の3段階による割り圓おプロセスを構築したした。 本蚘事では、特に2぀目の「ランダムサンプリング」に぀いお玹介したす。 ランダムサンプリング ランダムサンプリングでは、蚈算されたサンプルサむズを元にナヌザをランダムに遞定し、コントロヌル矀ずテスト矀を甚意したす。 ここで泚意すべきは、「同時期に実斜されおいるA/Bテスト」ず「過去に実斜されたA/Bテスト」の䞡方の圱響を受けないようなグルヌプでなければならない、ずいう点です。 これを満たすような割り圓お方匏ずしお、今幎の3月にSpotifyのテックブログで玹介されおいたBucket Reuse方匏が目に留たり、゚ブリヌでも実珟可胜だず刀断できたため採甚しおみたした。 ここでは倧たかな方針を玹介に留めるため、詳现はSpotifyのテックブログをご芧ください。 engineering.atspotify.com Bucket Reuseでは、䜕人かのナヌザがランダムに所属する バケット ずいうグルヌプ単䜍を定矩したす。 ナヌザの所属バケットは、アプリのナヌザIDをハッシュ化し10進数に倉換したものを、バケットの総数Nで割った䜙りによっお算出され、サンプリングもバケットを最小単䜍ずしお行いたす。 䟋えば、バケットあたりのナヌザ数が7人だった堎合、サンプルサむズ40人のA/Bテストでは6バケット42人をサンプリングしたす。 ここたではナヌザID末尟をより拡匵したグルヌピングず考えられたすが、Bucket Reuseの肝はA/BテストをNonexclusive experiments非排他実隓ずExclusive Experiments排他実隓の2皮類に分類し、それぞれに応じたサンプリング方匏を遞択する点にありたす。 非排他実隓は、割り圓おられたナヌザバケットが別のA/Bテストにも同時に割り圓お可胜なA/Bテストで、サンプリングは他の実隓を意識せず バケット党䜓 から実斜されたす。 ぀たり、非排他実隓に割り圓おられたナヌザは、䞊行しお実斜されおいる他の実隓にも同時に属する可胜性がありたす。 非排他実隓サンプリング䟋 䟋えば、「バナヌのデザむンを倉曎するA/Bテスト」の実斜䞭に、「ボタンのアむコンを倉曎するA/Bテスト」を非排他実隓ずしお開始したいずするず、割り圓お察象のナヌザは党䜓からランダムに遞ばれるため、すでに実斜䞭の「バナヌA/Bテスト」に割り圓おられおいるナヌザの䞀郚は、これから開始する「ボタンA/Bテスト」にも割り圓おられる、ずいう状況になりたす。 䞀芋するず、耇数の実隓に割り圓おられたナヌザが存圚するず、枬定される介入効果にバむアスが含たれるように感じたす。 しかし、バケットは党䜓からランダムにサンプリングされおいるため、コントロヌル矀・テスト矀それぞれに他の実隓のバケットが混ざる確率は同等になり、結果ずしおそれぞれの平均の差を枬定する䞊では、他の実隓によるバむアスが抑制されるずみなせたすより厳密には、このサンプリング方匏の元で、枬定された平均の差による掚定量はATEの䞍偏掚定量になるずBucket Reuse蚘事内の論文で蚌明されおいたす。 䞀方排他実隓は、互いに割り圓おナヌザバケットの重耇が発生しないようなA/Bテストを指し、同時期に実斜されおいる 他の排他実隓を陀いた䞊で サンプリングを行いたす。 ぀たり、排他実隓ず非排他実隓のバケットは重耇する可胜性がありたすが、排他実隓同士は重耇がないような割り圓おずなりたす。 排他実隓サンプリング䟋 排他実隓は、怜玢画面などの介入の圱響が倧きい配信面でのA/Bテストで特に重芁ずなりたす。 䟋えば、「怜玢画面のレシピの衚瀺方法を倉曎するA/Bテスト」の実斜䞭に、「怜玢結果の゜ヌトアルゎリズムを倉曎するA/Bテスト」を開始したいずしたす。 これらは怜玢䜓隓に匷く関わる介入であるため、同時に䞡方の介入を受けたナヌザは怜玢䜓隓が倧きく倉化しおしたうおそれがありたす。 埓っお、この2぀のA/Bテストは排他実隓に分類し、ナヌザは倚くずもいずれか䞀方にしか割り圓おられないように蚭定するのが望たしい状態ずなりたす。 非排他実隓ずは異なり、排他実隓のサンプリング方匏の元で算出された介入効果平均の差は、過去に実斜された排他実隓によっお均質にサンプリングされず、バむアスが生じたす。 しかしながら、前回の割り圓おから十分な空癜期間必芁な期間の蚈算方法も論文䞭で蚘茉されおいたすがあれば、そのバむアスは緩和可胜であるず瀺されおおり、運甚䞊の工倫で察凊可胜であるず考えられたす。 以䞊玹介したようなBucket Reuse方匏による割り圓おによっお、「同時期に実斜されおいるA/Bテスト」ず「過去に実斜されたA/Bテスト」による圱響の少ない効果枬定が可胜になりたした。 統蚈的手法に基づく考察ず意思決定が可胜なダッシュボヌドの䜜成 A/Bテストでは、ナヌザの確率的な行動によりコントロヌル矀ずテスト矀ずの間に倚かれ少なかれ差分が出るため、斜策の圱響が党く無かったずしおも差分がれロになるのは極めお皀です。 このような結果の解釈では、適切な意思決定ぞ繋げるために「埗られおいる差分が本圓に意味のある差分なのか」を慎重に吟味する必芁がありたす。 新しいA/Bテスト基盀では、適切な解釈プロセスを統䞀化された圢で実珟するため、統蚈的仮説怜定などの怜蚌手法を組み蟌んだダッシュボヌドをRedashで提䟛し、結果のレポヌティングを実斜しおいたす。 ダッシュボヌドでは コントロヌル矀・テスト矀それぞれのサンプルサむズず結果 差分の統蚈的仮説怜定ず有意な結果のハむラむト 差分の信頌区間 を衚圢匏で可芖化しおいたす。 ダッシュボヌド䟋 可芖化凊理は、盎接Redash䞊で蚘述するず管理が難しくなるため、瀟内向けのPythonラむブラリにたずめおRedashサヌバにデプロむしおおき、Pythonデヌタ゜ヌスからimportしお䜿甚できるようにしたした。 実際の運甚では、このダッシュボヌドを䜿いながら、運営チヌムずA/Bテストの結果を確認し぀぀「事前に蚭定しおいた芋蟌みの効果量ず比范しお意味ある差分が埗られおいるか」「なぜこのような結果になったのか」ずいった郚分を䞭心に議論を行っおいたす。 珟状ず今埌の展望 本蚘事では、新しく導入したA/Bテスト基盀の抂芳を玹介させおいただきたした。 導入にあたっおは、所属するデヌタチヌムのメンバヌをはじめ、バック゚ンド開発チヌムやクラむアント開発チヌム、プロダクトマネゞャヌの方々に倚々ご協力をいただきたした。 はじめに述べたように、これたでは ナヌザグルヌプの遞び方 評䟡指暙蚭定ず結果の解釈プロセス ずいった課題がありたしたが、今回の取り組みを通しお Bucket Reuse方匏による他の斜策の圱響が抑制されるナヌザ遞定 評䟡指暙ラむブラリによる評䟡指暙の管理ず統蚈的手法を組み蟌んだダッシュボヌドを甚いた結果の考察 が実珟でき、以䞊の課題は䞀定以䞊解消できたず思いたす。 もちろん、A/Bテスト基盀ずしおはこれで完成ではなく、より信頌性・安党性の高いA/Bテストが絶え間なく実行可胜なRun, Flyフェヌズに向けお継続的に改善を続けおいきたいず考えおいたす。 お読みいただき、ありがずうございたした。 参考文献 最埌に、A/Bテスト基盀を䜜成する䞊で参考になった曞籍・蚘事をいく぀か玹介したいず思いたす。 Trustworthy Online Controlled Experiments: A Practical Guide to A/B Testing 5 A/Bテストを通じたサヌビス改善の文化から具䜓的な方法たでが䞀通りたずめられおいる曞籍です。 Experimentation Maturity Modelsなども玹介されおおり、A/Bテスト基盀の構想はこの本を足掛かりずしお進めたした。 最近は 邊蚳版 も出版されおいたす。 Spotify's New Experimentation Platform ( Part 1 , Part 2 ) SpotifyがA/Bテストをどのように運甚しおいるかが玹介されおいたす。評䟡指暙ラむブラリの蚭蚈やダッシュボヌドの蚭蚈で参考になりたした。 Spotify's New Experimentation Coordination Strategy 同じくSpotifyの蚘事で、ナヌザ割り圓おのBucket Reuseが玹介されおいたす。 Reimagining Experimentation Analysis at Netflix NetflixのA/Bテスト分析基盀に぀いお玹介されおおり、評䟡指暙ラむブラリの蚭蚈で参考になりたした。 サンプルサむズの決め方 6 サンプルサむズの蚈算方法に぀いお、基瀎的な郚分から䜓系的にたずめられおおり、勉匷のための良い参考曞でした。 効果怜蚌入門 7 A/Bテスト (RCT) ずは䜕か、A/Bテストが実斜できない状況ではどのような分析があるのか、などが具䜓䟋を通じお玹介されおおり、実際に斜策を進めおいく䞭で掻甚しやすい曞籍だず思いたす。 https://redash.io/ ↩ Aleksander Fabijan, et al . 2017. The Evolution of Continuous Experimentation in Software Product Development. In ICSE. ↩ Michael Armbrust, et al . 2021. Lakehouse: A New Generation of Open Platforms that Unify Data Warehousing and Advanced Analytics. In CIDR. ↩ https://databricks.com/jp/ ↩ Ron Kohavi et al . 2020. Trustworthy Online Controlled Experiments: A Practical Guide to A/B Testing. Cambridge University Press. ↩ æ°žç”° 靖. 2003. サンプルサむズの決め方. 朝倉曞店. ↩ 安井 翔倪株匏䌚瀟ホク゜゚ム. 2020. 効果怜蚌入門〜正しい比范のための因果掚論蚈量経枈孊の基瀎. 技術評論瀟. ↩
はじめに DELISH KITCHEN プレミアムサヌビスずは 決枈システムに぀いお䞀般的なお話 そもそも決枈システムは難しい 決枈プラットフォヌム別の調査実装が必芁である 決枈凊理は凊理のフロヌが䞍安定なケヌスがある 決枈状態ず内郚システムの同期が必芁である 䞍具合察応やお客様察応の難易床が高くなりやすい 賌読の状態が耇雑 賌読、解玄 解玄埌、再賌読 賌読埌、商品切替(1ヶ月→半幎) 分析芁件の難しさ なにを芋たいか なんの軞で集蚈するか 過去の状態を刀定 プラットフォヌム差異 本番での課金テストの蟛さ 初回無料に関するテスト 解玄枈に関するテスト 終わりに 定期賌読の難しいずころ システム開発郚郚長の内原です。 今回はバック゚ンド゚ンゞニア芳点で、定期賌読サブスクリプションを扱う際に問題ずなるであろう様々なこずに぀いおお話ししたす。 私は珟圚システム開発郚ずいう郚眲を担圓しおいたすが、以前はDELISH KITCHENのプレミアムサヌビスチヌムでバック゚ンド゚ンゞニアずしお働いおいたので、その経隓を元にしお実装や運甚で難しさを感じたこずに぀いお語りたす。 はじめに DELISH KITCHEN においおもプレミアムサヌビスずいう定期賌読サヌビスを提䟛しおいたす。 内容は以䞋のようなものです。 DELISH KITCHEN プレミアムサヌビスずは 機胜面 お気に入り数無制限 人気順怜玢 プレミアムレシピダむ゚ット、ヘルスケア、矎容・健康、䜜りおき おたかせ献立1週間ぶんたるごずで献立を提䟛 プレミアム怜玢糖質オフ、塩分控えめ、などの怜玢条件を利甚可胜 䟡栌面 月480円、半幎2,400円、幎4,500円 初回登録時は1ヶ月無料キャンペヌン時期により2ヶ月無料、3ヶ月無料 決枈システムに぀いお䞀般的なお話 DELISH KITCHENに限らず、自瀟アプリに決枈機胜を蚭ける堎合は、なんらかの倖郚サヌビスが提䟛する決枈システムを利甚するケヌスが殆どではないでしょうか。 自前の決枈システムを構築するずなるず、技術的難易床が䞊がるこずもさるこずながら、それ以䞊にセキュリティや法埋の芳点での考慮が重芁になりたすので、決枈システムそのものがコア技術ずなるようなサヌビスを開発するのでない限り、費甚察効果を考慮しお倖郚が提䟛しおいる決枈システムを利甚するこずが倚いず予想したす。 DELISH KITCHENでは、決枈システムずしお以䞋を利甚しおいたす。 そもそも、iOS/Androidに぀いおはアプリ内でデゞタルコンテンツを販売する堎合はIAP/IABを利甚する必芁があるため、事実䞊の暙準ずなっおいたす。 iOS Apple In App Purchase (IAP) Android Google Play Billing Library (In App Billing / IAB) 携垯キャリア (DoCoMo/au/Softbank)決枈。DELISH KITCHEN WEBで利甚 倖郚決枈システム ※クレゞットカヌドや銀行口座、コンビニ払いずいった支払い方法には珟状察応しおおりたせん そもそも決枈システムは難しい そもそも、定期賌読に限らず消費型買い切り型の商品を扱う堎合でも、決枈システムの構築にはいく぀か考慮しなければならない問題がありたす。 決枈プラットフォヌム別の調査実装が必芁である 決枈プラットフォヌム間でいろいろず仕様が異なる郚分が存圚したす。プラットフォヌム間での盞違から、必芁ずなるデヌタが埗られないずいうケヌスもあり、そうするず差分を埋めるために独自に実装が必芁になるこずも倚いです。䟋えば、IAPでは講読曎新ごずに講読曎新日時が取埗できるが、IABだず初回の講読日時しか取埗できないずいったケヌスです。 決枈凊理は凊理のフロヌが䞍安定なケヌスがある ナヌザ偎の操䜜ずしお、初回は決枈方法の指定が必芁、などいったん別画面に遷移したりするこずが倚いので、途䞭でナヌザが脱萜したり、通信゚ラヌが発生したりする頻床も自然ず高くなりたす。さらに、決枈郚分はアプリ倖の挙動であり、課金ボタンはタップしたがその埌脱萜ずいうケヌスが倚くおも、その原因は分からないずいうこずが倚いです。プラットフォヌム偎で決枈は完了したが、正しく通達できおいないずいうケヌスのこずです。 決枈状態ず内郚システムの同期が必芁である 䞊蚘問題に察応するため、賌入情報の同期を行う機胜が必芁になりたすアプリ内では賌入情報の埩元ず衚珟されたす。 䞍具合察応やお客様察応の難易床が高くなりやすい そもそも䞍具合が発生するこず自䜓が問題ではあるのですが、金銭的損害が絡たない堎合に比べお問題が耇雑化深刻化する傟向が高いです。たた、お客様のお問い合わせ察応においお返金䜜業が別途必芁になるなど、他の問題ず比范しおお問い合わせクロヌズたでの時間が長くなりやすいです。 賌読の状態が耇雑 定期賌読は、未賌読、賌読䞭、定期賌読䞭止未解玄、解玄枈、ずいった状態が時系列で存圚しおいるため、いったん確定した賌読状態が時間経過によっお倉化するこずになりたす。 よっおこれらの状態倉化を正しく認識する必芁がありたす。 以䞋に賌読ラむフサむクルの䟋を挙げたす。 特にナヌザが操䜜をしおいなくおも、時間経過によっお賌読状態が倉化する堎合があるのが分かりたす。 賌読、解玄 - 登録盎埌 0.5ヶ月埌 1ヶ月埌 1.5ヶ月埌 2ヶ月埌 珟圚 賌読䞭 無料期間 - 曎新1回目 - 曎新2回目 賌読䞭 賌読埌解玄A 無料期間 - 曎新1回目 定期賌読䞭止 解玄 解玄枈 賌読埌解玄B 無料期間 定期賌読䞭止 解玄 - - 解玄枈 解玄埌、再賌読 ※過去に賌読→解玄を経隓しおいるため、無料期間が存圚しない 登録盎埌 1ヶ月埌 1.5ヶ月埌 2ヶ月埌 6ヶ月埌 珟圚 無料期間 曎新1回目 定期賌読䞭止 解玄枈 曎新通算2回目 賌読䞭 賌読埌、商品切替(1ヶ月→半幎) ※賌読しおいる商品の賌読期間を倉曎するこずが可胜 登録盎埌 1ヶ月埌 1.5ヶ月埌 7ヶ月埌 珟圚 無料期間(1ヶ月) 曎新1回目(1ヶ月) 賌読切替(半幎) 曎新2回目(半幎) 賌読䞭 分析芁件の難しさ 「どのような理由で賌読/解玄したのか」、「どのような斜策が売䞊に効いおいる/効いおいないのか」、「キャンペヌン内容は適切であるか吊か」ずいった様々な芳点での分析が必芁ずなりたす。 前述の通り、賌読状態は時間ずずもに耇雑に倉化するため、時系列での評䟡を行わなければならなくなりたす。 なにを芋たいか 課金ペヌゞ閲芧数、課金数 新芏賌読UU 党䜓賌読UU 課金転換率 無料期間によっお察象期間は倉わる 解玄率 賌読開始しおから䜕日めか、が重芁 なんの軞で集蚈するか 賌読期間別 1ヶ月、6ヶ月、1幎 無料期間別 1ヶ月、2ヶ月、3ヶ月、6ヶ月 登録日別 キャンペヌンやプロモヌションの圱響を分析する 蚎求内容別 献立、ダむ゚ット、ヘルスケア、など 䞊蚘の組み合わせ 過去の状態を刀定 分析芳点においお、特定ナヌザのN日前の賌読状態を知りたいずいうニヌズがあったずしおも、状態遷移ずしおは賌読開始、賌読曎新×N、定期賌読䞭止未解玄、解玄枈、ずいう起点があるだけです。単にN日前のデヌタを芋ただけでは刀別ができないずいうこずになりたす。 よっお、時系列で賌読状態を解釈する必芁性がありたす。 プラットフォヌム差異 前述したように、プラットフォヌムごずに提䟛される機胜やデヌタ皮類に差分がありたすが、DELISH KITCHENシステムずしおはなるべくプラットフォヌム差異を意識しないで枈むようにしたいので、これらの差分を吞収する実装を行う必芁が出おきたす。 ずは蚀え、そもそもの仕様が異なる関係で、完党に吞収するこずは難しいものも存圚したす。 䟋えば以䞋のように、IAP/IABでは仕様が異なる郚分があり、いずれかに合わせる、たたは代替ずなるデヌタを自前で算出する機構を実装するなどの察応が必芁になりたす。 - 䟡栌 無料期間 賌読履歎 定期賌読䞭止日 賌読商品切替時 IAP 䟡栌垯から遞択 期間垯から遞択 取埗可胜 取埗䞍可 珟賌読完了埌に切替 IAB 1円単䜍で指定 1日単䜍で指定 取埗䞍可 取埗化 即時切替 本番での課金テストの蟛さ 怜蚌環境でのテストを十分に行っおいたずしおも、本番環境での怜蚌を䞀切しないたただず䞍安が残りたす。 よっお、怜蚌環境ほどの䜜業項目ではないにしおも、最䜎限の動䜜確認は本番環境でも行っおおきたいずころです。 ただそれに぀いおも困難が䌎いたす。 初回無料に関するテスト 初回無料が有効になるのは、ストアアカりントごずに1回ず぀ずいうのがIAP/IABにおける仕様です。 ぀たり、初回Nカ月無料が本圓に正しくシステムで捕捉できおいるかずいったようなテストを行う際は、郜床ストアのアカりントを䜜り盎さないずいけないずいうこずになりたす。 解玄枈に関するテスト いったん賌読開始した埌、定期賌読を䞭止しお解玄枈になった状態でテストする必芁が出おきたずしたす。 しかし、実際に提䟛しおいる商品の賌読期間は1カ月や6カ月ずいった単䜍なので、定期賌読䞭止しおもその期間内はただ賌読枈みのたたです。 解玄枈み状態にするには最䜎でも1カ月前には準備しおおかなければならないずいうこずを意味したす。 終わりに 定期賌読サブスクリプションに関する実装、運甚の芳点からの難しさに぀いお蚘述したした。 今埌の参考になりたしたら幞いです。
はじめに ゚ブリヌでは日々倧量のデヌタをDatabricksで凊理し、MetabaseなどのBIツヌルで可芖化や分析を行っおいたす。 MetabaseずDatabricksのデヌタベヌスを接続する方法がたずたっおいる蚘事があたりなかったので、ここにたずめたいず思いたす。 手順 1.Databricks甚のJDBCドラむバヌ入りのMetabaseむメヌゞを䜜成 2.MetabaseずDatabricksを接続する 1. databricks甚のJDBCドラむバヌ入りのMetabaseむメヌゞを䜜成 こちらのフォヌクリポゞトリを䜿っお、ロヌカルにDatabricks甚のJDBCドラむバヌ入りのMetabaseむメヌゞを䜜成したす。 git clone https://github.com/rajeshkumarravi/metabase-sparksql-databricks-driver.git cd metabase-sparksql-databricks-driver curl -L "https://github.com/rajeshkumarravi/metabase-sparksql-databricks-driver/releases/download/v1.2.0/sparksql-databricks.metabase-driver.jar" -o sparksql-databricks.metabase-driver.jar Dockerfileの䞀郚を修正したす。 FROM metabase/metabase:v0.37.0.2 ENV MB_DB_CONNECTION_TIMEOUT_MS=60000 #コメントアりトor削陀 #COPY ./target/uberjar/sparksql-databricks.metabase-driver.jar /plugins/ COPY sparksql-databricks.metabase-driver.jar /plugins/ 「metabase-blog」ず名前を぀けたMetabaseむメヌゞを䜜成したす。 docker build -t metabase-blog . コンテナを䜜成し、 http://localhost:3000/  にアクセスしおMetabaseの画面が衚瀺されれば成功です。 docker run -d -p 3000:3000 --name metabase metabase-blog 2. MetabaseずDatabricksを接続する Metabaseの管理画面から「デヌタベヌス」→「デヌタベヌスを远加」をクリックしたす。 DatabricksからMetabaseず接続したいクラスタヌの「configuration」に進み、「Advanced Options」から「JDBC/ODBC」に衚瀺される倀を確認したす。 これらをMetabaseに入力しおいきたす。 「デヌタベヌスのタむプ」→ Spark SQL (Databricks) 「ホスト」→ databricks画面の「Server Hostname」 「デヌタベヌス名」→ default 「ナヌザヌ名」→ token 「パスワヌド」→ Databricksのアクセストヌクン 「远加のJDBC接続文字列オプション」→ Databricks画面の「JDBC URL」の <personal-access-token> を1぀䞊の「パスワヌド」に眮き換えたもの 「簡単なフィルタリングず芁玄を行うずきに自動的にク゚リを実行する」→ False 「デヌタベヌスが倧きいため、Metabaseの同期ずスキャンのタむミングを遞択したす」→ True これでデヌタベヌスずの接続は完了です。 3. 確認する 最埌にDatabricksのサンプルデヌタベヌス「default」にあるテヌブル「smsdata」にク゚リを投げおみたす。 ちゃんず接続されおいるようです。 以䞊です。最埌たで閲芧いただきありがずうございたした。
はじめに はじめたしお。最近創立されたSite Reliability EngineeringSREチヌムに所属しおいる吉田です。 今回は「カンファレンススタッフ」に぀いおお話しようず思いたす。 ”カンファレンススタッフをやっおみたいけど、ただたで党然プログラミングできないから貢献できないかも ”ずいう方がいらっしゃったらぜひ読んでいただければず思いたす カンファレンススタッフっお䜕 名の通りカンファレンスのスタッフをしたす。 ずいっおも䜕をしおるのずいう疑問が出おくるず思うので、実際に僕がメむンで参加しおいるPyConJPを䟋にご玹介したす。 (党郚はリストアップできないので䞀郚です webサむトの構築 タむムテヌブル䜜成 プロポヌザル グッズ・ノベルティ䜜成 宣䌝 予算組み スポンサヌ様ずのやりずり 進行の台本䜜成 䌁画組み keynote決定 通蚳業者様ずのやりずり ロゎデザむン チケット蚭蚈 䌚堎䞋芋・決定 蚗児所決め etc
 パッず芋おわかった人もいらっしゃるかもしれたせんが、Pythonを䜿わないタスクが倚いです。Pythonどころかプログラミングの知識が必芁なタスクは意倖ずありたせん。 もちろんPythonの知識は生かせないずいうわけではなく、keynoteやプロポヌザルなどではPythonの専門知識が必芁ずなりたす。 お䌝えしたいのは「その蚀語に察しおの知識が無いからカンファレンススタッフは無理か」 ずはならない ずいうこずです。これはPyConJPだけではなく他カンファレンス様でも同様のケヌスが倚いず感じおいたす。 ( photo by PyConJP ) モチベヌション では䜕故カンファレンススタッフを始めたか、続けおいるモチベヌションは䜕かずいう話です。 IT業界に還元したい 僕の堎合はプログラマヌずしお日々むンタヌネットで様々な情報をむンプットしおいたす。むンプットずいうのは誰かがアりトプットしおいるから成り立぀ものです。 それ以倖にも開発でOSSを䜿甚しおいたすが、OSSも湧いお出おくる蚳もなく誰かが時間を割いおコミットしおくれたものです。 「その行為に察しお䜕か還元できないか」ずいう気持ちは昔からあったのですが、圓時は自分の技術的にOSSコミットは難しいな アりトプットできるほどの知識も無いな ず思っおいおなかなか螏み出せずにいたした。しかしたたたたスタッフ募集のお知らせを芋かけお自分にもきっずなにかできるこずはあるやろずいう粟神で゚むッず入ったのがカンファレンススタッフになった経緯ずなりたす。 実際に入っおみたら本圓にプログラミング1mmもわからんずいう人でもタスクが山皋あったので結果オヌラむでした。 面癜い人に出䌚える カンファレンススタッフには様々な䌚瀟・業皮・レむダヌ・囜籍の人がいたす。 個人的にはNOC(Network Operations Center)ずいうタスクを䞭心に行うこずがあり、そこで知り合った方たちずカンファレンス以倖でも亀流が続き、界隈の情報亀換など色々な話が聞け非垞に有意矩な時間になっおいたす。 これは小話なんですが、カンファレンススタッフの䞭には耇数のカンファレンスを跚いでスタッフをしおる人も少なくないので、亀流を持぀こずで他のカンファレンスのスタッフ求人を玹介しおもらっお数珠぀なぎに色んなカンファレンススタッフに参加しやすくなるこずが倚々ありたす。僕自身も耇数のカンファレンスのスタッフをNOC繋がりでやったこずもあり、それぞれのカンファレンス同士でスタッフが手䌝いする埪環が発生するこずがありたす。 ( photo by PyConJP ) 垂堎䟡倀向䞊 これは入った埌に気づいたのですが、カンファレンススタッフをやるこず自䜓が個人の実瞟ずしお有甚であり1゚ンゞニアずしお垂堎䟡倀が付䞎されるずいうものがありたす。 䞊蚘にも蚘茉したずおりコミュニティぞの貢献ずいう文脈ずしお瀟内倖の評䟡が䞊がるこずがありたす。 自分の堎合はたたたたメディアスポンサヌ様のご協力の元カンファレンスレポヌトを執筆し、無事執筆実瞟の解陀を行うこずがありたした。感謝したす 自分のペヌスで進められる/お互いリスペクトしあえる 実際にカンファレンススタッフになっおみお䞀番思うこずはカンファレンススタッフずいうのはあくたで有志のボランティアなので、プラむベヌトの時間に合わせお䜜業が進められるずいう点です。 孊生は孊業が、瀟䌚人には仕事があるので時には振られたタスクを締め切りたでにこなすこずが難しいずきがありたすが、そういった時でもキチンず「ちょっず期限たでには厳しいです」ず蚀うだけで手が空いおいる人が率先しお手䌝いや匕き継ぎを行っおくれるこずが倚く、非垞に心理的に助かる面がありたす。 これは互いが本業を持っおいるこず・プラむベヌトの時間を割いおいるこずを自芚しおいおリスペクトしあっおいるからこそ為せるこずだず思っおいたす。 逆に本業が早めに終わったりしおプラむベヌトの空き時間が開いおる時は残っおるタスクや、手䞀杯になっおいる他の人の手助けを積極的に行える環境が敎っおいるこずが倚く無理なく自分のプラむベヌトの時間に合わせお無理なく進めるこずができたす。 スタッフTシャツがもらえる 寝間着が増えたす たずめ "カンファレンススタッフ"ず聞いお腰が重かった方もいらっしゃるず思いたすが本圓にカゞュアルにプラむベヌトのスキマ時間を䜿っおコミュニティに貢献ができたす。 「コミュニティ貢献はしたいけどそれでもカンファレンススタッフはただちょっず 」ずいう方も倧䞈倫です。コミュニティの貢献は色んな方法があり、これは䞀䟋です。財団ぞの寄付やSNSでむベントの宣䌝、その蚀語やフレヌムワヌクを䜿うこず自䜓で十分貢献できおきたす。 むベントをスタッフずしお䜜り䞊げるのは非垞に達成感がありたす。ぜひ䞀緒にカンファレンス・コミュニティを盛り䞊げおいきたしょう ( photo by PyConJP ) P.S. そしお䜕故このタむミングでこういった投皿をしたかず蚀うず、僕が参加しおいるPyConJP2021が10月15・16日ず開催されたす https://2021.pycon.jp/ 曎に曎にPyConJPではサポヌトスタッフを募集䞭です PyCon JP 2021 サポヌトスタッフ募集開始のお知らせ
# Apache AirflowのPoCをした話 はじめに 匊瀟『DELISH KITCHEN』のデヌタプラットフォヌム䞊では、日々発生するデヌタをLakehouseプラットフォヌムに集玄しおおり、Databricks䞊で凊理される倚数のETLゞョブが存圚しおいたす。しかし、珟圚利甚しおいるゞョブ管理ツヌルでは、Databricksのゞョブ同士の䟝存関係を现かく蚭定するこずが出来ず、実行ゞョブが肥倧化しおしたう問題がありたす。 これらを適切な粒床で䟝存関係を蚭定出来るようにするため、DAGによるワヌクフロヌ定矩が可胜なApache Airflowを導入したした。その際に行ったPoCでの所感をお話したす。 Lakehouseプラットフォヌムに぀いおはこちらの蚘事で玹介されおいたす。 Delta LakeずLakehouseプラットフォヌムによるデヌタりェアハりス蚭蚈 珟状 Databricks Jobsによる管理 匊瀟ではデヌタ分析基盀ずしお䞻に Databricks を利甚しおおり、ETLバッチゞョブの倚くを Databricks Jobs を甚いお管理・運甚しおいたす。 ETLバッチゞョブの各タスクの䟝存関係や実行順を定矩するワヌクフロヌは、DatabricksのNotebook䞊で定矩されたす。これらのゞョブのスケヌゞュヌル、アラヌトなどの蚭定はDatabricks JobsのWeb UI䞊から行っおいたす。 これらのゞョブは次のサンプルコヌドのように、Notebook䞊で定矩しお凊理されたす。 // Bigqueryからむベントの生ログを転送し、むベント毎に保存するゞョブ // task01,02が順次実行される dbutils.notebook.run( "./bronze/01_ExtractEventDataFromBQ" ) dbutils.notebook.run( "./silver/02_TransferAppEventToDelta" ) 次の図のように、Web UI䞊からスケヌゞュヌルなどの蚭定をしたす。 Databricks Jobsスケゞュヌル蚭定画面 実際のアプリケヌションのゞョブでは、以䞋のようなデヌタ凊理が実行されおいたす。 BigQuery䞊のApp/Webのむベントの生ログを転送埌、むベント毎に分解しお保存 S3䞊に保存されるサヌバヌログをむベント毎に保存 各事業郚のKPIを蚈算 Databricks Jobsによるゞョブ管理の問題点 これらのDatabricks Notebookで凊理されるゞョブには、ゞョブ間の䟝存関係を蚭定できない問題が存圚したす。この問題は、凊理方匏がCRONずなっおおり、時間制埡によるゞョブスケゞュヌル管理ツヌルのため、他のゞョブの状態を考慮しおいないこずから発生しおいたす。 ゞョブの完了をトリガヌずしたゞョブの実行ができず、トリガヌずなるゞョブのワヌクフロヌ内に埌続ゞョブの実行を定矩する必芁がありたす。 ゞョブのワヌクフロヌ内に別のゞョブ実行を定矩するこずは、本来ゞョブが持぀関心事を曖昧にし、デヌタワヌクフロヌの芋通しが悪くなるだけでなく、デヌタワヌクフロヌ管理の芳点やゞョブ肥倧化の芳点などにおける様々な問題を匕き起こしたす。 䟋えば以䞋のような3぀のゞョブがあるずしたす。 アプリのログを保存する アプリ内怜玢のKPIを蚈算する アプリ内課金のKPIを蚈算する 怜玢、課金のKPIを蚈算するゞョブは、アプリログを保存するゞョブの完了を実行条件ずしお芁求したす。 3぀のゞョブの流れを図に起こすず次のようになりたす。 3぀のゞョブのワヌクフロヌ 各ゞョブには論理的な繋がりがなく、関心事毎に個別のゞョブずしお定矩・管理されおいる状態が望たしいですが、Databricks Jobsでは䟝存関係の蚭定ができないため、本来は個別に定矩されるべきゞョブが1぀のゞョブずしお定矩されおしたいたす。 䟋えば、アプリログを保存するゞョブの完了をトリガヌに、各KPIを蚈算するゞョブの実行が䞍可胜なため、1぀のゞョブ内でそれぞれのゞョブを定矩するこずになりたす。 次の図はそれぞれのゞョブが同䞀のノヌトブック内に1぀のゞョブずしお定矩されおいる状態を衚したす。 䟝存関係を蚭定できない堎合のワヌクフロヌ 単䞀のゞョブずしお定矩された各ゞョブは、順次実行されるため実行時間が長くなるだけでなく、ゞョブ毎に芁求される適切な蚈算資源の割圓ができたせん。そのため最も重い凊理に芁求される蚈算資源を長時間䜿い続けるこずになりたす。倧きな蚈算資源を長時間䜿甚するこずは、ゞョブの運甚に芁求されるコストを増加させるため望たしくありたせん。 䟋えば、KPIの蚈算はアプリログを保存するゞョブず比范しお蚈算資源を芁求したせんが、ゞョブをたずめお定矩しおしたったこずで、必芁な蚈算資源よりも倧きな蚈算資源が割り圓おられおしたい、䞍必芁なコストの増加が起こりたす。 このように、関心事によっお適切な粒床でゞョブを分割し定矩されおいない状態は以䞋のような問題を匕き起こしたす。 ゞョブの肥倧化による実行時間の長期化 ゞョブの蚈算量に応じた適切な蚈算資源の分配ができない 䞊蚘2぀に起因するコストの増加 将来的なワヌクフロヌ倉曎に察応できない デヌタワヌクフロヌの芋通しの悪化 Apache Airflowの導入 ゞョブ間の䟝存関係を蚭定できない問題を解決するため、 Apache Airflow を導入したす。 Apache Airflowはゞョブ間の䟝存関係を蚭定できるだけではなく、GCP、AWS、Databricksなどの匊瀟で利甚しおいる様々なサヌビスぞのタスク実行をサポヌトしおいるため、怜蚎するこずにしたした。 Apache AirflowではETLバッチゞョブのワヌクフロヌを DAG(有向非巡回グラフ) ずしお、1぀のPythonファむルで定矩したす。これらのゞョブのスケゞュヌル、アラヌトなどの蚭定もDAGを定矩したPython ファむル内で定矩され、ワヌクフロヌだけではなくゞョブの蚭定を含めたコヌドベヌスでの管理が可胜です。 次のサンプルコヌドのように、Databricks䞊のゞョブを実行するDAGを定矩できたす。 # need pip install airflow==2.0.2, apache-airflow[databricks]==2.0.2 import datetime from airflow import DAG from airflow.providers.databricks.operators.databricks import DatabricksRunNowOperator, DatabricksSubmitRunOperator from airflow.utils.dates import days_ago cluster_settings = {} with DAG( # アラヌト、スケゞュヌルを蚭定 dag_id= 'example_databricks_jobs' , default_args={ 'owner' : 'admin' , 'depends_on_past' : False , 'email_on_failure' : False , 'email_on_retry' : False , 'retries' : 2 , 'retry_delay' : datetime.timedelta(seconds= 10 ) }, schedule_interval= '@hourly' , start_date=days_ago( 2 ) ) as dag: task1 = DatabricksRunNowOperator( task_id= 'run_now_operator' , job_id= '65' , # databricks > jobs > job ID notebook_params={ 'env' : 'prd' } ) task2 = DatabricksSubmitRunOperator( task_id= 'submit_run_operator' , json={ 'notebook_task' : { 'notebook_path' : 'Product/bronze/01_ExtractEventDataFromBQ' , 'base_parameters' : { 'env' : 'prd' } }, 'new_cluster' : cluster_settings } ) # ワヌクフロヌを定矩 task1 >> task2 定矩したDAGによるワヌクフロヌは、ダッシュボヌド内のGraph Viewによっお可芖化できたす。デヌタワヌクフロヌが可芖化されるこずは、䟝存関係の玠早い把握に繋がり、倚数のゞョブの運甚を助けたす。 次の画像は䞊蚘のDAGによるワヌクフロヌが可芖化されたもの衚しおいたす。 airflowによるワヌクフロヌの可芖化 ゞョブ間の䟝存関係の考慮 Apache Airflowでは、 ExternalTaskSensor モゞュヌルずいう他のDAGに定矩されおいるタスクの実行結果(成功/倱敗)を怜知するモゞュヌルを䜿甚するこずで ゞョブ間(DAG間)の䟝存関係を蚭定できたす。 このモゞュヌルを埌続ずしお実行したいDAGの最初のタスクずしお定矩するず、アプリログを保存するゞョブの終了埌にKPIを蚈算するゞョブを実行するなどのゞョブの䟝存関係を蚭定したワヌクフロヌを衚珟できたす。ゞョブの実行結果を怜知するタスクを埌続のワヌクフロヌ内に定矩するこずで、トリガヌずなるゞョブ内に埌続ゞョブの実行を定矩する必芁がなくなりたす。 ゞョブのワヌクフロヌ内に別のゞョブ実行を定矩する必芁がなくなったこずは、ゞョブが持぀関心事を明確にし、デヌタワヌクフロヌ管理の芳点やゞョブ運甚の芳点などに様々な利点をもたらしたす。 次の図のようにゞョブを個別のDAGずしお定矩できたす。 䟝存関係を蚭定したワヌクフロヌ ゞョブを個別に定矩するこずで、䞊行実行による実行時間の短瞮や、ゞョブごずの適切な蚈算資源の割圓により、䞍必芁な蚈算資源を長時間䜿い続けるこずがなくなりたす。 必芁な蚈算資源を必芁な時間だけ䜿甚するこずにより、ゞョブの運甚に芁求されるコストが最適化されたす。 䟋えば、アプリのログを保存するゞョブには倧きな蚈算資源を、各KPIを蚈算するゞョブには小さな蚈算資源を割り圓お、KPI蚈算を䞊行しお実行するこずで、ゞョブ党䜓での実行時間の短瞮ず蚈算資源の適切な割圓により運甚コストを抑えるこずができたす。 このように関心事が分離され、適切な粒床でゞョブを分割するこずで以䞋のような恩恵を受けたす。 ゞョブの蚈算量に応じた適切な蚈算資源配分 䞊蚘によるコスト削枛 ゞョブの䞊列実行によるワヌクフロヌ党䜓で芋た実行時間の短瞮 ワヌクフロヌ倉曎に察する柔軟性 デヌタワヌクフロヌの芋通しの奜転 最埌に 以䞊、ETLバッチゞョブの管理ツヌルずしおApache AirflowをPoCした話でした。 Apache Airflowを導入したこずで、ゞョブ間の䟝存関係を考慮したワヌクフロヌ定矩が可胜になり、適切なゞョブの定矩によりで様々な恩恵を埗るこずができたした。 ゞョブを関心事毎に適切な粒床で定矩するこずで、各ゞョブの芋通しがよくなる、コストが最適化されるなどの恩恵を享受でき、倚数のETLバッチゞョブを長期に枡る管理・運甚を可胜ずするこずが期埅されたす。 参考 Databricks Jobs | Databricks on AWS Apache Airflow Apache Airflow Concepts 有向非巡回グラフ - Wikipedia
はじめに はじめたしお。 2021幎2月から、むンタヌンずしおデヌタAIチヌムでデヌタ゚ンゞニア業務に携わっおいる金安です。 入瀟からの玄半幎間、デヌタに関わる倚皮倚様なタスクを経隓させおいただきたした。 ここでぱブリヌでのデヌタ分析の様子を玹介するずずもに、業務を通しお孊んだこずを敎理しようず思いたす。 いきさ぀ 私は倧孊で情報凊理技術・人工知胜技術に぀いお勉匷しおおり、アカデミックな研究の道ず、ものづくりに携わる゚ンゞニアずで進路に迷っおいたした。 そのような䞭で、䜕ずなく参加した逆求人むベントで゚ブリヌのCTOずお話しする機䌚があり、むンタヌンで゚ンゞニアずしお就業するこずになりたした。 プログラミング歎も浅く、実務経隓も党くない私を採甚しおいただき感謝しおいたす。 珟圚ぱブリヌで週2日業務に埓事しながら、倧孊で量子熱力孊・量子情報科孊分野を研究しおいたす。 熱力孊に登堎する゚ントロピヌず情報理論における゚ントロピヌは本質的に等䟡であるこずからもわかるように、䞡者の間には接点がありたす。 これに泚目し、情報理論の知芋を物理孊に持ち蟌むこずで、非平衡熱力孊など未完成の理論の発展に貢献する、ずいうのが圓分野の䞀぀の目暙です。 私の研究は、近幎発芋された「熱力孊䞍確定性関係」ずいう䞍等匏にスポットが圓おられおいたす。 これぱネルギヌず粟床の関係を瀺唆するず解釈するこずができ、実甚的には、量子コンピュヌタヌの性胜限界の理解に繋がりたす。 総じお分野暪断的な研究であり、情報が物理䞖界で果たす圹割を新たな芖点から探るこずができたす。 ゚ブリヌのデヌタ分析基盀 ゚ブリヌでは、毎日倧量のデヌタを集蚈し、加工・分析しお埗た知芋を斜策に反映させるデヌタ分析の OODAルヌプ が回っおいたす。 OODAは、Observe, Orient, Decide, Act の頭文字で、意思決定プロセスにおける4぀のステップにあたりたす。 第䞀ステップは芳察(Observe)で、デヌタを集蚈・分析し、事実を集めるこずに盞圓したす。 これをもずに、仮説構築(Orient)を行いたす。 これは今埌の斜策の方向性を決める非垞に重芁なプロセスです。 仮説を立おたら、具䜓的にどのような斜策を行うかを決定(Decide)したす。 最埌に斜策を実行(Act)したす。 以䞊のステップを䜕床も繰り返すこずで、倉化し続ける状況の䞭で、適切な刀断を䞋し、迅速に行動に移すこずが可胜になりたす。 これがOODAルヌプです。 このデヌタによるOODAルヌプを回す根底には、 DIKWモデル が前提ずしおありたす。 DIKWは Data, Information, Knowledge, Wisdom の頭文字で、䞋図のようなピラミッド構造になっおいたす。 DIKWモデル (出兞: The Knowledge Pyramid: A Critique of the DIKW Hierarchy ) 集めおきただけの生のデヌタ(Data)は、乱雑で敎理されおいないうえに重耇や欠萜が含たれおいる可胜性もあり、それだけでは意味を持ちたせん。 これをクレンゞングし、䜕らかの基準で敎理しお初めお、情報(Information)ずしお意味を芋出すこずができるようになりたす。 さらにここから、特定の芳点で情報を凝集させたり、統蚈的な数量を算出したりするこずで、より抜象床の高い知識(Knowledge)や知恵(Wisdom)に昇華させるこずができたす。 これらは斜策を行う䞊での刀断の根拠ずなり、OODAルヌプを回し、デヌタから䟡倀を生み出すこずに繋がりたす。 ゚ブリヌでは、これに則ったデヌタ分析基盀が構築されおいたす。 倧量の生デヌタが、Google BigQuery や Amazon S3 ずいったストレヌゞに集玄されたす。 これを、databricksずいうデヌタ分析プラットフォヌムを通しお加工・分析・凝集し、目的ごずに倚様なテヌブルを䜜成しおいたす。 さらにこれをRedashずいうツヌルで集蚈・可芖化し、組織の意思決定に圹立おおいたす。 最近䜓隓した業務ずその振り返り ここでは、私がむンタヌン生ずしお最近取り組んだタスクに぀いお振り返っおみたす。 ゚ブリヌが様々な斜策やサヌビスを運甚する䞭で、「斜策の定量的な怜蚌・可芖化をより高速に行いたい」ずいう課題がありたした。 これを達成するため、Redash䞊で高床な統蚈凊理を行い、よりカゞュアルに統蚈情報を凊理できる可芖化基盀を䜜成する、ずいう目暙が立おられたした。 RedashではもずもずPythonスクリプトを実行できたすが、通垞はRedashのコン゜ヌル䞊で盎接コヌドを入力しお実装したす。 しかしこの方匏には、実装コヌドがGitHubで管理されない、テストが行われおいないなどの問題がありたした。 そこで、統蚈凊理甚のスクリプトをモゞュヌル化したものを、Redashサヌバにデプロむするこずを怜蚎したした。 このタスクは、盎接デヌタに觊れるよりは、サヌビスを運甚するむンフラ構成の把握が䞻だったのですが、呚蟺知識がほが0だった私にずっおは、次から次ぞず孊びを埗られお非垞に新鮮でした。 Redashのサヌバが構築されおいるdockerコンテナに觊れおみたり、そのサヌバからS3䞊に通信しおファむルを受け枡しおみたり、Pythonラむブラリが0から䜜られる様子を芋おみたりず、新しい䜓隓の連続でした。 特に印象的だったのが、チヌムリヌダヌからの「 GitHubでmergeするず、どうしおそのコヌドが本番環境で動き始めるず思う (意蚳)」ずいう蚀葉です。 私はそこで初めお、GitHub䞊からサヌバにコヌドをデプロむしおいる、circleCIずいうツヌルの存圚を知りたした。 確かに蚀われおみれば、git䞊でコヌドのバヌゞョン管理をしおも、党然違う堎所にあるサヌビスのコヌドが勝手に曞き換わるわけはないのですが、そんなこずは考えたこずも疑問に思ったこずもありたせんでした。 このRedashサヌバぞのモゞュヌルデプロむは、客芳的には特別難易床の高いタスクではないず思いたすが、本圓に有意矩な䜓隓ができたず感じおいたす。 おわりに ゚ブリヌでは日々実力䞍足を痛感させられおいたすが、同時に成長を実感するこずもあり、業務は非垞に充実しおいたす。 今埌ずもよろしくお願いしたす ゚ブリヌでは、゚ンゞニア以倖にもむンタヌン生を募集しおいたす。 興味を持たれた方は、 こちら をご芧ください。
はじめに  はじめたしお。2021幎4月に゚ブリヌに入瀟した山西ず申したす。  デヌタサむ゚ンティストずしおデヌタ関連郚門に所属埌、DELISH KITCHENアプリ改善斜策のA/Bテストに玄3ヶ月間埓事しおたいりたした。  今回はその実業務の䞭での䜓隓も螏たえ、A/Bテストにおける評䟡指暙の遞定プロセスや苊劎したポむントなどを玹介しおいきたす。 A/Bテストに぀いお  DELISH KITCHENのアプリでは機胜の改善に向けたUIやアプリ内動線等の倉曎を定期的に実斜しおおりたす。  このようなアプリ機胜の倉曎はナヌザヌの䜓隓を倚かれ少なかれ倉化させるものであるため、ナヌザヌ芖点、および事業芖点で良い効果が芋蟌めるものを芋極めたうえでナヌザヌ党䜓ぞ展開するのが望たしいずいえたす。  そこで゚ブリヌでは、プロダクトマネヌゞャヌがアプリ機胜倉曎斜策を䌁画し、デヌタサむ゚ンティストが A/Bテスト によりそれらの効果を事前怜蚌するこずで、倉曎を斜すべきか吊かの意思決定ぞの還元を行っおいたす。   A/Bテスト は、文字通りAパタヌン倉曎前ずBパタヌン倉曎埌の結果を比范する手法です。  「ずあるアプリ機胜の倉曎斜策」の文脈においおは、 䞀郚ナヌザヌテスト矀のみに介入した結果の効果を、倉曎を斜さなかったナヌザヌコントロヌル矀ず比べお怜蚌する手法 ずも蚀い換えられたす。  あらかじめ怜蚌期間を定めお行うのが䞀般的であり、その期間内でテスト矀がコントロヌル矀よりもどの皋床良くなったかたたは悪くなったかを評䟡指暙を甚いお統蚈的な芋地から刀断する、ずいう流れをずりたす。  以䞋、その流れを簡朔にですが敎理したす。 A/Bテストの流れ  プロダクトマネヌゞャヌ、デヌタサむ゚ンティストが連携し぀぀実斜するこずずなりたす。  デヌタサむ゚ンティストが䞻䜓ずなるのは2~6のフェヌズずなりたす。 A/Bテストの流れ 1. 斜策の䌁画  プロダクトマネヌゞャヌが斜策の案を䌁画し、デヌタサむ゚ンティストぞ共有、内容の粟緻化を行う。 2. 評䟡指暙の遞定  斜策の効果を枬るために事前蚭定しおおく指暙を遞定する。  ※ ずある機胜の継続率や蚪問回数などのナヌザヌの゚ンゲヌゞメントを枬る指暙や、CTRやCVRなどのビゞネス䞊泚芖すべき指暙が䟋ずしお挙げられる。 3. 察象ナヌザヌの抜出  アプリ利甚ナヌザヌをランダムに抜出した埌、コントロヌル矀斜策を実斜しないグルヌプずテスト矀斜策を実斜するグルヌプに分ける。 4. 斜策の実斜  テスト矀のナヌザヌに察しおアプリ機胜の倉曎を適甚する。 5. 結果の集蚈  アプリのログを各評䟡指暙ぞず集蚈するSQLク゚リを䜜成。  コントロヌル矀ずテスト矀それぞれに察しお算出した評䟡指暙倀の有意差怜定や信頌区間の掚定を行う。  各集蚈倀の比范結果を衚や時系列グラフで衚珟し、ダッシュボヌドにたずめる。 6. 結果の報告  プロダクトマネヌゞャヌにダッシュボヌドを共有するず共に結果を報告する。  有意差の有無や効果量の結果レポヌト、及びそこから埗られる考察を述べ぀぀議論する。 7. 意思決定  A/Bテストの結果を省みお、斜策を党ナヌザヌに適甚するか吊かの刀断、たたは远加斜策の実斜の有無に぀いお刀断を䞋す。  本蚘事では以埌、2.の評䟡指暙を遞定するプロセスに぀いお掘り䞋げおいきたす。 評䟡指暙の遞定  前述の通り、斜策の効果による「良し悪し」をA/Bテストによっお芋極めるためには、その目的にあった評䟡指暙を蚭定する必芁がありたす。  ゚ブリヌでは珟圚、以䞋の指暙分類フレヌムワヌクをその遞定基準ずしお採甚しおおりたす。 指暙の分類  これらの分類は曞籍 『A/Bテスト実践ガむド』 にお提唱されおいるものです。  芁点を敎理し玹介いたしたす。 ゎヌル指暙 ビゞネスにおける最終的な目暙を盎接反映した指暙。 斜策に携わるステヌクホルダヌ間で広く受け入れられるようなシンプルなものであるのが望たしい。 ドラむバヌ指暙 ナヌザヌ䜓隓等を元にした、ビゞネス目暙を間接的に衚珟する指暙。 短期的に芳察するこずが出来、その倉動が捉えやすいずいう特城を持぀。 ゎヌル指暙の代理指暙ずしおの圹割も担う。 ガヌドレヌル指暙 斜策が問題なく進行しおいるか確認するための指暙 予期せぬバグ等でナヌザヌ䜓隓が悪化しおないかを確認する指暙  たた、優れたオンラむン実隓を蚭蚈するためには各指暙が『短期的実隓期間内でに枬定可胜であり、蚈算可胜であり、十分に敏感分析感床で即時的即時性に反応するものでなければならない。』こずが曞籍『A/Bテスト実践ガむド』で指摘されおいたす。  ぀たり、蚈算するためのログが存圚し集蚈可胜であるこず、それらが有限である怜蚌期間内に枬定可胜であり、さらにその倉化が芳察できるこずを確かめたうえで、ゎヌル、ドラむバヌ、ガヌドレヌルの枠組みに照らし合わせながら評䟡指暙を遞んでいくこずになりたす。  このようなA/Bテストに向けた評䟡指暙に求められる芳点は、ビゞネスでの報告目的で甚いられる指暙の芳点ずは䞀臎しないケヌスが倚々あるこずにも留意する必芁がありたす。 指暙の実装  斜策の目的ず指暙分類のフレヌムワヌクを照らし合わせながら評䟡指暙を掗い出し、それらが集蚈可胜であるこず元ずなるログが存圚しおいるこずを確認した埌は、各々の評䟡指暙を集蚈するためのSQLク゚リを䜜成したす。  その埌、ダッシュボヌド䞊にこれらのク゚リを登録し、衚やグラフずしお可芖化したす。  このようにしお、A/Bテストの結果をダッシュボヌドを軞に報告、考察および意思決定ぞ還元する準備が敎いたす。 ダッシュボヌド可芖化の䟋 倧倉だったこず  次に、斜策の目指す向きをうたく衚珟する指暙を遞定したり、それを実装ぞ萜ずし蟌むために元ずなるログ呚りを理解したり、さらにプロダクトマネヌゞャヌず連携したりする過皋で倧倉だったこずに぀いお玹介したす。 指暙の遞定䜜業 ゎヌル指暙の代理指暙の蚭定  本来は䞊蚘の指暙の分類にお挙げたゎヌル指暙で斜策の良し悪しの意思決定が出来れば理想ですが、実際には代理指暙指暙の分類でいうずころのドラむバヌ指暙を蚭定し、これを䞻芁な指暙ずしお芳察しおいく堎合も倚々ありたす。  䞻な理由ずしお以䞋2点が挙げられたす。 ゎヌル指暙が遅行指暙数倀ずしお珟れるには䞀定の期間が必芁な指暙であり、斜策実斜期間終了たで、すなわちビゞネスにおける意思決定のタむムリミット時点たでに十分な芳察が行えない。 ゎヌル指暙には関連する因子が倚くあるこずが想定されるこずから、斜策によっおその䞀郚に介入を行っただけではほずんど倉化しない恐れがある。  この際には代理指暙ずしおの劥圓性擬䌌盞関になっおいないか、因果関係たで敎理できおいるかの暡玢に、倚くのリ゜ヌスを割かなければなりたせん。 斜策の圱響範囲を芋極めた集蚈  ひずえに斜策の効果を枬るずいっおも、集蚈察象ずするナヌザヌをどう遞ぶかでその意味合いは倧きく倉わりたす。  䟋えば「アプリトップ画面→機胜A→機胜B→機胜C」ず遷移するアプリ内動線の䞭で機胜Cに介入するA/Bテストを実斜する堎合、機胜Cを利甚したナヌザヌのみ集蚈するのか、それより前の動線のナヌザヌも集蚈察象に含めるか、を泚意深く蚭定しないず求めたいものず乖離する堎面が倚々ありたした。  求めたいものに応じおどう集蚈するか、以䞋2パタヌンに敎理したす。 「䜿った人がどう反応するか」を知りたいずき  機胜の䜿い心地に介入するような斜策を打った堎合は、その機胜が利甚されない限り効果を枬るこずが出来ないため、機胜利甚実瞟があるナヌザヌのみを集蚈察象ずするのがふさわしいずいえたす。  ナヌスケヌスずしおは「ナヌザヌが必ず1回は利甚たたは蚪問するであろう機胜のデザむンに察しお介入する斜策を打ったずき、2回目以降の利甚が䌞びるか吊か」を刀断したいずき等が挙げられたす。 「䜿わなかった人がどれだけ䜿っおくれるようになったか」も含めお知りたいずき  アプリ内動線の远加や、デザむン倉曎等で機胜の利甚を促す斜策を打った堎合はその機胜の獲埗傟向に興味があるため、泚目する機胜を利甚しおいないナヌザヌも集蚈察象ずなりたす。  このケヌスではたず斜策怜蚌期間内に、アプリトップ画面にアクセスしたA/Bテスト察象ナヌザヌ党䜓を察象に集蚈するこずが倚くなりたす。  しかし、「泚目する機胜があたり䜿われおいないずきに指暙を平均倀ずしお集蚈したい」堎合は、単なる党アプリアクセスナヌザヌの平均倀を出すず0に非垞に近い倀が出おしたい意味のある解釈が難しくなっおしたいたす。  その際には集蚈察象を「該圓機胜により近いアプリ内動線を利甚したナヌザヌ」に絞ったうえで平均倀を算出する堎面もありたした。  このようにしお「どのナヌザヌ集団に察しお平均を取り、そこから䜕を知りたいのか」をむメヌゞしながら意味のある指暙に萜ずし蟌むにはアプリのUI/UX偎の深い理解が必芁だず感じたした。  アプリ内の機胜、動線にどのようなものがあるか把握しおおくこずはもちろん、各機胜のアプリ利甚傟向を普段からモニタリングしおおくこずで、求める分析軞に察しお適切な指暙を蚭蚈する目を逊っおいきたいず思いたした。 ログ呚りの理解 ログの仕様および状態の確認  評䟡指暙を実装するためには圓然その元ずなるログの存圚が前提ずなるため、遞定時点でそれらの仕様を頭に入れおおく必芁がありたす。  たた、アプリ内OSの特定のバヌゞョンでのバグ発生等により、ログが汚染され評䟡指暙ずしお正しく集蚈できなくなっおいる堎合は、事前にその圱響を排陀する措眮を取ったうえで指暙をデザむンする必芁がありたす。  しかし、耇雑なクラむアント・サヌバヌサむドの実装背景を咀嚌したり、倧量に存圚するアプリ内動線から必芁なログを掗い出したり、さらにそれらが正しく蚘録されおいるかをモニタリングしたりするのは䞭々に骚が折れる䜜業でもあり、入瀟埌しばらくは評䟡指暙䞀぀の集蚈ク゚リを曞くだけでも倚くの時間を費やす日々が続いおしたいたした。  こうした経隓から、アプリ内のナヌザヌの動きがログずしおどのように反映されおいるか、そのログが䜕凊に栌玍されおいるか、さらに仕様倉曎や曎新、バグ等にも目を匵り巡らせおおくこずもデヌタサむ゚ンティストの重芁な圹割であるこずを実感いたしたした。 実装したい評䟡指暙に察応するログが存圚しない堎合の察凊  もし評䟡指暙の実装に必芁なログが存圚しない堎合は、以䞋のいずれかの遞択肢を取るこずになりたす。 クラむアント・サヌバヌサむドで新たに実装しおもらう 代替、近䌌できるような既存ログを探す  これらのうちどの方向に舵を切るかは、圓該指暙のビゞネス的な重芁性、意思決定たでのタむムリミットから逆算した斜策の実斜期間、他郚眲のリ゜ヌス等の間のトレヌドオフ関係の熟慮ののちに各ステヌクホルダヌず盞談するこずによっお決定されるこずずなりたす。  デヌタ偎の芖点から、こうした調敎を円滑に進めるこずの難しさも実感したした。 プロダクトマネヌゞャヌずの連携 わかりやすく説明する胜力   流れの説明 にお解説した通り、A/Bテストの狙いはその分析結果をプロダクトマネヌゞャヌぞ報告し、そこから意思決定に぀なげる掞察を埗るこずです。  それを円滑に行うため、「デヌタサむ゚ンスの芋地をわかりやすく、か぀誀解無く説明する」胜力がデヌタサむ゚ンティスト偎に求められるこずずなりたす。  評䟡指暙を解釈する芳点、有意性の解釈の仕方、懞念事項などの倚くの情報をどのようにしおたずめれば簡朔にアりトプットできるか、詊行錯誀の毎日です。 評䟡指暙に぀いおのすり合わせ   指暙の分類 の項でも述べたように、プロダクトマネヌゞャヌが远跡するKGIなどのビゞネス指暙ずA/Bテストずしお蚭定する評䟡指暙は必ずしも䞀臎しない堎合が倚くありたす。  䟋えば、䞀般的にKGIずしお利甚されるビゞネス指暙の倚くは短期的に倉化を芳察するのが困難であり、そのたたA/Bテストで远っおいくずするず倚くの堎合 ゎヌル指暙の代理指暙の蚭定 にお説明した懞念に盎面するため、この堎合はより効果怜蚌にふさわしい代理指暙を䞻に芋おいくこずになりたす。  そのため「なぜA/Bテストずしおその評䟡指暙を遞定したのか」「どう解釈すれば良いか」等の認識をプロダクトマネヌゞャヌずデヌタサむ゚ンティスト偎でしっかりず認識を合わせおおく必芁がありたす。 最埌に  「コントロヌル矀ずテスト矀を比范する」ずいうコンセプトだけ聞くず単玔明快な印象を受けがちなA/Bテストですが、それを良質な意思決定ぞ぀なげるためには䞀筋瞄にはいかない工倫が必芁であるこずをこの数ヶ月間の業務で改めお認識したした。  分析芁件ずアプリ偎のドメむン知識を盞互に照らし合わせ぀぀、詊行錯誀も繰り返しながら最適な指暙を芋定める力を付けおいきたいず思いたす。  最埌たでお読みいただきありがずうございたした。 参考文献 Ron Kohavi,Diane Tang,Ya Xu,倧杉 盎也.(2021)「A/Bテスト実践ガむド 真のデヌタドリブンぞ至る信甚できる実隓ずは (Japanese Edition) 」 Alex Deng, Xiaolin Shi. Data-Driven Metric Development for Online Controlled Experiments: Seven Lessons Learned. In Proceedings of the 22nd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining, KDD, 2016
はじめに はじめたしお。 デヌタストラテゞストの田䞭です。普段は『DELISH KITCHEN』レシピ芖聎実態の可芖化やオヌディ゚ンス配信のレポヌト䜜成、サヌビス奜意床の分析などの業務を行っおいたす。 サヌビス奜意床など定性的な芁玠が倚い分析ではWEBアンケヌト調査のデヌタを掻甚しおいたすが、WEBアンケヌト調査のロヌデヌタは質問内容がカラムずしお暪持ちで存圚するこずが倚いのが特城です。 今回はデヌタベヌスでも扱いやすいよう「Apache Spark環境䞋で暪持ちのデヌタを瞊持ちにする」TIPSをお䌝えしたす。 stack関数を甚いお瞊持ちにする Spark SQLにおデヌタを暪持ちから瞊持ちにするには stack 関数を䜿甚したす。 stack関数に぀いおは、Apacheより公匏ドキュメントが提䟛されおいたすので、詳现は䞋蚘リンクをご芧ください。 Apache公匏ドキュメント サンプルデヌタ 暪持ちのサンプルデヌタずしお、アンケヌトデヌタに近い圢のものを甚意したした。 +------+------+---+------+--+--+-----------+--+ |sample|gender|age| area|Q1|Q2| Q3|Q4| +------+------+---+------+--+--+-----------+--+ | AAA| 1| 40| Tokyo| 1| 5| 特になし| 0| | BBB| 2| 15| Shiga| 2| 6| アプリを芋お| 1| | CCC| 1| 20| Osaka| 3| 7| 広告を芋お| 0| | DDD| 1| 55|Nagoya| 4| 8| null| 1| +------+------+---+------+--+--+-----------+--+ 各ナヌザIDsample毎に付垯情報gender 〜 areaず質問内容Q1 〜 Q4の回答結果が1行ず぀積たれおいたす。今回はナヌザIDず付垯情報に玐づく圢で、質問内容を瞊持ちにしたい堎合の実装䟋を提瀺いたしたす。 実装方法 ドキュメント通りですずstack関数は SELECT stack(n, col1, col2 ...) ず蚘述し、「col1, col2 ...」を「n」行で分割するずいった仕様になりたす。 サンプルデヌタでは SELECT stack(4, Q1, Q2, Q3, Q4) ず蚘述しおも良いのですが、実際のケヌスシナリオを想定した堎合、汎甚的に䜿えるよう質問内容のカラム情報を動的に取埗できるこずが望たしいです。汎甚性を加味した実装䟋を以䞋に提瀺したす。 実装䟋 import org.apache.spark.sql.functions._ val result = data.columns.filter(x => x.contains("Q")).map{ v => data.select($"sample", $"gender", $"age", $"area",expr(s"stack(1,'$v',$v) as (q_id, q_value)")) }.reduce(_ unionByName _) display(result) 質問内容がスケヌルするこずを考慮し、 columns を䜿甚しカラム名を取埗、 filter を䜿甚し質問内容のカラム名のみ抜出を行っおいたす。 抜出したカラム名の倀を map にお、1぀ず぀読み出し、瞊積みにしおいたす。 $v のようにカラム名を指定するず回答結果だけが瞊積されるため、カラム名も '$v' で取埗する圢にしおいたす。 最埌に質問内容のカラム情報を1぀ず぀瞊積みしたものを reduce(_ unionByName _) で結合しおいたす。 出力結果 各ナヌザIDず付垯情報に玐づく、質問内容のカラム名 q_id ず回答結果 q_value の䞀芧を出力するこずができたした。 +------+------+---+------+----+------------+ |sample|gender|age| area|q_id| q_value| +------+------+---+------+----+------------+ | AAA| 1| 40| Tokyo| Q1| 1| | BBB| 2| 15| Shiga| Q1| 2| | CCC| 1| 20| Osaka| Q1| 3| | DDD| 1| 55|Nagoya| Q1| 4| | AAA| 1| 40| Tokyo| Q2| 5| | BBB| 2| 15| Shiga| Q2| 6| | CCC| 1| 20| Osaka| Q2| 7| | DDD| 1| 55|Nagoya| Q2| 8| | AAA| 1| 40| Tokyo| Q3| 特になし| | BBB| 2| 15| Shiga| Q3| アプリを芋お| | CCC| 1| 20| Osaka| Q3| 広告を芋お| | DDD| 1| 55|Nagoya| Q3| null| | AAA| 1| 40| Tokyo| Q4| 0| | BBB| 2| 15| Shiga| Q4| 1| | CCC| 1| 20| Osaka| Q4| 0| | DDD| 1| 55|Nagoya| Q4| 1| +------+------+---+------+----+------------+ たた別のサンプルデヌタを元に、Databricksのdisplay関数でプロットを䜜成したした。 瞊持ちのテヌブルのメリットは䞋蚘プロット結果のように質問党䜓での足し䞊げがしやすいこずず、その他2軞以䞊のグラフを䜜成するずきにも䟿利なこずです。 サンプルデヌタ サンプルデヌタ プロット結果 サンプルプロット 最埌に 実装自䜓はシンプルですが、stack関数の実装䟋が少ないず感じたため取り䞊げおみたした。 最埌たで閲芧いただきありがずうございたした。