You can now filter the active memory pane by type.
Add excludes for the analytics language pane too. Try to avoid rid queries when we already have the rids. Use GetListByCanSee instead of GetList for preloads to increase the chances of getting something useful. Provisionally extend topic preloading to the first three topic list pages. Add the panel_statistics_memory_type_total phrase. Add the panel_statistics_memory_type_stack phrase. Add the panel_statistics_memory_type_heap phrase.
This commit is contained in:
parent
8a719bd13d
commit
a56ed113dd
|
@ -307,6 +307,14 @@ type PanelAnalyticsStdUnit struct {
|
|||
Unit string
|
||||
TimeType string
|
||||
}
|
||||
type PanelAnalyticsActiveMemory struct {
|
||||
Graph PanelTimeGraph
|
||||
ViewItems []PanelAnalyticsItemUnit
|
||||
TimeRange string
|
||||
Unit string
|
||||
TimeType string
|
||||
MemType int
|
||||
}
|
||||
|
||||
type PanelStats struct {
|
||||
Users int
|
||||
|
|
|
@ -252,7 +252,7 @@ func compileCommons(c *tmpl.CTemplateSet, header *Header, header2 *Header, out T
|
|||
var replyList []*ReplyUser
|
||||
reply := Reply{1, 1, "Yo!", 1, Config.DefaultGroup, now, 0, 0, 1, "::1", true, 1, 1, ""}
|
||||
ru := &ReplyUser{ClassName: "", Reply: reply, CreatedByName: "Alice", Avatar: avatar, URLPrefix: "", URLName: "", Level: 0, Attachments: miniAttach}
|
||||
ru.Init(topic.ID)
|
||||
ru.Init()
|
||||
replyList = append(replyList, ru)
|
||||
tpage := TopicPage{htitle("Topic Name"), replyList, topic, &Forum{ID: 1, Name: "Hahaha"}, poll, Paginator{[]int{1}, 1, 1}}
|
||||
tpage.Forum.Link = BuildForumURL(NameToSlug(tpage.Forum.Name), tpage.Forum.ID)
|
||||
|
@ -268,19 +268,19 @@ func compileTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName string
|
|||
header, header2, _ := tmplInitHeaders(user, user2, user3)
|
||||
now := time.Now()
|
||||
|
||||
poll := Poll{ID: 1, Type: 0, Options: map[int]string{0: "Nothing", 1: "Something"}, Results: map[int]int{0: 5, 1: 2}, QuickOptions: []PollOption{
|
||||
/*poll := Poll{ID: 1, Type: 0, Options: map[int]string{0: "Nothing", 1: "Something"}, Results: map[int]int{0: 5, 1: 2}, QuickOptions: []PollOption{
|
||||
PollOption{0, "Nothing"},
|
||||
PollOption{1, "Something"},
|
||||
}, VoteCount: 7}
|
||||
avatar, microAvatar := BuildAvatar(62, "")
|
||||
}, VoteCount: 7}*/
|
||||
//avatar, microAvatar := BuildAvatar(62, "")
|
||||
miniAttach := []*MiniAttachment{&MiniAttachment{Path: "/"}}
|
||||
var replyList []*ReplyUser
|
||||
topic := TopicUser{1, "blah", "Blah", "Hey there!", 0, false, false, now, now, 1, 1, 0, "", "127.0.0.1", 1, 0, 1, 0, "classname", poll.ID, "weird-data", BuildProfileURL("fake-user", 62), "Fake User", Config.DefaultGroup, avatar, microAvatar, 0, "", "", "", "", "", 58, false, miniAttach, nil}
|
||||
//topic := TopicUser{1, "blah", "Blah", "Hey there!", 0, false, false, now, now, 1, 1, 0, "", "127.0.0.1", 1, 0, 1, 0, "classname", poll.ID, "weird-data", BuildProfileURL("fake-user", 62), "Fake User", Config.DefaultGroup, avatar, microAvatar, 0, "", "", "", "", "", 58, false, miniAttach, nil}
|
||||
// TODO: Do we want the UID on this to be 0?
|
||||
avatar, microAvatar = BuildAvatar(0, "")
|
||||
//avatar, microAvatar = BuildAvatar(0, "")
|
||||
reply := Reply{1, 1, "Yo!", 1, Config.DefaultGroup, now, 0, 0, 1, "::1", true, 1, 1, ""}
|
||||
ru := &ReplyUser{ClassName: "", Reply: reply, CreatedByName: "Alice", Avatar: avatar, URLPrefix: "", URLName: "", Level: 0, Attachments: miniAttach}
|
||||
ru.Init(topic.ID)
|
||||
ru := &ReplyUser{ClassName: "", Reply: reply, CreatedByName: "Alice", Avatar: "", URLPrefix: "", URLName: "", Level: 0, Attachments: miniAttach}
|
||||
ru.Init()
|
||||
replyList = append(replyList, ru)
|
||||
|
||||
// Convienience function to save a line here and there
|
||||
|
@ -477,7 +477,7 @@ func compileJSTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName stri
|
|||
avatar, microAvatar = BuildAvatar(0, "")
|
||||
reply := Reply{1, 1, "Yo!", 1, Config.DefaultGroup, now, 0, 0, 1, "::1", true, 1, 1, ""}
|
||||
ru := &ReplyUser{ClassName: "", Reply: reply, CreatedByName: "Alice", Avatar: avatar, URLPrefix: "", URLName: "", Level: 0, Attachments: miniAttach}
|
||||
ru.Init(topic.ID)
|
||||
ru.Init()
|
||||
replyList = append(replyList, ru)
|
||||
|
||||
varList = make(map[string]tmpl.VarItem)
|
||||
|
|
|
@ -422,9 +422,8 @@ func GetRidsForTopic(tid int, offset int) (rids []int, err error) {
|
|||
return rids, rows.Err()
|
||||
}
|
||||
|
||||
func (ru *ReplyUser) Init(parentID int) error {
|
||||
func (ru *ReplyUser) Init() error {
|
||||
ru.UserLink = BuildProfileURL(NameToSlug(ru.CreatedByName), ru.CreatedBy)
|
||||
ru.ParentID = parentID
|
||||
ru.ContentLines = strings.Count(ru.Content, "\n")
|
||||
|
||||
postGroup, err := Groups.Get(ru.Group)
|
||||
|
@ -516,7 +515,7 @@ func (topic *TopicUser) Replies(offset int, pFrag int, user *User) (rlist []*Rep
|
|||
//log.Print("reply cached serve")
|
||||
reply = &ReplyUser{ClassName: "", Reply: *re, CreatedByName: ruser.Name, Avatar: ruser.Avatar, URLPrefix: ruser.URLPrefix, URLName: ruser.URLName, Level: ruser.Level}
|
||||
|
||||
err := reply.Init(topic.ID)
|
||||
err := reply.Init()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
@ -554,7 +553,7 @@ func (topic *TopicUser) Replies(offset int, pFrag int, user *User) (rlist []*Rep
|
|||
return nil, "", err
|
||||
}
|
||||
|
||||
err = reply.Init(topic.ID)
|
||||
err = reply.Init()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
@ -596,8 +595,8 @@ func (topic *TopicUser) Replies(offset int, pFrag int, user *User) (rlist []*Rep
|
|||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var likeRid int
|
||||
for rows.Next() {
|
||||
err := rows.Scan(&likeRid)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
|
|
|
@ -2,6 +2,7 @@ package common
|
|||
|
||||
import (
|
||||
//"log"
|
||||
"database/sql"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
|
@ -308,7 +309,16 @@ func (tList *DefaultTopicList) getList(page int, orderby string, argList []inter
|
|||
//log.Print("rcap: ", rcap)
|
||||
//log.Print("topic.PostCount: ", topic.PostCount)
|
||||
//log.Print("topic.PostCount == 2 && rlen < rcap: ", topic.PostCount == 2 && rlen < rcap)
|
||||
if topic.PostCount == 2 && rlen < rcap {
|
||||
|
||||
// Avoid the extra queries on topic list pages, if we already have what we want...
|
||||
var hRids = false
|
||||
if tcache != nil {
|
||||
if t, err := tcache.Get(topic.ID); err == nil {
|
||||
hRids = len(t.Rids) != 0
|
||||
}
|
||||
}
|
||||
|
||||
if topic.PostCount == 2 && rlen < rcap && !hRids && page < 5 {
|
||||
rids, err := GetRidsForTopic(topic.ID, 0)
|
||||
if err != nil {
|
||||
return nil, Paginator{nil, 1, 1}, err
|
||||
|
@ -324,9 +334,11 @@ func (tList *DefaultTopicList) getList(page int, orderby string, argList []inter
|
|||
}
|
||||
|
||||
if tcache != nil {
|
||||
if _, err := tcache.Get(topic.ID); err == sql.ErrNoRows {
|
||||
_ = tcache.Set(topic.Topic())
|
||||
}
|
||||
}
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
return nil, Paginator{nil, 1, 1}, err
|
||||
|
|
|
@ -889,6 +889,9 @@
|
|||
|
||||
"panel_statistics_spam_hide":"Hide Spam",
|
||||
"panel_statistics_spam_show":"Show Spam",
|
||||
"panel_statistics_memory_type_total":"Total",
|
||||
"panel_statistics_memory_type_stack":"Stack",
|
||||
"panel_statistics_memory_type_heap":"Heap",
|
||||
|
||||
"panel_statistics_time_range_one_year":"1 year",
|
||||
"panel_statistics_time_range_three_months":"3 months",
|
||||
|
|
35
main.go
35
main.go
|
@ -64,17 +64,40 @@ func afterDBInit() (err error) {
|
|||
count = 0
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Use the same cached data for both the topic list and the topic fetches...
|
||||
tList, _, _, err := c.TopicList.GetList(1, "", nil)
|
||||
group, err := c.Groups.Get(c.GuestUser.Group)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if count > len(tList) {
|
||||
count = len(tList)
|
||||
|
||||
// TODO: Use the same cached data for both the topic list and the topic fetches...
|
||||
tList, _, _, err := c.TopicList.GetListByCanSee(group.CanSee, 1, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctList := make([]*c.TopicsRow, len(tList))
|
||||
copy(ctList, tList)
|
||||
|
||||
tList, _, _, err = c.TopicList.GetListByCanSee(group.CanSee, 2, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, tItem := range tList {
|
||||
ctList = append(ctList, tItem)
|
||||
}
|
||||
|
||||
tList, _, _, err = c.TopicList.GetListByCanSee(group.CanSee, 3, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, tItem := range tList {
|
||||
ctList = append(ctList, tItem)
|
||||
}
|
||||
|
||||
if count > len(ctList) {
|
||||
count = len(ctList)
|
||||
}
|
||||
for i := 0; i < count; i++ {
|
||||
_, _ = c.Topics.Get(tList[i].ID)
|
||||
_, _ = c.Topics.Get(ctList[i].ID)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ func analyticsRowsToAverageMap(rows *sql.Rows, labelList []int64, avgMap map[int
|
|||
return avgMap, rows.Err()
|
||||
}
|
||||
|
||||
func analyticsRowsToAverageMap2(rows *sql.Rows, labelList []int64, avgMap map[int64]int64) (map[int64]int64, error) {
|
||||
func analyticsRowsToAverageMap2(rows *sql.Rows, labelList []int64, avgMap map[int64]int64, typ int) (map[int64]int64, error) {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var stack, heap int64
|
||||
|
@ -175,6 +175,11 @@ func analyticsRowsToAverageMap2(rows *sql.Rows, labelList []int64, avgMap map[in
|
|||
log.Print("createdAt: ", createdAt)
|
||||
log.Print("unixCreatedAt: ", unixCreatedAt)
|
||||
}
|
||||
if typ == 1 {
|
||||
heap = 0
|
||||
} else if typ == 2 {
|
||||
stack = 0
|
||||
}
|
||||
var pAvgMap = make(map[int64]pAvg)
|
||||
for _, value := range labelList {
|
||||
if unixCreatedAt > value {
|
||||
|
@ -589,7 +594,17 @@ func AnalyticsActiveMemory(w http.ResponseWriter, r *http.Request, user c.User)
|
|||
if err != nil && err != sql.ErrNoRows {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
avgMap, err = analyticsRowsToAverageMap2(rows, labelList, avgMap)
|
||||
|
||||
var typ int
|
||||
switch r.FormValue("mtype") {
|
||||
case "1":
|
||||
typ = 1
|
||||
case "2":
|
||||
typ = 2
|
||||
default:
|
||||
typ = 0
|
||||
}
|
||||
avgMap, err = analyticsRowsToAverageMap2(rows, labelList, avgMap, typ)
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -604,7 +619,7 @@ func AnalyticsActiveMemory(w http.ResponseWriter, r *http.Request, user c.User)
|
|||
}
|
||||
graph := c.PanelTimeGraph{Series: [][]int64{avgList}, Labels: labelList}
|
||||
c.DebugLogf("graph: %+v\n", graph)
|
||||
pi := c.PanelAnalyticsStdUnit{graph, avgItems, timeRange.Range, timeRange.Unit, "time"}
|
||||
pi := c.PanelAnalyticsActiveMemory{graph, avgItems, timeRange.Range, timeRange.Unit, "time", typ}
|
||||
return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "panel_analytics_right", "analytics", "panel_analytics_active_memory", pi})
|
||||
}
|
||||
|
||||
|
@ -1012,19 +1027,35 @@ func AnalyticsLanguages(w http.ResponseWriter, r *http.Request, user c.User) c.R
|
|||
}
|
||||
ovList := analyticsVMapToOVList(vMap)
|
||||
|
||||
ex := strings.Split(r.FormValue("ex"), ",")
|
||||
var inEx = func(name string) bool {
|
||||
for _, e := range ex {
|
||||
if e == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var vList [][]int64
|
||||
var legendList []string
|
||||
var i int
|
||||
for _, ovitem := range ovList {
|
||||
if inEx(ovitem.name) {
|
||||
continue
|
||||
}
|
||||
lName, ok := phrases.GetHumanLangPhrase(ovitem.name)
|
||||
if !ok {
|
||||
lName = ovitem.name
|
||||
}
|
||||
if inEx(lName) {
|
||||
continue
|
||||
}
|
||||
var viewList []int64
|
||||
for _, value := range revLabelList {
|
||||
viewList = append(viewList, ovitem.viewMap[value])
|
||||
}
|
||||
vList = append(vList, viewList)
|
||||
lName, ok := phrases.GetHumanLangPhrase(ovitem.name)
|
||||
if !ok {
|
||||
lName = ovitem.name
|
||||
}
|
||||
legendList = append(legendList, lName)
|
||||
if i >= 6 {
|
||||
break
|
||||
|
@ -1038,10 +1069,16 @@ func AnalyticsLanguages(w http.ResponseWriter, r *http.Request, user c.User) c.R
|
|||
// TODO: Sort this slice
|
||||
var langItems []c.PanelAnalyticsAgentsItem
|
||||
for lang, count := range langMap {
|
||||
if inEx(lang) {
|
||||
continue
|
||||
}
|
||||
lLang, ok := phrases.GetHumanLangPhrase(lang)
|
||||
if !ok {
|
||||
lLang = lang
|
||||
}
|
||||
if inEx(lLang) {
|
||||
continue
|
||||
}
|
||||
langItems = append(langItems, c.PanelAnalyticsAgentsItem{
|
||||
Agent: lang,
|
||||
FriendlyAgent: lLang,
|
||||
|
|
|
@ -79,8 +79,8 @@ func ViewProfile(w http.ResponseWriter, r *http.Request, user c.User, header *c.
|
|||
|
||||
replyLiked := false
|
||||
replyLikeCount := 0
|
||||
ru := &c.ReplyUser{Reply: c.Reply{rid, 0, replyContent, replyCreatedBy, replyGroup, replyCreatedAt, replyLastEdit, replyLastEditBy, 0, "", replyLiked, replyLikeCount, 0, ""}, ContentHtml: c.ParseMessage(replyContent, 0, ""), CreatedByName: replyCreatedByName, Avatar: replyAvatar, Level: 0}
|
||||
ru.Init(puser.ID)
|
||||
ru := &c.ReplyUser{Reply: c.Reply{rid, puser.ID, replyContent, replyCreatedBy, replyGroup, replyCreatedAt, replyLastEdit, replyLastEditBy, 0, "", replyLiked, replyLikeCount, 0, ""}, ContentHtml: c.ParseMessage(replyContent, 0, ""), CreatedByName: replyCreatedByName, Avatar: replyAvatar, Level: 0}
|
||||
ru.Init()
|
||||
|
||||
group, err := c.Groups.Get(ru.Group)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{lang "panel_statistics_active_memory_head"}}</h1>
|
||||
<select form="timeRangeForm" class="typeSelector to_right autoSubmitRedirect" name="mtype">
|
||||
<option val="0"{{if eq .MemType 0}} selected{{end}}>{{lang "panel_statistics_memory_type_total"}}</option>
|
||||
<option val="1"{{if eq .MemType 1}} selected{{end}}>{{lang "panel_statistics_memory_type_stack"}}</option>
|
||||
<option val="2"{{if eq .MemType 2}} selected{{end}}>{{lang "panel_statistics_memory_type_heap"}}</option>
|
||||
</select>
|
||||
{{template "panel_analytics_time_range_month.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -357,7 +357,7 @@
|
|||
.analytics .colstack_head h1 {
|
||||
margin-top: 2px;
|
||||
}
|
||||
.spamSelector + .timeRangeSelector {
|
||||
select + .timeRangeSelector {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ button, .formbutton, .panel_right_button:not(.has_inner_button), #panel_users .p
|
|||
color: rgb(200,200,200);
|
||||
}*/
|
||||
|
||||
.spamSelector + .timeRangeSelector {
|
||||
select + .timeRangeSelector {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.spamSelector + .timeRangeSelector {
|
||||
select + .timeRangeSelector {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@
|
|||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.spamSelector + .timeRangeSelector {
|
||||
select + .timeRangeSelector {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue