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
Kuniwak
PRO
November 20, 2017
Programming
8.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.7k
仕様漏れ実装漏れをなくすトレーサビリティAI基盤のご紹介
orgachem
PRO
16
10k
要求定義・仕様記述・設計・検証の手引き - 理論から学ぶ明確で統一された成果物定義
orgachem
PRO
37
22k
DeNA での思い出 / Memories at DeNA
orgachem
PRO
8
3.6k
それ CLI フレームワークがなくてもできるよ / Building CLI Tools Without Frameworks
orgachem
PRO
18
4.7k
状態遷移図を書こう / Sequence Chart vs State Diagram
orgachem
PRO
4
770
テストケースの名前はどうつけるべきか?
orgachem
PRO
2
940
欠陥を早期に発見するための 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
Signal Forms: Details & Live Coding @enterJS 2026 in Mannheim
manfredsteyer
PRO
0
230
PHPだって関数型したい 〜できること、できないこと〜 / fp-in-php
jsoizo
0
190
Creating Composable Callables in Contemporary C++
rollbear
0
200
はてなアカウント基盤 State of the Union
cockscomb
1
1.3k
気圧・高度・GPSを記録&可視化するアプリ「Koudo」を作った話
hjmkth
1
350
AI時代、エンジニアはどう育つのか -未経験エンジニアの成長を間近で見て考えたこと-
thasu0123
0
100
Embedded SREと共に達成した会員管理システムのAWS移行 - SRE NEXT 2026 ランチスポンサーセッション
niftycorp
PRO
1
2.3k
共通化で考えるべきは、実装より公開する型だった
codeegg
0
210
Haskell/Servantを通してWebミドルウェアを捉え直す
pizzacat83
1
480
フィードバックで育てるAI開発
kotaminato
1
110
Webフレームワークの ベンチマークについて
yusukebe
0
200
『コードを書く以外の』エンジニアリング〜課金基盤移行プロジェクト推進のためのTips4選
yuriko1211
0
330
Featured
See All Featured
The Language of Interfaces
destraynor
162
27k
Color Theory Basics | Prateek | Gurzu
gurzu
0
390
Technical Leadership for Architectural Decision Making
baasie
3
440
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
300
The Mindset for Success: Future Career Progression
greggifford
PRO
0
410
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
260
BBQ
matthewcrist
89
10k
The Pragmatic Product Professional
lauravandoore
37
7.4k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
340
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
210
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
220
Building the Perfect Custom Keyboard
takai
2
810
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 ͝ڵຯ͕͋Γ·ͨ͠ΒɺҰॹʹϥϯνʹ ߦ͖·ͤΜ͔ʁ