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
780
テストケースの名前はどうつけるべきか?
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
共通化で考えるべきは、実装より公開する型だった
codeegg
0
250
act1-costs.pdf
sumedhbala
0
240
関数型プログラミングのメリットって何だろう?
wanko_it
0
180
そのテスト、説明できますか?~LWテスト戦略FW~のご紹介
nakahara
0
210
Claude Opus 4.6以後の受託開発エンジニアの変化(Claude Code開発ノウハウ大公開スペシャルbyクラスメソッド)
iidatakuma
1
790
SREは、MCPとSRE Agentをこう使え!
kazumax55
0
150
トークンをケチるな、設計しろ:GitHub Copilotを賢く使うコンテキスト戦略
ochtum
0
320
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
shogogg
0
260
才能?センス?知らん、 続けたもん勝ちだ。-- 結婚・出産・癌を越えてなお、私がプロダクトを創り続ける理由
16bitidol
2
870
Performance Engineering for Everyone
elenatanasoiu
0
270
えっ!!コードを読まずに開発を!?
hananouchi
0
220
PHPだって関数型したい 〜できること、できないこと〜 / fp-in-php
jsoizo
0
220
Featured
See All Featured
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
350
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
220
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.4k
The World Runs on Bad Software
bkeepers
PRO
72
12k
The Curious Case for Waylosing
cassininazir
1
430
So, you think you're a good person
axbom
PRO
2
2.1k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
410
Building Adaptive Systems
keathley
44
3.1k
Statistics for Hackers
jakevdp
799
230k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.6k
Information Architects: The Missing Link in Design Systems
soysaucechin
0
1k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
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 ͝ڵຯ͕͋Γ·ͨ͠ΒɺҰॹʹϥϯνʹ ߦ͖·ͤΜ͔ʁ