bugfix: update session param has a mistake (#576)

* add cache counter for login part.1

* add login counter api

* feature: prober support multi-metric with different tags

* bugfix: session counter reset

* add models.stats for counter

* bugfix: update session param has a mistake
This commit is contained in:
yubo 2021-02-03 15:00:14 +08:00 committed by GitHub
parent 2d9bc50401
commit e839c6bd6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 157 additions and 37 deletions

View File

@ -0,0 +1,9 @@
set names utf8;
use n9e_rdb;
CREATE TABLE `stats`
(
`name` varchar(64) not null,
`value` bigint not null default 0,
PRIMARY KEY (`name`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8;

View File

@ -355,3 +355,11 @@ CREATE TABLE `session` (
KEY (`username`),
KEY (`updated_at`)
) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8;
CREATE TABLE `stats`
(
`name` varchar(64) not null,
`value` bigint not null default 0,
PRIMARY KEY (`name`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8;

View File

@ -64,7 +64,7 @@ func SessionCleanupByUpdatedAt(ts int64) error {
return err
}
func (s *Session) Update(cols ...string) error {
_, err := DB["rdb"].Where("id=?", s.Sid).Cols(cols...).Update(s)
_, err := DB["rdb"].Where("sid=?", s.Sid).Cols(cols...).Update(s)
return err
}
@ -118,7 +118,6 @@ func SessionGetUserWithCache(sid string) (*User, error) {
return nil, fmt.Errorf("user not found")
}
return UserMustGet("username=?", s.Username)
}
func SessionTotal(where string, args ...interface{}) (int64, error) {

62
src/models/stats.go Normal file
View File

@ -0,0 +1,62 @@
package models
type Stats struct {
Name string `json:"name"`
Value int64 `json:"value"`
}
func NewStats(name string) (*Stats, error) {
c := Stats{Name: name}
has, err := DB["rdb"].Where("name=?", c.Name).Get(&c)
if err != nil {
return nil, err
}
if !has {
c.Save()
}
return &c, nil
}
func MustNewStats(name string) *Stats {
m, err := NewStats(name)
if err != nil {
panic(err)
}
return m
}
func (p *Stats) Get() int64 {
var s Stats
has, _ := DB["rdb"].Where("name=?", p.Name).Get(&s)
if !has {
p.Save()
}
return s.Value
}
func (p *Stats) Save() error {
_, err := DB["rdb"].Insert(p)
return err
}
func (p *Stats) Del() error {
_, err := DB["rdb"].Where("name=?", p.Name).Delete(p)
return err
}
// for GAUAGE
func (p *Stats) Update(i int64) error {
p.Value = i
_, err := DB["rdb"].Where("name=?", p.Name).Cols("value").Update(p)
return err
}
// for COUNTER
func (p *Stats) Inc(i int) error {
_, err := DB["rdb"].Exec("update stats set value = value + ? where name=?", i, p.Name)
return err
}

View File

@ -38,6 +38,11 @@ helo_stats_test_histogram_count{region="bj",zone="test_1"} 56
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 15 1490802350000
# HELP test_guage guage
# TYPE test_guage gauge
test_guauge{label="1"} 1.1
test_guauge{label="2"} 1.2
test_guauge{label="3"} 1.3
`
func TestCollect(t *testing.T) {

View File

@ -129,7 +129,7 @@ func (p *Metric) parse() (err error) {
return
}
func (p *Metric) Calc(vars map[string]*dataobj.MetricValue) (float64, error) {
func (p *Metric) Calc(vars map[string][]*dataobj.MetricValue) (float64, error) {
return p.notations.Calc(vars)
}

View File

@ -62,17 +62,17 @@ func (s *StackFloat) Push(f float64) { *s = append(*s, f) }
func (s *StackFloat) Pop() float64 { n := (*s)[len(*s)-1]; *s = (*s)[:len(*s)-1]; return n }
func (s *StackFloat) Len() int { return len(*s) }
func (rpn Notations) Calc(vars map[string]*dataobj.MetricValue) (float64, error) {
func (rpn Notations) Calc(vars map[string][]*dataobj.MetricValue) (float64, error) {
var s StackFloat
for i := 0; i < rpn.Len(); i++ {
tn := rpn[i]
switch tn.tokenType {
case tokenVar:
if v, ok := vars[tn.tokenVariable]; !ok {
if v, ok := vars[tn.tokenVariable]; !ok && len(v) == 0 {
return 0, fmt.Errorf("variable %s is not set", tn.tokenVariable)
} else {
logger.Debugf("get %s %f", tn.tokenVariable, v.Value)
s.Push(v.Value)
logger.Debugf("get %s %f", tn.tokenVariable, v[0].Value)
s.Push(v[0].Value)
}
case tokenConst:
s.Push(tn.tokenConst)

View File

@ -97,10 +97,15 @@ func (p *collectRule) prepareMetrics() (metrics []*dataobj.MetricValue, err erro
return
}
vars := map[string]*dataobj.MetricValue{}
vars := map[string][]*dataobj.MetricValue{}
for _, v := range metrics {
logger.Debugf("get v[%s] %f", v.Metric, v.Value)
vars[v.Metric] = v
if _, ok := vars[v.Metric]; ok {
vars[v.Metric] = []*dataobj.MetricValue{v}
} else {
vars[v.Metric] = append(vars[v.Metric], v)
}
}
metrics = metrics[:0]
@ -123,31 +128,33 @@ func (p *collectRule) prepareMetrics() (metrics []*dataobj.MetricValue, err erro
}
for k, v := range vars {
if metric, ok := pluginConfig.Metrics[k]; ok {
metrics = append(metrics, &dataobj.MetricValue{
Nid: nid,
Metric: k,
Timestamp: ts,
Step: p.Step,
CounterType: metric.Type,
TagsMap: v.TagsMap,
Value: v.Value,
ValueUntyped: v.ValueUntyped,
})
} else {
if pluginConfig.Mode == config.PluginModeWhitelist {
continue
for _, v2 := range v {
if metric, ok := pluginConfig.Metrics[k]; ok {
metrics = append(metrics, &dataobj.MetricValue{
Nid: nid,
Metric: k,
Timestamp: ts,
Step: p.Step,
CounterType: metric.Type,
TagsMap: v2.TagsMap,
Value: v2.Value,
ValueUntyped: v2.ValueUntyped,
})
} else {
if pluginConfig.Mode == config.PluginModeWhitelist {
continue
}
metrics = append(metrics, &dataobj.MetricValue{
Nid: nid,
Metric: k,
Timestamp: ts,
Step: p.Step,
CounterType: "GAUGE",
TagsMap: v2.TagsMap,
Value: v2.Value,
ValueUntyped: v2.ValueUntyped,
})
}
metrics = append(metrics, &dataobj.MetricValue{
Nid: nid,
Metric: k,
Timestamp: ts,
Step: p.Step,
CounterType: "GAUGE",
TagsMap: v.TagsMap,
Value: v.Value,
ValueUntyped: v.ValueUntyped,
})
}
}
return

View File

@ -370,7 +370,7 @@ func (p *Authenticator) updateUserStatus() {
now := time.Now().Unix()
if p.frozenTime > 0 {
// 3个月以上未登录用户自动变为休眠状态
if _, err := models.DB["rdb"].Exec("update user set status=?, updated_at=?, locked_at=? where ((logged_at > 0 and logged_at<?) or (logged_at == 0 and created_at < ?)) and status in (?,?,?)",
if _, err := models.DB["rdb"].Exec("update user set status=?, updated_at=?, locked_at=? where ((logged_at > 0 and logged_at<?) or (logged_at = 0 and created_at < ?)) and status in (?,?,?)",
models.USER_S_FROZEN, now, now, now-p.frozenTime,
models.USER_S_ACTIVE, models.USER_S_INACTIVE, models.USER_S_LOCKED); err != nil {
logger.Errorf("update user status error %s", err)

View File

@ -146,6 +146,8 @@ func sessionUsername(c *gin.Context) string {
}
func sessionLogin(c *gin.Context, username, remoteAddr, accessToken string) {
stats.Login.Inc(1)
s, ok := session.FromContext(c.Request.Context())
if !ok {
logger.Warningf("session.Start() err not found sessionStore")

View File

@ -39,6 +39,8 @@ func Start() {
Config(r)
initStats()
srv.Addr = address.GetHTTPListen("rdb")
srv.Handler = r

View File

@ -23,6 +23,7 @@ func Config(r *gin.Engine) {
notLogin.GET("/v2/nodes", nodeGets)
notLogin.GET("/pwd-rules", pwdRulesGet)
notLogin.GET("/counter", counterGet)
}

View File

@ -293,7 +293,7 @@ func authLogin(in *v1LoginInput) (user *models.User, err error) {
err = _e("Invalid login type %s", in.Type)
}
if user != nil {
if user != nil && in.RemoteAddr != "" {
if err := auth.WhiteListAccess(user, in.RemoteAddr); err != nil {
return nil, _e("Deny Access from %s with whitelist control", in.RemoteAddr)
}
@ -684,8 +684,7 @@ func v1SessionGet(c *gin.Context) {
}
func v1SessionGetUser(c *gin.Context) {
sid := urlParamStr(c, "sid")
user, err := models.SessionGetUserWithCache(sid)
user, err := models.SessionGetUserWithCache(urlParamStr(c, "sid"))
renderData(c, user, err)
}

View File

@ -0,0 +1,26 @@
package http
import (
"github.com/didi/nightingale/src/models"
"github.com/gin-gonic/gin"
)
type rdbStats struct {
Login *models.Stats
}
var (
stats *rdbStats
)
func initStats() {
stats = &rdbStats{
Login: models.MustNewStats("login"),
}
}
func counterGet(c *gin.Context) {
renderData(c, map[string]int64{
"login": stats.Login.Get(),
}, nil)
}