Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Error Handling at Spring
Search
Wisdom
February 18, 2015
48
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Error Handling at Spring
nycgolang meetup
Wisdom
February 18, 2015
More Decks by Wisdom
See All by Wisdom
Deployment Strategies at Codecademy
waomuya
0
41
Go_at_MongoDB.pdf
waomuya
1
50
Featured
See All Featured
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
2
2k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
710
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Music & Morning Musume
bryan
48
7.4k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
22k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Documentation Writing (for coders)
carmenintech
77
5.6k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Navigating Team Friction
lara
192
16k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
3.4k
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
560
Prompt Engineering for Job Search
mfonobong
0
520
Transcript
How Spring Handles Errors What we’ve learned; What we’re doing.
None
None
None
I need stuff 200 OK
I need stuff 400 Bad Request
I need stuff 500 Internal Error
I need stuff 418 I’m a teapot
“Fail Fast”
if err != nil { return err }
func GetProduct(id int) (Product, error) { product, err := db.Select(...)
return product, err }
func GetProduct(id int) (Product, error) { product, err := db.Select(...)
return product, err } func ContrivedMethod(id int) error { product, err := GetProduct(id) if err != nil { return err } ... }
func GetProduct(id int) (Product, error) { product, err := db.Select(...)
return product, err } func ContrivedMethod(id int) error { product, err := GetProduct(id) if err != nil { return err } ... } func HandleRequest(id int, w http.ResponseWriter, r *http.Request) { err := ContrivedMethod(id) if err != nil { http.Error(w, err.Error(),...) } ... }
strconv.ParseInt: parsing "adsf": invalid syntax
strconv.ParseInt: parsing "adsf": invalid syntax pq: duplicate key value violates
unique constraint
strconv.ParseInt: parsing "adsf": invalid syntax pq: duplicate key value violates
unique constraint Product not found
Errors Need Context
func GetProduct(id int) (Product, error) { product, err := db.Select(...)
return product, err } func ContrivedMethod(id int) error { product, err := GetProduct(id) if err != nil { return err } ... } func HandleRequest(id int, w http.ResponseWriter, r *http.Request) { err := ContrivedMethod(id) if err != nil { http.Error(w, err.Error(),...) } ... } Lost Context
type SpringError { error stackTrace string }
type SpringError { error stackTrace string } Context!
func GetProduct(id int) (Product, *SpringError) { product, err := db.Select(...)
return product, wrap(err) }
No product found main.GetProduct(0x1, 0x1704, 0x2b7a0, ...) /tmp/sandbox244941649/main.go:25 +0xc0 main.ContrivedMethod(0x1,
0x931a0, 0x0, 0x0) /tmp/sandbox244941649/main.go:30 +0x60 main.main() /tmp/sandbox244941649/main.go:34 +0x40
strconv.ParseInt: parsing "adf": invalid syntax
func GetProduct(id int) (Product, error) { product, err := db.Select(...)
return product, err } func ContrivedMethod(id int) error { product, err := GetProduct(id) if err != nil { return err } ... } func HandleRequest(id int, w http.ResponseWriter, r *http.Request) { err := ContrivedMethod(id) if err != nil { http.Error(w, err.Error(),...) } ... } Wrapped? Wrapped?
Use Types
func GetProduct(id int) (Product, *SpringError) { product, err := db.Select(...)
return product, wrap(err) } func ContrivedMethod(id int) *SpringError { product, err := GetProduct(id) if err != nil { return err } ... } func HandleRequest(id int, w http.ResponseWriter, r *http.Request) { err := ContrivedMethod(id) if err != nil { http.Error(w, err.String(),...) } ... } errors get wrapped Already Wrapped!
Errors Are Values https://blog.golang.org/errors-are-values
func GetProduct(id int) (Product, *SpringError) { product, err := db.Select(...)
return product, wrap(err) } func ContrivedMethod(id int) *SpringError { product, err := GetProduct(id) if err != nil { return err } ... } func HandleRequest(id int, w http.ResponseWriter, r *http.Request) { err := ContrivedMethod(id) if err != nil { http.Error(w, err.String(),...) } ... }
func GetProduct(id int) (Product, *SpringError) { product, err := db.Select(...)
return product, wrap(err) } func ContrivedMethod(id int) *SpringError { product, err := GetProduct(id) if err != nil { return err } ... } func HandleRequest(id int, w http.ResponseWriter, r *http.Request) { err := ContrivedMethod(id) if err != nil { http.Error(w, err.String(),...) } ... }
func GetProduct(id int) (Product, *SpringError) { product, err := db.Select(...)
return product, wrap(err) } func ContrivedMethod(id int) *SpringError { product, err := GetProduct(id) if err != nil { return err } ... } func HandleRequest(id int, w http.ResponseWriter, r *http.Request) { err := ContrivedMethod(id) if err != nil { http.Error(w, err.String(),...) } ... }
func GetProduct(id int) (Product, *SpringError) { product, err := db.Select(...)
return product, wrap(err) } func ContrivedMethod(id int) *SpringError { product, err := GetProduct(id) if err != nil { return err } ... } func HandleRequest(id int, w http.ResponseWriter, r *http.Request) { err := ContrivedMethod(id) if err != nil { http.Error(w, err.String(),...) } ... }
func GetProduct(id int) (product Product, err *SpringError) { defer annotateError(&err,
“fetching product with id %d”, id) product, err := db.Select(...) return product, wrap(err) }
func HandleRequest(id int, w http.ResponseWriter, r *http.Request) { err :=
ContrivedMethod(id) if err != nil { err.Annotate(“request for %s”, request.URL.String()) http.Error(w, err.String(),...) } ... }
Product not found in request for /product/1124 fetching product with
id 1124 main.GetProduct(0x1, 0x1704, 0x2b7a0, ...) /tmp/sandbox244941649/main.go:25 +0xc0 main.ContrivedMethod(0x1, 0x931a0, 0x0, 0x0) /tmp/sandbox244941649/main.go:30 +0x60 main.main() /tmp/sandbox244941649/main.go:34 +0x40
Recap • We used to see hard to understand errors
in production. • Now we don’t. • Add context to your errors. • Use the type system to enforce that every error is addressed. • Make it easy to add extra context where it is helpful
Questions? @jimtla or
[email protected]