func runDashboard(addr string, httpLogFile string) { log.Info("dashboard listening on addr: ", addr) m := martini.Classic() f, err := os.OpenFile(httpLogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { Fatal(err) } defer f.Close() m.Map(stdlog.New(f, "[martini]", stdlog.LstdFlags)) binRoot, err := filepath.Abs(filepath.Dir(os.Args[0])) if err != nil { Fatal(err) } m.Use(martini.Static(filepath.Join(binRoot, "assets/statics"))) m.Use(render.Renderer(render.Options{ Directory: filepath.Join(binRoot, "assets/template"), Extensions: []string{".tmpl", ".html"}, Charset: "UTF-8", IndentJSON: true, })) m.Use(cors.Allow(&cors.Options{ AllowOrigins: []string{"*"}, AllowMethods: []string{"POST", "GET", "DELETE", "PUT"}, AllowHeaders: []string{"Origin", "x-requested-with", "Content-Type", "Content-Range", "Content-Disposition", "Content-Description"}, ExposeHeaders: []string{"Content-Length"}, AllowCredentials: false, })) m.Get("/api/server_groups", apiGetServerGroupList) m.Get("/api/overview", apiOverview) m.Get("/api/redis/:addr/stat", apiRedisStat) m.Get("/api/redis/:addr/:id/slotinfo", apiGetRedisSlotInfo) m.Get("/api/redis/group/:group_id/:slot_id/slotinfo", apiGetRedisSlotInfoFromGroupId) m.Put("/api/server_groups", binding.Json(models.ServerGroup{}), apiAddServerGroup) m.Put("/api/server_group/(?P<id>[0-9]+)/addServer", binding.Json(models.Server{}), apiAddServerToGroup) m.Delete("/api/server_group/(?P<id>[0-9]+)", apiRemoveServerGroup) m.Put("/api/server_group/(?P<id>[0-9]+)/removeServer", binding.Json(models.Server{}), apiRemoveServerFromGroup) m.Get("/api/server_group/(?P<id>[0-9]+)", apiGetServerGroup) m.Post("/api/server_group/(?P<id>[0-9]+)/promote", binding.Json(models.Server{}), apiPromoteServer) m.Get("/api/migrate/status", apiMigrateStatus) m.Get("/api/migrate/tasks", apiGetMigrateTasks) m.Post("/api/migrate", binding.Json(migrateTaskForm{}), apiDoMigrate) m.Post("/api/rebalance", apiRebalance) m.Get("/api/slot/list", apiGetSlots) m.Get("/api/slot/:id", apiGetSingleSlot) m.Post("/api/slots/init", apiInitSlots) m.Get("/api/slots", apiGetSlots) m.Post("/api/slot", binding.Json(RangeSetTask{}), apiSlotRangeSet) m.Get("/api/proxy/list", apiGetProxyList) m.Get("/api/proxy/debug/vars", apiGetProxyDebugVars) m.Post("/api/proxy", binding.Json(models.ProxyInfo{}), apiSetProxyStatus) m.Get("/api/action/gc", apiActionGC) m.Get("/api/force_remove_locks", apiForceRemoveLocks) m.Get("/api/remove_fence", apiRemoveFence) m.Get("/slots", pageSlots) m.Get("/", func(r render.Render) { r.Redirect("/admin") }) zkBuilder := utils.NewConnBuilder(globalEnv.NewZkConn) safeZkConn = zkBuilder.GetSafeConn() unsafeZkConn = zkBuilder.GetUnsafeConn() // create temp node in ZK if err := createDashboardNode(); err != nil { log.Fatal(err) // do not release dashborad node here } // create long live migrate manager globalMigrateManager = NewMigrateManager(safeZkConn, globalEnv.ProductName()) go func() { c := getProxySpeedChan() for { atomic.StoreInt64(&proxiesSpeed, <-c) } }() m.RunOnAddr(addr) }
func runDashboard(addr string, httpLogFile string) { log.Infof("dashboard listening on addr: %s", addr) m := martini.Classic() f, err := os.OpenFile(httpLogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { log.PanicErrorf(err, "open http log file failed") } defer f.Close() m.Map(stdlog.New(f, "[martini]", stdlog.LstdFlags)) binRoot, err := filepath.Abs(filepath.Dir(os.Args[0])) if err != nil { log.PanicErrorf(err, "get binroot path failed") } m.Use(martini.Static(filepath.Join(binRoot, "assets/statics"))) m.Use(render.Renderer(render.Options{ Directory: filepath.Join(binRoot, "assets/template"), Extensions: []string{".tmpl", ".html"}, Charset: "UTF-8", IndentJSON: true, })) m.Use(cors.Allow(&cors.Options{ AllowOrigins: []string{"*"}, AllowMethods: []string{"POST", "GET", "DELETE", "PUT"}, AllowHeaders: []string{"Origin", "x-requested-with", "Content-Type", "Content-Range", "Content-Disposition", "Content-Description"}, ExposeHeaders: []string{"Content-Length"}, AllowCredentials: false, })) m.Get("/api/server_groups", apiGetServerGroupList) m.Get("/api/overview", apiOverview) m.Get("/api/redis/:addr/stat", apiRedisStat) m.Get("/api/redis/:addr/:id/slotinfo", apiGetRedisSlotInfo) m.Get("/api/redis/group/:group_id/:slot_id/slotinfo", apiGetRedisSlotInfoFromGroupId) m.Put("/api/server_groups", binding.Json(models.ServerGroup{}), apiAddServerGroup) m.Put("/api/server_group/(?P<id>[0-9]+)/addServer", binding.Json(models.Server{}), apiAddServerToGroup) m.Delete("/api/server_group/(?P<id>[0-9]+)", apiRemoveServerGroup) m.Put("/api/server_group/(?P<id>[0-9]+)/removeServer", binding.Json(models.Server{}), apiRemoveServerFromGroup) m.Get("/api/server_group/(?P<id>[0-9]+)", apiGetServerGroup) m.Post("/api/server_group/(?P<id>[0-9]+)/promote", binding.Json(models.Server{}), apiPromoteServer) m.Get("/api/migrate/status", apiMigrateStatus) m.Get("/api/migrate/tasks", apiGetMigrateTasks) m.Post("/api/migrate", binding.Json(migrateTaskForm{}), apiDoMigrate) m.Post("/api/rebalance", apiRebalance) m.Get("/api/slot/list", apiGetSlots) m.Get("/api/slot/:id", apiGetSingleSlot) m.Post("/api/slots/init", apiInitSlots) m.Get("/api/slots", apiGetSlots) m.Post("/api/slot", binding.Json(RangeSetTask{}), apiSlotRangeSet) m.Get("/api/proxy/list", apiGetProxyList) m.Get("/api/proxy/debug/vars", apiGetProxyDebugVars) m.Post("/api/proxy", binding.Json(models.ProxyInfo{}), apiSetProxyStatus) m.Get("/api/action/gc", apiActionGC) m.Get("/api/force_remove_locks", apiForceRemoveLocks) m.Get("/api/remove_fence", apiRemoveFence) //m.Get("/api/action/gc", apiActionGC) m.Get("/slots", pageSlots) m.Get("/", func(r render.Render) { r.Redirect("/admin") }) //check key slot correspondence m.Get("/api/keyslot/(?P<key>.+)", apiKeySlot) m.Get("/api/remove_migration", apiRemoveMigration) m.Get("/api/remove_migration_fail", apiRemoveMigrationForFail) m.Get("/api/proxy/slowop", apiGetProxySlowop) zkBuilder := utils.NewConnBuilder(globalEnv.NewZkConn) safeZkConn = zkBuilder.GetSafeConn() unsafeZkConn = zkBuilder.GetUnsafeConn() // create temp node in ZK if err := createDashboardNode(); err != nil { log.WarnErrorf(err, "create zk node failed") // do not release dashborad node here } // create long live migrate manager globalMigrateManager = NewMigrateManager(safeZkConn, globalEnv.ProductName()) go func() { tick := time.Tick(time.Second) var lastCnt, qps int64 for _ = range tick { cnt := getAllProxyOps() if cnt > 0 { qps = cnt - lastCnt lastCnt = cnt } else { qps = 0 } atomic.StoreInt64(&proxiesSpeed, qps) } }() go func() { for { err := models.ActionGC(safeZkConn, globalEnv.ProductName(), models.GC_TYPE_SEC, 60*60*24) if err != nil { log.Warnf("clean actions failed %+v", err) } time.Sleep(60 * 60 * 24 * time.Second) } }() m.RunOnAddr(addr) }