update abort & error show & sessionRelease in defer
Showing
4 changed files
with
29 additions
and
198 deletions
| ... | @@ -16,18 +16,24 @@ type Context struct { | ... | @@ -16,18 +16,24 @@ type Context struct { |
| 16 | func (ctx *Context) Redirect(status int, localurl string) { | 16 | func (ctx *Context) Redirect(status int, localurl string) { |
| 17 | ctx.Output.Header("Location", localurl) | 17 | ctx.Output.Header("Location", localurl) |
| 18 | ctx.Output.SetStatus(status) | 18 | ctx.Output.SetStatus(status) |
| 19 | ctx.Output.Body([]byte(" ")) | ||
| 19 | } | 20 | } |
| 20 | 21 | ||
| 21 | func (ctx *Context) Abort(status int, body string) { | 22 | func (ctx *Context) Abort(status int, body string) { |
| 22 | ctx.Output.SetStatus(status) | 23 | ctx.Output.SetStatus(status) |
| 23 | ctx.Output.Body([]byte(body)) | 24 | // first panic from ErrorMaps, is is user defined error functions. |
| 24 | 25 | if _, ok := middleware.ErrorMaps[body]; ok { | |
| 26 | panic(body) | ||
| 27 | } | ||
| 28 | // second panic from HTTPExceptionMaps, it is system defined functions. | ||
| 25 | if e, ok := middleware.HTTPExceptionMaps[status]; ok { | 29 | if e, ok := middleware.HTTPExceptionMaps[status]; ok { |
| 26 | if len(body) >= 1 { | 30 | if len(body) >= 1 { |
| 27 | e.Description = body | 31 | e.Description = body |
| 28 | } | 32 | } |
| 29 | panic(e) | 33 | panic(e) |
| 30 | } | 34 | } |
| 35 | // last panic user string | ||
| 36 | panic(body) | ||
| 31 | } | 37 | } |
| 32 | 38 | ||
| 33 | func (ctx *Context) WriteString(content string) { | 39 | func (ctx *Context) WriteString(content string) { | ... | ... |
| ... | @@ -70,12 +70,6 @@ func (c *Controller) Finish() { | ... | @@ -70,12 +70,6 @@ func (c *Controller) Finish() { |
| 70 | 70 | ||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | func (c *Controller) Destructor() { | ||
| 74 | if c.CruSession != nil { | ||
| 75 | c.CruSession.SessionRelease() | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | func (c *Controller) Get() { | 73 | func (c *Controller) Get() { |
| 80 | http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405) | 74 | http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405) |
| 81 | } | 75 | } |
| ... | @@ -178,7 +172,16 @@ func (c *Controller) Redirect(url string, code int) { | ... | @@ -178,7 +172,16 @@ func (c *Controller) Redirect(url string, code int) { |
| 178 | } | 172 | } |
| 179 | 173 | ||
| 180 | func (c *Controller) Abort(code string) { | 174 | func (c *Controller) Abort(code string) { |
| 181 | panic(code) | 175 | status, err := strconv.Atoi(code) |
| 176 | if err == nil { | ||
| 177 | c.Ctx.Abort(status, code) | ||
| 178 | } else { | ||
| 179 | c.Ctx.Abort(200, code) | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | func (c *Controller) StopRun() { | ||
| 184 | panic("") | ||
| 182 | } | 185 | } |
| 183 | 186 | ||
| 184 | func (c *Controller) UrlFor(endpoint string, values ...string) string { | 187 | func (c *Controller) UrlFor(endpoint string, values ...string) string { | ... | ... |
middleware/profile.go
deleted
100644 → 0
| 1 | package middleware | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | "log" | ||
| 6 | "os" | ||
| 7 | "runtime" | ||
| 8 | "runtime/debug" | ||
| 9 | "runtime/pprof" | ||
| 10 | "strconv" | ||
| 11 | "sync/atomic" | ||
| 12 | "time" | ||
| 13 | ) | ||
| 14 | |||
| 15 | var heapProfileCounter int32 | ||
| 16 | var startTime = time.Now() | ||
| 17 | var pid int | ||
| 18 | |||
| 19 | func init() { | ||
| 20 | pid = os.Getpid() | ||
| 21 | } | ||
| 22 | |||
| 23 | func StartCPUProfile() { | ||
| 24 | f, err := os.Create("cpu-" + strconv.Itoa(pid) + ".pprof") | ||
| 25 | if err != nil { | ||
| 26 | log.Fatal(err) | ||
| 27 | } | ||
| 28 | pprof.StartCPUProfile(f) | ||
| 29 | } | ||
| 30 | |||
| 31 | func StopCPUProfile() { | ||
| 32 | pprof.StopCPUProfile() | ||
| 33 | } | ||
| 34 | |||
| 35 | func StartBlockProfile(rate int) { | ||
| 36 | runtime.SetBlockProfileRate(rate) | ||
| 37 | } | ||
| 38 | |||
| 39 | func StopBlockProfile() { | ||
| 40 | filename := "block-" + strconv.Itoa(pid) + ".pprof" | ||
| 41 | f, err := os.Create(filename) | ||
| 42 | if err != nil { | ||
| 43 | log.Fatal(err) | ||
| 44 | } | ||
| 45 | if err = pprof.Lookup("block").WriteTo(f, 0); err != nil { | ||
| 46 | log.Fatalf(" can't write %s: %s", filename, err) | ||
| 47 | } | ||
| 48 | f.Close() | ||
| 49 | } | ||
| 50 | |||
| 51 | func SetMemProfileRate(rate int) { | ||
| 52 | runtime.MemProfileRate = rate | ||
| 53 | } | ||
| 54 | |||
| 55 | func GC() { | ||
| 56 | runtime.GC() | ||
| 57 | } | ||
| 58 | |||
| 59 | func DumpHeap() { | ||
| 60 | filename := "heap-" + strconv.Itoa(pid) + "-" + strconv.Itoa(int(atomic.AddInt32(&heapProfileCounter, 1))) + ".pprof" | ||
| 61 | f, err := os.Create(filename) | ||
| 62 | if err != nil { | ||
| 63 | fmt.Fprintf(os.Stderr, "testing: %s", err) | ||
| 64 | return | ||
| 65 | } | ||
| 66 | if err = pprof.WriteHeapProfile(f); err != nil { | ||
| 67 | fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", filename, err) | ||
| 68 | } | ||
| 69 | f.Close() | ||
| 70 | } | ||
| 71 | |||
| 72 | func ShowGCStat() { | ||
| 73 | go func() { | ||
| 74 | var numGC int64 | ||
| 75 | |||
| 76 | interval := time.Duration(100) * time.Millisecond | ||
| 77 | gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)} | ||
| 78 | memStats := &runtime.MemStats{} | ||
| 79 | for { | ||
| 80 | debug.ReadGCStats(gcstats) | ||
| 81 | if gcstats.NumGC > numGC { | ||
| 82 | runtime.ReadMemStats(memStats) | ||
| 83 | |||
| 84 | printGC(memStats, gcstats) | ||
| 85 | numGC = gcstats.NumGC | ||
| 86 | } | ||
| 87 | time.Sleep(interval) | ||
| 88 | } | ||
| 89 | }() | ||
| 90 | } | ||
| 91 | |||
| 92 | func PrintGCSummary() { | ||
| 93 | memStats := &runtime.MemStats{} | ||
| 94 | runtime.ReadMemStats(memStats) | ||
| 95 | gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)} | ||
| 96 | debug.ReadGCStats(gcstats) | ||
| 97 | |||
| 98 | printGC(memStats, gcstats) | ||
| 99 | } | ||
| 100 | |||
| 101 | func printGC(memStats *runtime.MemStats, gcstats *debug.GCStats) { | ||
| 102 | |||
| 103 | if gcstats.NumGC > 0 { | ||
| 104 | lastPause := gcstats.Pause[0] | ||
| 105 | elapsed := time.Now().Sub(startTime) | ||
| 106 | overhead := float64(gcstats.PauseTotal) / float64(elapsed) * 100 | ||
| 107 | allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds() | ||
| 108 | |||
| 109 | fmt.Printf("NumGC:%d Pause:%s Pause(Avg):%s Overhead:%3.2f%% Alloc:%s Sys:%s Alloc(Rate):%s/s Histogram:%s %s %s \n", | ||
| 110 | gcstats.NumGC, | ||
| 111 | toS(lastPause), | ||
| 112 | toS(avg(gcstats.Pause)), | ||
| 113 | overhead, | ||
| 114 | toH(memStats.Alloc), | ||
| 115 | toH(memStats.Sys), | ||
| 116 | toH(uint64(allocatedRate)), | ||
| 117 | toS(gcstats.PauseQuantiles[94]), | ||
| 118 | toS(gcstats.PauseQuantiles[98]), | ||
| 119 | toS(gcstats.PauseQuantiles[99])) | ||
| 120 | } else { | ||
| 121 | // while GC has disabled | ||
| 122 | elapsed := time.Now().Sub(startTime) | ||
| 123 | allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds() | ||
| 124 | |||
| 125 | fmt.Printf("Alloc:%s Sys:%s Alloc(Rate):%s/s\n", | ||
| 126 | toH(memStats.Alloc), | ||
| 127 | toH(memStats.Sys), | ||
| 128 | toH(uint64(allocatedRate))) | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | func avg(items []time.Duration) time.Duration { | ||
| 133 | var sum time.Duration | ||
| 134 | for _, item := range items { | ||
| 135 | sum += item | ||
| 136 | } | ||
| 137 | return time.Duration(int64(sum) / int64(len(items))) | ||
| 138 | } | ||
| 139 | |||
| 140 | // human readable format | ||
| 141 | func toH(bytes uint64) string { | ||
| 142 | switch { | ||
| 143 | case bytes < 1024: | ||
| 144 | return fmt.Sprintf("%dB", bytes) | ||
| 145 | case bytes < 1024*1024: | ||
| 146 | return fmt.Sprintf("%.2fK", float64(bytes)/1024) | ||
| 147 | case bytes < 1024*1024*1024: | ||
| 148 | return fmt.Sprintf("%.2fM", float64(bytes)/1024/1024) | ||
| 149 | default: | ||
| 150 | return fmt.Sprintf("%.2fG", float64(bytes)/1024/1024/1024) | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | // short string format | ||
| 155 | func toS(d time.Duration) string { | ||
| 156 | |||
| 157 | u := uint64(d) | ||
| 158 | if u < uint64(time.Second) { | ||
| 159 | switch { | ||
| 160 | case u == 0: | ||
| 161 | return "0" | ||
| 162 | case u < uint64(time.Microsecond): | ||
| 163 | return fmt.Sprintf("%.2fns", float64(u)) | ||
| 164 | case u < uint64(time.Millisecond): | ||
| 165 | return fmt.Sprintf("%.2fus", float64(u)/1000) | ||
| 166 | default: | ||
| 167 | return fmt.Sprintf("%.2fms", float64(u)/1000/1000) | ||
| 168 | } | ||
| 169 | } else { | ||
| 170 | switch { | ||
| 171 | case u < uint64(time.Minute): | ||
| 172 | return fmt.Sprintf("%.2fs", float64(u)/1000/1000/1000) | ||
| 173 | case u < uint64(time.Hour): | ||
| 174 | return fmt.Sprintf("%.2fm", float64(u)/1000/1000/1000/60) | ||
| 175 | default: | ||
| 176 | return fmt.Sprintf("%.2fh", float64(u)/1000/1000/1000/60/60) | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | } |
| ... | @@ -376,6 +376,12 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -376,6 +376,12 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 376 | if !RecoverPanic { | 376 | if !RecoverPanic { |
| 377 | panic(err) | 377 | panic(err) |
| 378 | } else { | 378 | } else { |
| 379 | if ErrorsShow { | ||
| 380 | if handler, ok := middleware.ErrorMaps[fmt.Sprint(err)]; ok { | ||
| 381 | handler(rw, r) | ||
| 382 | return | ||
| 383 | } | ||
| 384 | } | ||
| 379 | var stack string | 385 | var stack string |
| 380 | Critical("Handler crashed with error", err) | 386 | Critical("Handler crashed with error", err) |
| 381 | for i := 1; ; i++ { | 387 | for i := 1; ; i++ { |
| ... | @@ -389,13 +395,14 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -389,13 +395,14 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 389 | middleware.ShowErr(err, rw, r, stack) | 395 | middleware.ShowErr(err, rw, r, stack) |
| 390 | } | 396 | } |
| 391 | } else { | 397 | } else { |
| 398 | if !RecoverPanic { | ||
| 399 | panic(err) | ||
| 400 | } else { | ||
| 401 | // in production model show all infomation | ||
| 392 | if ErrorsShow { | 402 | if ErrorsShow { |
| 393 | handler := p.getErrorHandler(fmt.Sprint(err)) | 403 | handler := p.getErrorHandler(fmt.Sprint(err)) |
| 394 | handler(rw, r) | 404 | handler(rw, r) |
| 395 | } else { | 405 | } else { |
| 396 | if !RecoverPanic { | ||
| 397 | panic(err) | ||
| 398 | } else { | ||
| 399 | Critical("Handler crashed with error", err) | 406 | Critical("Handler crashed with error", err) |
| 400 | for i := 1; ; i++ { | 407 | for i := 1; ; i++ { |
| 401 | _, file, line, ok := runtime.Caller(i) | 408 | _, file, line, ok := runtime.Caller(i) |
| ... | @@ -525,6 +532,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -525,6 +532,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 525 | // session init after static file | 532 | // session init after static file |
| 526 | if SessionOn { | 533 | if SessionOn { |
| 527 | context.Input.CruSession = GlobalSessions.SessionStart(w, r) | 534 | context.Input.CruSession = GlobalSessions.SessionStart(w, r) |
| 535 | defer context.Input.CruSession.SessionRelease() | ||
| 528 | } | 536 | } |
| 529 | 537 | ||
| 530 | if do_filter(AfterStatic) { | 538 | if do_filter(AfterStatic) { |
| ... | @@ -744,9 +752,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -744,9 +752,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 744 | if do_filter(AfterExec) { | 752 | if do_filter(AfterExec) { |
| 745 | goto Admin | 753 | goto Admin |
| 746 | } | 754 | } |
| 747 | |||
| 748 | method = vc.MethodByName("Destructor") | ||
| 749 | method.Call(in) | ||
| 750 | } | 755 | } |
| 751 | 756 | ||
| 752 | //start autorouter | 757 | //start autorouter |
| ... | @@ -835,9 +840,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -835,9 +840,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 835 | goto Admin | 840 | goto Admin |
| 836 | } | 841 | } |
| 837 | 842 | ||
| 838 | method = vc.MethodByName("Destructor") | ||
| 839 | method.Call(in) | ||
| 840 | |||
| 841 | goto Admin | 843 | goto Admin |
| 842 | } | 844 | } |
| 843 | } | 845 | } | ... | ... |
-
Please register or sign in to post a comment