diff --git a/context/context.go b/context/context.go index f13e4856..18d098f1 100644 --- a/context/context.go +++ b/context/context.go @@ -16,18 +16,24 @@ type Context struct { func (ctx *Context) Redirect(status int, localurl string) { ctx.Output.Header("Location", localurl) ctx.Output.SetStatus(status) + ctx.Output.Body([]byte(" ")) } func (ctx *Context) Abort(status int, body string) { ctx.Output.SetStatus(status) - ctx.Output.Body([]byte(body)) - + // first panic from ErrorMaps, is is user defined error functions. + if _, ok := middleware.ErrorMaps[body]; ok { + panic(body) + } + // second panic from HTTPExceptionMaps, it is system defined functions. if e, ok := middleware.HTTPExceptionMaps[status]; ok { if len(body) >= 1 { e.Description = body } panic(e) } + // last panic user string + panic(body) } func (ctx *Context) WriteString(content string) { diff --git a/controller.go b/controller.go index f5c59d7b..d5be2ef0 100644 --- a/controller.go +++ b/controller.go @@ -70,12 +70,6 @@ func (c *Controller) Finish() { } -func (c *Controller) Destructor() { - if c.CruSession != nil { - c.CruSession.SessionRelease() - } -} - func (c *Controller) Get() { http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405) } @@ -178,7 +172,16 @@ func (c *Controller) Redirect(url string, code int) { } func (c *Controller) Abort(code string) { - panic(code) + status, err := strconv.Atoi(code) + if err == nil { + c.Ctx.Abort(status, code) + } else { + c.Ctx.Abort(200, code) + } +} + +func (c *Controller) StopRun() { + panic("") } func (c *Controller) UrlFor(endpoint string, values ...string) string { diff --git a/middleware/profile.go b/middleware/profile.go deleted file mode 100644 index 0bb09058..00000000 --- a/middleware/profile.go +++ /dev/null @@ -1,180 +0,0 @@ -package middleware - -import ( - "fmt" - "log" - "os" - "runtime" - "runtime/debug" - "runtime/pprof" - "strconv" - "sync/atomic" - "time" -) - -var heapProfileCounter int32 -var startTime = time.Now() -var pid int - -func init() { - pid = os.Getpid() -} - -func StartCPUProfile() { - f, err := os.Create("cpu-" + strconv.Itoa(pid) + ".pprof") - if err != nil { - log.Fatal(err) - } - pprof.StartCPUProfile(f) -} - -func StopCPUProfile() { - pprof.StopCPUProfile() -} - -func StartBlockProfile(rate int) { - runtime.SetBlockProfileRate(rate) -} - -func StopBlockProfile() { - filename := "block-" + strconv.Itoa(pid) + ".pprof" - f, err := os.Create(filename) - if err != nil { - log.Fatal(err) - } - if err = pprof.Lookup("block").WriteTo(f, 0); err != nil { - log.Fatalf(" can't write %s: %s", filename, err) - } - f.Close() -} - -func SetMemProfileRate(rate int) { - runtime.MemProfileRate = rate -} - -func GC() { - runtime.GC() -} - -func DumpHeap() { - filename := "heap-" + strconv.Itoa(pid) + "-" + strconv.Itoa(int(atomic.AddInt32(&heapProfileCounter, 1))) + ".pprof" - f, err := os.Create(filename) - if err != nil { - fmt.Fprintf(os.Stderr, "testing: %s", err) - return - } - if err = pprof.WriteHeapProfile(f); err != nil { - fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", filename, err) - } - f.Close() -} - -func ShowGCStat() { - go func() { - var numGC int64 - - interval := time.Duration(100) * time.Millisecond - gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)} - memStats := &runtime.MemStats{} - for { - debug.ReadGCStats(gcstats) - if gcstats.NumGC > numGC { - runtime.ReadMemStats(memStats) - - printGC(memStats, gcstats) - numGC = gcstats.NumGC - } - time.Sleep(interval) - } - }() -} - -func PrintGCSummary() { - memStats := &runtime.MemStats{} - runtime.ReadMemStats(memStats) - gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)} - debug.ReadGCStats(gcstats) - - printGC(memStats, gcstats) -} - -func printGC(memStats *runtime.MemStats, gcstats *debug.GCStats) { - - if gcstats.NumGC > 0 { - lastPause := gcstats.Pause[0] - elapsed := time.Now().Sub(startTime) - overhead := float64(gcstats.PauseTotal) / float64(elapsed) * 100 - allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds() - - 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", - gcstats.NumGC, - toS(lastPause), - toS(avg(gcstats.Pause)), - overhead, - toH(memStats.Alloc), - toH(memStats.Sys), - toH(uint64(allocatedRate)), - toS(gcstats.PauseQuantiles[94]), - toS(gcstats.PauseQuantiles[98]), - toS(gcstats.PauseQuantiles[99])) - } else { - // while GC has disabled - elapsed := time.Now().Sub(startTime) - allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds() - - fmt.Printf("Alloc:%s Sys:%s Alloc(Rate):%s/s\n", - toH(memStats.Alloc), - toH(memStats.Sys), - toH(uint64(allocatedRate))) - } -} - -func avg(items []time.Duration) time.Duration { - var sum time.Duration - for _, item := range items { - sum += item - } - return time.Duration(int64(sum) / int64(len(items))) -} - -// human readable format -func toH(bytes uint64) string { - switch { - case bytes < 1024: - return fmt.Sprintf("%dB", bytes) - case bytes < 1024*1024: - return fmt.Sprintf("%.2fK", float64(bytes)/1024) - case bytes < 1024*1024*1024: - return fmt.Sprintf("%.2fM", float64(bytes)/1024/1024) - default: - return fmt.Sprintf("%.2fG", float64(bytes)/1024/1024/1024) - } -} - -// short string format -func toS(d time.Duration) string { - - u := uint64(d) - if u < uint64(time.Second) { - switch { - case u == 0: - return "0" - case u < uint64(time.Microsecond): - return fmt.Sprintf("%.2fns", float64(u)) - case u < uint64(time.Millisecond): - return fmt.Sprintf("%.2fus", float64(u)/1000) - default: - return fmt.Sprintf("%.2fms", float64(u)/1000/1000) - } - } else { - switch { - case u < uint64(time.Minute): - return fmt.Sprintf("%.2fs", float64(u)/1000/1000/1000) - case u < uint64(time.Hour): - return fmt.Sprintf("%.2fm", float64(u)/1000/1000/1000/60) - default: - return fmt.Sprintf("%.2fh", float64(u)/1000/1000/1000/60/60) - } - } - -} diff --git a/router.go b/router.go index d1eca546..442a4dbb 100644 --- a/router.go +++ b/router.go @@ -376,6 +376,12 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) if !RecoverPanic { panic(err) } else { + if ErrorsShow { + if handler, ok := middleware.ErrorMaps[fmt.Sprint(err)]; ok { + handler(rw, r) + return + } + } var stack string Critical("Handler crashed with error", err) for i := 1; ; i++ { @@ -389,12 +395,13 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) middleware.ShowErr(err, rw, r, stack) } } else { - if ErrorsShow { - handler := p.getErrorHandler(fmt.Sprint(err)) - handler(rw, r) + if !RecoverPanic { + panic(err) } else { - if !RecoverPanic { - panic(err) + // in production model show all infomation + if ErrorsShow { + handler := p.getErrorHandler(fmt.Sprint(err)) + handler(rw, r) } else { Critical("Handler crashed with error", err) for i := 1; ; i++ { @@ -525,6 +532,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) // session init after static file if SessionOn { context.Input.CruSession = GlobalSessions.SessionStart(w, r) + defer context.Input.CruSession.SessionRelease() } if do_filter(AfterStatic) { @@ -744,9 +752,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) if do_filter(AfterExec) { goto Admin } - - method = vc.MethodByName("Destructor") - method.Call(in) } //start autorouter @@ -835,9 +840,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) goto Admin } - method = vc.MethodByName("Destructor") - method.Call(in) - goto Admin } }