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
iOS アプリエラー監視の設計とその効果
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Kuniwak
PRO
November 20, 2017
Programming
9k
33
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
iOS アプリエラー監視の設計とその効果
Kuniwak
PRO
November 20, 2017
More Decks by Kuniwak
See All by Kuniwak
AIベース静的検査器の偽陽性率を抑える工夫3選
orgachem
PRO
8
2.8k
仕様漏れ実装漏れをなくすトレーサビリティAI基盤のご紹介
orgachem
PRO
16
11k
要求定義・仕様記述・設計・検証の手引き - 理論から学ぶ明確で統一された成果物定義
orgachem
PRO
40
24k
DeNA での思い出 / Memories at DeNA
orgachem
PRO
8
3.7k
それ CLI フレームワークがなくてもできるよ / Building CLI Tools Without Frameworks
orgachem
PRO
18
4.8k
状態遷移図を書こう / Sequence Chart vs State Diagram
orgachem
PRO
4
810
テストケースの名前はどうつけるべきか?
orgachem
PRO
2
970
欠陥を早期に発見するための Software Engineer in Test とその重要性 / What is Software Engineer in Test and How they works
orgachem
PRO
22
5k
住宅を WebXR で評価しよう / Evaluating My Home by WebXR
orgachem
PRO
0
250
Other Decks in Programming
See All in Programming
夏だ!祭りだ!祭りとはドメインモデリングでは?
ryugen04
0
390
ドリフトを絶対に許さない(?)CDK運用 / CDK Ops with Zero Tolerance for Drifts (?)
akihisaikeda
1
230
MySQLとPostgreSQLって何が違うの?
akagami
0
140
コンパウンドプロダクト開発のためのローカルプロセスマネージャー再発明 #layerxgo
izumin5210
0
340
わからない話を追いかけたら、プログラミング言語を作る側にいた
ydah
3
550
【QA Test Talk Vol.8】AI-DLC による Whole Team Approach の加速
pkshadeck
PRO
0
240
片田舎のおっさん、 Swift Buildのダイアモンド問題解決の不具合修正PRを出すが、解決方法がキャッシュをしないようにすることであり、ビルド時間が伸びると言われてマージされないので高速化もする/swiftbuild
yimajo
0
280
GDG Korea Android: 2026 I/O Extended ~ What's new in Android development tools
pluu
0
240
VibeCodingからAgenticWorkflowへ
starfish719
0
870
源内ハンズオン概要編
hideg
0
210
バグを直したら useEffect が消えた
colorful12
3
700
リアルな遅延を測る仕様
kota_yata
1
130
Featured
See All Featured
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
470
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
280
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Faster Mobile Websites
deanohume
310
32k
Music & Morning Musume
bryan
47
7.3k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
180
Information Architects: The Missing Link in Design Systems
soysaucechin
1
1.1k
Thoughts on Productivity
jonyablonski
76
5.3k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
RailsConf 2023
tenderlove
30
1.5k
Transcript
J04ΞϓϦΤϥʔࢹͷ ઃܭͱͦͷޮՌ
"CPVUNF
,VOJXBL גࣜձࣾ%JWFSTFͷJ04ςοΫϦʔυɻ ͱ͋ΔΞϓϦͷϦχϡʔΞϧϓϩδΣΫτʹ ్த͔ΒՃΘͬͨͷͷɺςετࠔͳઃܭΛ ͷͨΓʹͨͨ͠ΊɺཪϦχϡʔΞϧΛ։࢝ɻ ࠷ऴతʹςετΛಋೖ͠ɺ։ൃΛഒʹͨ͠ɻ झຯ5%%ɻ
Τϥʔࢹͱ
w ΞϓϦͰൃੜͨ͠ΤϥʔΛαʔόʹૹΔͳͲͯ͠ ΤϥʔͷൃੜͳͲΛࢹ͢Δٕज़ w ྫ͑ɺΞϓϦ͕Ϋϥογϡͨ͠ΒϨϙʔτΛ ඈ͢ΫϥογϡϨϙʔτ͜ͷҰछ w ΫϥογϡϨϙʔτղੳαʔϏεͰ $SBTIMZUJDT͕༗໊
Τϥʔͷൃੜ66 Τϥʔͷ*% ΤϥʔͷΧςΰϦ Τϥʔൃੜͷ࣌ؒతਪҠ Τϥʔൃੜ࣌ͷσόΠε Τϥʔൃੜ࣌ͷ04
w ࣮ɺଟ͘ͷΫϥογϡϨϙʔταʔϏε ΫϥογϡҎ֎ͷΤϥʔࢹͰ͖Δ w ྫ͑ɺ8FC"1*ݺͼग़࣌͠ͷΤϥʔɺ ෦ঢ়ଶͷෆ߹ͳͲͷΤϥʔࢹͰ͖Δ ૹ৴ͷํޙͰհ͠·͢
Τϥʔࢹͷಛੑ
w ΤϥʔࢹͷಛੑҎԼͷͭɿ w ඇৗʹൣͳόάΛݕͰ͖Δ w Τϯόά͔Βൃݟ·Ͱͷ͕͍࣌ؒ
ਤղ
όάΛݟ͚ͭΔͨΊͷखஈ ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ
όά9Λݟ͚ͭΒΕΔॴ όά9 ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ
όά9 ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ ্ͷํͰࢭ·Δͱ
ݪҼڀ໌ͷ͕͍࣌ؒ όά: ಛघͳΤϥʔԼͷํͰ ͔͠ݟ͚ͭΒΕͳ͍
ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ Τϥʔࢹಛघͳ ΤϥʔΛݟ͚ͭΒΕΔ
΄΅࠷ޙͷࡆ όά: ͔͠͠ɺ্ͷΑΓ Τϯόά͔Βൃݟ·Ͱͷ ͕࣌ؒͱ͍ͯ
ΤϥʔࢹͰݟ͚ͭΔ͖ Τϥʔͱ
ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ ༧ޠλΠϙ ม໊λΠϙ
ϓϩύςΟ໊ λΠϙ ذߟྀ࿙Ε ίϯϙʔωϯτ ༷ͷෆ߹ ༷ͷޡղ ಛघͳڥͰ͔͠ ࠶ݱ͠ͳ͍Τϥʔ ҋ ཧͷόάݕͷ࢟
ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ ༧ޠλΠϙ ม໊λΠϙ
ϓϩύςΟ໊ λΠϙ ذߟྀ࿙Ε ίϯϙʔωϯτ ༷ͷෆ߹ ༷ͷޡղ ಛघͳڥͰ͔͠ ࠶ݱ͠ͳ͍Τϥʔ ҋ όά͕Լͷ·Ͱ ಥ͖ൈ͚ͯ͠·͏ͷͰ ݪҼڀ໌ʹ͕͔͔࣌ؒΔ μϝͳόάݕͷ࢟
ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ ༧ޠλΠϙ ม໊λΠϙ
ϓϩύςΟ໊ λΠϙ ذߟྀ࿙Ε ίϯϙʔωϯτ ༷ͷෆ߹ ༷ͷޡղ ಛघͳڥͰ͔͠ ࠶ݱ͠ͳ͍Τϥʔ ҋ ཧͷόάݕͷ࢟
ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ ༧ޠλΠϙ ม໊λΠϙ
ϓϩύςΟ໊ λΠϙ ذߟྀ࿙Ε ίϯϙʔωϯτ ༷ͷෆ߹ ༷ͷޡղ ಛघͳڥͰ͔͠ ࠶ݱ͠ͳ͍Τϥʔ ҋ ΤϥʔࢹͰݕ͖͢ Τϥʔ͜ͷ͋ͨΓ
͜͜·Ͱͷ·ͱΊ w ΤϥʔࢹಛघͳόάΛ ݕ͢ΔͨΊͷखஈ w ͳ͓ɺͦͷલͷखஈͰόάΛ ݟ͚ͭΒΕΔͳΒͦͷํ͕ ݪҼڀ໌Λ͘Ͱ͖Δ
Τϥʔࢹͷ࣮ํ๏
ΤϥʔࢹαʔϏεͷ"1*ΛѲ͢Δ ΤϥʔϨϙʔλʔΛΧελϚΠζ͢Δ ΤϥʔϨϙʔλʔΛΈࠐΉ
ΤϥʔࢹαʔϏεͷ "1*ΛѲ͢Δ
Crashlytics.sharedInstance().recordError(error) $SBTIMZUJDTʹΤϥʔΛૹ৴͢Δίʔυ &SSPSͰͳ͘/4&SSPSͳͷͰҙ
ΤϥʔϨϙʔλʔΛ ΧελϚΠζ͢Δ
/4&SSPSʹม͢Δͷ ໘ͳͷͰɺ4XJGUͷ&SSPSΛ /4&SSPS͍͍ײ͡ʹ มͯ͘͠ΕΔϥούʔΛॻ͘ $SBTIMZUJDTͷ߹
class CrashlyticsErrorReporter { private let crashlytics = Crashlytics.sharedInstance() func report(error:
Error, from reporter: Any) { #if DEBUG let prefix = "DEBUG " #else let prefix = "" #endif let detailedError = NSError( domain: "\(prefix)\(type(of: reporter))", code: CrashlyticsErrorTracker.getNSErrorCode(bySwiftError: error), userInfo: [ NSLocalizedDescriptionKey: "\(error)", ] ) self.crashlytics.recordError(detailedError) } private static func getNSErrorCode(bySwiftError error: Error) -> Int { let bridgedError = error as NSError return bridgedError.code } } %(ϏϧυΛ۠ผͰ͖ΔΑ͏ʹ͓ͯ͘͠ͱ ຊ൪ڥͱ։ൃڥΛ۠ผ͘͢͠ͳΔ ΤϥʔϨϙʔλʔʹͲͷΑ͏ʹ ूܭ͞ΕΔ͔Λҙࣝ͢Δ ྫ͑ɺ$SBTIMZUJDT/4&SSPSͷ EPNBJOͱDPEFͷͰΤϥʔΛ άϧʔϐϯά͢ΔͷͰɺͦΕͧΕ Τϥʔ*%ͱൃੜݩΛࢦఆ͢Δͱ ៉ྷʹΤϥʔ͕·ͱ·Δ ΤϥʔͷશจάϧʔϐϯάʹΘͳ͍Α͏ʹ͢Δ ʢϢʔβʔ*%ͱ͔͕ೖΔͱݸผͷΤϥʔʹͳͬͯ ૯ΛѲͰ͖ͳ͘ͳΔͷͰʣ $SBTIMZUJDT༻ͷΤϥʔϨϙʔλʔΛ࡞ SFQPSUؔΛݺͿͱΤϥʔϨϙʔτ͕ ૹ৴͞ΕΔΑ͏ʹ࣮͍ͯ͠Δ ΤϥʔͱҰॹʹൃੜݩ͕ Θ͔ΔΑ͏ʹ͓ͯ͘͠ͱ ݪҼͷݟ͕͖ͭ͘͢ͳΔ
ΤϥʔϨϙʔλʔΛ ΈࠐΉ
Α͘ΈΔΈࠐΈํ๏
class UserApiRepository: UserRepositoryProtocol { private let api: GitHubApiClientProtocol func get(by
id: GitHubUser.Id) -> Promise<GitHubUser> { return self.api .fetch( endpoint: GitHubApiEndpoint(path: "/user/" + id.text), headers: [:], parameters: [] ) .then { data -> GitHubUser in let response: GitHubUserResponse = try unbox(data: data) return response.user } .catch { error in ErrorReporter.shared.report( error: error, reporter: self ) } } } Τϥʔ͕ฦ͖ͬͯͨΒ ΤϥʔϨϙʔτΛૹ৴ ʢͭ·Γϋʔυίʔυʣ "1*ݺͼग़͠ͷίʔυ
w ͔͠͠ϋʔυίʔυʹ͕ଟ͍ɿ w "1*ͷݺͼग़͠ʹؔͷͳ͍ίʔυ͕ೖΔͨΊ ୯Ұݪଇʹҧ͢Δ w ୯ମςετͰΤϥʔϨϙʔτ͕ૹΒΕͯ͠·͏ w ςετ͚࣌ͩ༗ޮͳϑϥάΛՃͯ͠ ΤϥʔϨϙʔτΛૹ৴͠ͳ͍Α͏ʹ
Ͱ͖ͳ͘ͳ͍͕Γͨ͘ͳ͍
ͦ͜Ͱ0CTFSWFSύλʔϯ
w 0CTFSWFSύλʔϯͰɺࢹऀ͕ࢹରͷ ঢ়ଶมԽΛͯ͠ಈ࡞͢Δ w ΤϥʔϨϙʔτʹԠ༻͢Δͱɿ w ࢹऀΤϥʔϨϙʔλʔ w ࢹରΤϥʔ͕ൃੜ͠͏ΔΦϒδΣΫτ w
0CTFSWFSύλʔϯΛ͑ϋʔυίʔυͷ ΛղফͰ͖Δ
Τϥʔͷൃੜݯ Τϥʔ͕ൃੜ͠·ͨ͠ ΤϥʔϨϙʔλʔ ࢹ
Τϥʔͷൃੜݯ ΤϥʔϨϙʔλʔ ࢹ Τϥʔ͕ى͖ͨͷͰ ΤϥʔϨϙʔτΛ ૹ৴͠·͢
Τϥʔͷൃੜݯ ΤϥʔϨϙʔλʔ ΤϥʔϨϙʔτૹ৴ ͷ Τϥʔ͕ى͜Γ͏Δ ॲཧͷ
Τϥʔͷൃੜݯ ΤϥʔϨϙʔλʔ ςετͷͱ͖ ΤϥʔϨϙʔλʔ ΛऔΓ͚ͳ͍
w ͨͩ͠ɺ0CTFSWFSύλʔϯΛ͑Δॴ ݶΒΕ͍ͯΔ w ࢹର͕ࢹՄೳͳΠϯλʔϑΣʔεΛ උ͍͑ͯͳ͍ͱ͍͚ͳ͍ͨΊ w .7 ΞʔΩςΫνϟͳΒɺ.PEFMࢹՄೳͳ ΠϯλʔϑΣʔεΛ͍࣋ͬͯΔͣͳͷͰɺ.PEFMʹ
ΤϥʔϨϙʔλʔΛΈࠐΈ͍ͣ͢ w 'MVYΞʔΩςΫνϟͷ߹4UPSF͕ࢹՄೳͳ ΠϯλʔϑΣʔεΛ͍࣋ͬͯΔͣ
.PEFM 7JFX &SSPS3FQPSUFS ࢹ ࢹ Τϥʔ͕ൃੜ͠·ͨ͠
.PEFM 7JFX &SSPS3FQPSUFS ࢹ ࢹ ΤϥʔΛදࣔ͠·͢ ΤϥʔϨϙʔτΛ ૹ৴͠·͢
func fetch() { switch self.currentState { case .fetching: return case
.fetched: self.stateMachine.transit(to: .fetching) self.repository.get(by: self.id) .then { user in self.stateMachine.transit(to: .fetched( result: .success(user) )) } .catch { error in self.stateMachine.transit(to: .fetched( result: .failure(.unspecified(debugInfo: "\(error) )) } } } ͜ͷ.PEFM"1*ݺͼग़͕͠Τϥʔʹ ͳͬͨΒΤϥʔঢ়ଶมԽ͢Δ ͦͷͨΊɺΤϥʔϨϙʔλʔ͔Βࢹ͍͢͠ .PEFMͷ"1*ݺͼग़͠ͷίʔυ ͜ͷΑ͏ͳ.PEFMͷઃܭͷৄࡉIUUQTHPPHM1G'+-Λࢀর͍ͯͩ͘͠͞
class UserModelErrorReporter { private let model: UserModelProtocol private let errorReporter:
ErrorReporterProtocol private let disposeBag = RxSwift.DisposeBag() init( observing model: UserModelProtocol, reportingBy errorReporter: ErrorReporterProtocol ) { self.model = model self.errorReporter = errorReporter self.model.didChange .subscribe(onNext: { [weak self] (state: UserModelState) in guard let `self` = self else { return } switch state { case let .fetched(result: .failure(error)): self.errorReporter.report(error: error, reporter: self) default: return } }) .disposed(by: disposeBag) } } .PEFM͕Τϥʔঢ়ଶʹͳͬͨΒ ΤϥʔϨϙʔτΛૹ৴ .PEFMͷঢ়ଶભҠΛࢹ .PEFMΛࢹ͢ΔΤϥʔϨϙʔλʔΛ࡞
͜͜·Ͱͷ·ͱΊ w Τϥʔࢹͷ࣮ํ๏ʹ 0CTFSWFSύλʔϯ͕ద͍ͯ͠Δ w .PEFM4UPSFΛࢹ͢ΔͱΑ͍
Τϥʔࢹͷίπ
ΤϥʔࢹΛ։࢝͢Δͱ ࠔౕ͕ͬͨͪΐͪ͘ΐ͘ग़ͯ͘Δ
Fatal Exception: SomethingError *** nil ใྔ͕΄ͱΜͲͳ͍ʂ
ΤϥʔʹͳΔ͘ ΫϦςΟΧϧͳใΛ٧ΊΑ͏
func example(input: String) -> String? { guard validate1(input) else {
return nil } guard validate2(input) else { return nil } guard validate3(input) else { return nil } return "OK! Hello \(input)" } ݪҼڀ໌Λ͘͢Δѱ͍ྫ ࣦഊͨ͠ݪҼ͕۠ผͰ͖ͳ͍
enum ExampleError: Error { case validate1(debugInfo: String) case validate2(debugInfo: String)
case validate3(debugInfo: String) } ͦ͏͍͏࣌FOVNͰΤϥʔΛ۠ผͰ͖ΔΑ͏ʹ͢Δ
func example(input: String) -> Result<String> { guard validate1(input) else {
return .failure(.validate1(debugInfo: input)) } guard validate2(input) else { return .failure(.validate2(debugInfo: input)) } guard validate3(input) else { return .failure(.validate3(debugInfo: input)) } return .success("OK! Hello \(input)") } ΤϥʔΛ۠ผ͍͢͠Α͍ྫ ࣦഊͨ͠ݪҼ͕۠ผͰ͖Δ ࣦഊͨ͠ࡍͷೖྗೖखͰ͖Δ
Τϥʔࢹͷ݁Ռ
w ϢʔβʔͷखݩͰൃੜ͍ͯ͠Δόάͷछྨ نΛѲͰ͖ΔΑ͏ʹͳͬͨ w छྨن͕ѲͰ͖ΔΑ͏ʹͳΔͱɺόάमਖ਼ͷ τϦΞʔδΛΓ͘͢ͳΔ w ՝ۚܥ࠷༏ઌͱ͔ɺΤϥʔͷଟ͍ͷ ͔ΒରॲͳͲ
w ϢʔβʔͷखݩͰ༧֎ͷΤϥʔ͕ى͍ͬͯͨ͜ w ςελʔʹΑΔಈ࡞֬ೝͱڥ͕ ҟͳ͍ͬͯͨͨΊɺൃݟͰ͖ͳ͔ͬͨΑ͏ͩ w ໘ന͍͜ͱʹɺ"QQMFͷϨϏϡʔΞ͕ૺ۰ͨ͠ όάͷݪҼڀ໌ʹཱͬͨ w 4BOECPYͷϨγʔτ͡Όͳ͍ͱ࠶ݱ͠ͳ͍
όάͩͬͨ
w خ͍͠෭࡞༻ͱͯ͠ɺςελʔͷૺ۰ͨ͠όάͷ ৄࡉ͕ೖखͰ͖ΔΑ͏ʹͳͬͨ w ςελʔͷಈ࡞֬ೝதʹΤϥʔϨϙʔτ͕ ඈΜͰ͘ΔͨΊʢ%(ϏϧυͳͷͰ͙͢Θ͔Δʣ w σόοά͕͍͢͝ḿΓ·͢
·ͱΊ w ΤϥʔࢹʹΑΓɺςελʔʹΑΔಈ࡞֬ೝͰ ݟ͚ͭΒΕͳ͔ͬͨΤϥʔΛൃݟͰ͖ΔΑ͏ʹ ͳͬͨ w ઃܭͷίπҎԼͷͭɿ w 0CTFSWFSύλʔϯΛ͏ w
ͳΔ͘ΤϥʔใΛΘ͔Γ͘͢͢Δ
એ w %JWFSTFͰ৽نࣄۀͷJ04։ൃνʔϜͷ νʔϜϦʔμʔΛืू͍ͯ͠·͢ʂ w தͷαʔϏεΛࣗͷྗͰಋ͍ͯΈ͍ͨͱ ࢥ͏ํʹɺͥͻ͖ͯ΄͍͠ͱࢥ͍ͬͯ·͢ʂ w ͝ڵຯ͕͋Γ·ͨ͠ΒɺҰॹʹϥϯνʹ ߦ͖·ͤΜ͔ʁ