Repository: alibaba/sentinel-golang
Pull request #365 (2020-12-28 03:46:18)

hotspot add mod:CLOSE;MONITOR;CONTROL
<!--  Thanks for submitting a pull request! Here are some tips for you:
1. Please make sure you have read and understood the contributing guidelines: https://github.com/alibaba/blob/master/CONTRIBUTING.md
2. Please make sure the PR has a corresponding issue.
-->

### Describe what this PR does / why we need it

Add hotspot rule mod field for meeting the needs of monitoring mode

### Does this pull request fix one issue?

NO
<!--If that, add "Fixes #xxxx" below in the next line. For example, Fixes #15. Otherwise, add "NONE" -->

### Describe how you did it


### Describe how to verify it


### Special notes for reviews

codecov-io: # [Codecov](https://codecov.io/gh/alibaba/sentinel-golang/pull/365?src=pr&el=h1) Report
> :exclamation: No coverage uploaded for pull request base (`mosn-customized@2a41098`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference#section-missing-base-commit).
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/alibaba/sentinel-golang/pull/365/graphs/tree.svg?width=650&height=150&src=pr&token=SrpzbhKA3E)](https://codecov.io/gh/alibaba/sentinel-golang/pull/365?src=pr&el=tree)

```diff
@@                Coverage Diff                 @@
##             mosn-customized     #365   +/-   ##
==================================================
  Coverage                   ?   49.93%           
==================================================
  Files                      ?       74           
  Lines                      ?     4087           
  Branches                   ?        0           
==================================================
  Hits                       ?     2041           
  Misses                     ?     1771           
  Partials                   ?      275           
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/alibaba/sentinel-golang/pull/365?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/alibaba/sentinel-golang/pull/365?src=pr&el=footer). Last update [2a41098...c318dab](https://codecov.io/gh/alibaba/sentinel-golang/pull/365?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/core/hotspot/rule.go b/core/hotspot/rule.go
index b726587..01af3d3 100644
--- a/core/hotspot/rule.go
+++ b/core/hotspot/rule.go
@@ -97,8 +97,20 @@ type Rule struct {
 	ParamsMaxCapacity int64 `json:"paramsMaxCapacity"`
 	// SpecificItems indicates the special threshold for specific value
 	SpecificItems map[interface{}]int64 `json:"specificItems"`
+	// Mode Switch
+	Mode Mode `json:"mode"`
 }
 
+// Mode represents the switch.
+type Mode string
+
+// defines the mode enum value
+const (
+	MONITOR Mode = "MONITOR"
+	CONTROL Mode = "CONTROL"
+	CLOSE   Mode = "CLOSE"
+)
+
 func (r *Rule) String() string {
 	b, err := json.Marshal(r)
 	if err != nil {
diff --git a/core/hotspot/rule_manager.go b/core/hotspot/rule_manager.go
index ee383c1..8a9a5f0 100644
--- a/core/hotspot/rule_manager.go
+++ b/core/hotspot/rule_manager.go
@@ -154,6 +154,10 @@ func onRuleUpdate(rules []*Rule) (err error) {
 			logging.Warn("[HotSpot onRuleUpdate] Ignoring invalid hotspot rule when loading new rules", "rule", r, "err", err.Error())
 			continue
 		}
+		if r.Mode == "" || r.Mode == CLOSE {
+			logging.Warn("[HotSpot onRuleUpdate] Ignoring Close hotspot rule when loading new rules", "rule", r)
+			continue
+		}
 		res := r.ResourceName()
 		ruleSet, ok := newRuleMap[res]
 		if !ok {
diff --git a/core/hotspot/slot.go b/core/hotspot/slot.go
index 95920b1..20beee6 100644
--- a/core/hotspot/slot.go
+++ b/core/hotspot/slot.go
@@ -56,6 +56,7 @@ func (s *Slot) Check(ctx *base.EntryContext) *base.TokenResult {
 		if args == nil || len(args) == 0 {
 			continue
 		}
+
 		for _, arg := range args {
 			arg := arg // https://golang.org/doc/faq#closures_and_goroutines
 			g.Go(func() error {
@@ -63,7 +64,12 @@ func (s *Slot) Check(ctx *base.EntryContext) *base.TokenResult {
 				if r == nil {
 					return nil
 				}
+
 				if r.Status() == base.ResultStatusBlocked {
+					if tc.BoundRule().Mode == MONITOR {
+						PutOutputAttachment(ctx, KeyIsMonitorBlocked, true)
+						return nil
+					}
 					return errors.Newf("concurrent canPassCheck err=%v", r.BlockError())
 				}
 				if r.Status() == base.ResultStatusShouldWait {
@@ -91,3 +97,12 @@ func canPassCheck(tc TrafficShapingController, arg interface{}, batch int64) *ba
 func canPassLocalCheck(tc TrafficShapingController, arg interface{}, batch int64) *base.TokenResult {
 	return tc.PerformChecking(arg, batch)
 }
+
+const KeyIsMonitorBlocked = "isMonitorBlocked"
+
+func PutOutputAttachment(ctx *base.EntryContext, key interface{}, value interface{}) {
+	if ctx.Data == nil {
+		ctx.Data = make(map[interface{}]interface{})
+	}
+	ctx.Data[key] = value
+}
diff --git a/core/hotspot/traffic_shaping.go b/core/hotspot/traffic_shaping.go
index 9f14f05..59c9e28 100644
--- a/core/hotspot/traffic_shaping.go
+++ b/core/hotspot/traffic_shaping.go
@@ -232,7 +232,6 @@ func (c *rejectTrafficShapingController) PerformChecking(arg interface{}, batchC
 	if metric == nil {
 		return nil
 	}
-
 	if c.metricType == Concurrency {
 		return c.performCheckingForConcurrencyMetric(arg)
 	} else if c.metricType > QPS {
diff --git a/example/hotspot_param_flow/qps_reject/hotspot_params_qps_reject_example.go b/example/hotspot_param_flow/qps_reject/hotspot_params_qps_reject_example.go
index 30e1d63..9120627 100644
--- a/example/hotspot_param_flow/qps_reject/hotspot_params_qps_reject_example.go
+++ b/example/hotspot_param_flow/qps_reject/hotspot_params_qps_reject_example.go
@@ -53,6 +53,7 @@ func main() {
 			Threshold:       50,
 			BurstCount:      0,
 			DurationInSec:   1,
+			Mode:            hotspot.CONTROL,
 		},
 		{
 			Resource:        "def",
@@ -62,6 +63,7 @@ func main() {
 			Threshold:       50,
 			BurstCount:      0,
 			DurationInSec:   1,
+			Mode:            hotspot.CONTROL,
 		},
 		{
 			Resource:        "efg",
@@ -71,6 +73,7 @@ func main() {
 			Threshold:       50,
 			BurstCount:      0,
 			DurationInSec:   1,
+			Mode:            hotspot.CONTROL,
 		},
 	})
 	if err != nil {


Test patch:
diff --git a/core/hotspot/rule_manager_test.go b/core/hotspot/rule_manager_test.go
index 9571dde..74af513 100644
--- a/core/hotspot/rule_manager_test.go
+++ b/core/hotspot/rule_manager_test.go
@@ -166,6 +166,7 @@ func Test_onRuleUpdate(t *testing.T) {
 		BurstCount:        10,
 		DurationInSec:     1,
 		SpecificItems:     specific,
+		Mode:              CONTROL,
 	}
 
 	specific2 := make(map[interface{}]int64)
@@ -182,6 +183,7 @@ func Test_onRuleUpdate(t *testing.T) {
 		BurstCount:        0,
 		DurationInSec:     1,
 		SpecificItems:     specific2,
+		Mode:              CONTROL,
 	}
 
 	specific3 := make(map[interface{}]int64)
@@ -198,6 +200,7 @@ func Test_onRuleUpdate(t *testing.T) {
 		BurstCount:        0,
 		DurationInSec:     1,
 		SpecificItems:     specific3,
+		Mode:              CONTROL,
 	}
 
 	r4 := &Rule{
@@ -211,6 +214,7 @@ func Test_onRuleUpdate(t *testing.T) {
 		BurstCount:        0,
 		DurationInSec:     2,
 		SpecificItems:     specific3,
+		Mode:              CONTROL,
 	}
 
 	updated, err := LoadRules([]*Rule{r1, r2, r3, r4})
@@ -230,6 +234,7 @@ func Test_onRuleUpdate(t *testing.T) {
 		BurstCount:        10,
 		DurationInSec:     1,
 		SpecificItems:     specific,
+		Mode:              CONTROL,
 	}
 	r22 := &Rule{
 		ID:                "22",
@@ -242,6 +247,7 @@ func Test_onRuleUpdate(t *testing.T) {
 		BurstCount:        0,
 		DurationInSec:     1,
 		SpecificItems:     specific2,
+		Mode:              CONTROL,
 	}
 	r23 := &Rule{
 		ID:                "23",
@@ -254,6 +260,7 @@ func Test_onRuleUpdate(t *testing.T) {
 		BurstCount:        0,
 		DurationInSec:     12,
 		SpecificItems:     specific3,
+		Mode:              CONTROL,
 	}
 
 	oldTc1Ptr := tcMap["abc"][0]
@@ -312,6 +319,7 @@ func TestLoadRules(t *testing.T) {
 				BurstCount:        10,
 				DurationInSec:     1,
 				SpecificItems:     specific,
+				Mode:              CLOSE,
 			},
 		})
 		assert.Nil(t, err)
@@ -327,6 +335,7 @@ func TestLoadRules(t *testing.T) {
 				BurstCount:        10,
 				DurationInSec:     1,
 				SpecificItems:     specific,
+				Mode:              CLOSE,
 			},
 		})
 		assert.Nil(t, err)
diff --git a/ext/datasource/helper_test.go b/ext/datasource/helper_test.go
index 3d55b26..accc4d7 100644
--- a/ext/datasource/helper_test.go
+++ b/ext/datasource/helper_test.go
@@ -434,6 +434,7 @@ func TestHotSpotParamRuleListJsonUpdater(t *testing.T) {
 			BurstCount:        10,
 			DurationInSec:     1,
 			SpecificItems:     m,
+			Mode:              hotspot.CONTROL,
 		}
 
 		m2 := make(map[interface{}]int64)
@@ -448,6 +449,7 @@ func TestHotSpotParamRuleListJsonUpdater(t *testing.T) {
 			BurstCount:        0,
 			DurationInSec:     1,
 			SpecificItems:     m2,
+			Mode:              hotspot.CONTROL,
 		}
 
 		m3 := make(map[interface{}]int64)
@@ -462,6 +464,7 @@ func TestHotSpotParamRuleListJsonUpdater(t *testing.T) {
 			BurstCount:        0,
 			DurationInSec:     1,
 			SpecificItems:     m3,
+			Mode:              hotspot.CONTROL,
 		}
 
 		r4 := &hotspot.Rule{
@@ -475,6 +478,7 @@ func TestHotSpotParamRuleListJsonUpdater(t *testing.T) {
 			BurstCount:        0,
 			DurationInSec:     2,
 			SpecificItems:     m3,
+			Mode:              hotspot.CONTROL,
 		}
 
 		err := HotSpotParamRulesUpdater([]*hotspot.Rule{r1, r2, r3, r4})