Observatory related fixes (#788)

* fix:observatory not supported by multi-json

* Fix: observatory starts with empty config & fails to close (#957)

* Update strategy_leastping.go (#1019)

* add custom probe URL support for observatory

* add custom probe interval for observer

* apply coding style

* Fix: observatory log & JSON config(#1211)

Co-authored-by: ihotte <ihotte@yeah.net>

* Change default probe url from api.v2fly.org to www.google.com

* Cherry-pick missing code from branch 'dev-advloadblancer-2'

Co-authored-by: Shelikhoo <xiaokangwang@outlook.com>
Co-authored-by: Loyalsoldier <10487845+Loyalsoldier@users.noreply.github.com>
Co-authored-by: fanyiguan <52657276+fanyiguang@users.noreply.github.com>
Co-authored-by: ihotte <3087168217@qq.com>
Co-authored-by: ihotte <ihotte@yeah.net>
This commit is contained in:
yuhan6665 2021-10-26 01:00:31 -04:00 committed by GitHub
parent 7038bded7b
commit abb8ba8b0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 601 additions and 22 deletions

View file

@ -5,6 +5,7 @@ import (
"github.com/xtls/xray-core/app/commander"
loggerservice "github.com/xtls/xray-core/app/log/command"
observatoryservice "github.com/xtls/xray-core/app/observatory/command"
handlerservice "github.com/xtls/xray-core/app/proxyman/command"
statsservice "github.com/xtls/xray-core/app/stats/command"
"github.com/xtls/xray-core/common/serial"
@ -31,6 +32,8 @@ func (c *APIConfig) Build() (*commander.Config, error) {
services = append(services, serial.ToTypedMessage(&loggerservice.Config{}))
case "statsservice":
services = append(services, serial.ToTypedMessage(&statsservice.Config{}))
case "observatoryservice":
services = append(services, serial.ToTypedMessage(&observatoryservice.Config{}))
}
}

View file

@ -0,0 +1,33 @@
package duration
import (
"encoding/json"
"fmt"
"time"
)
type Duration int64
func (d *Duration) MarshalJSON() ([]byte, error) {
dr := time.Duration(*d)
return json.Marshal(dr.String())
}
func (d *Duration) UnmarshalJSON(b []byte) error {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
switch value := v.(type) {
case string:
var err error
dr, err := time.ParseDuration(value)
if err != nil {
return err
}
*d = Duration(dr)
return nil
default:
return fmt.Errorf("invalid duration: %v", v)
}
}

View file

@ -0,0 +1,33 @@
package duration_test
import (
"encoding/json"
"testing"
"time"
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
)
type testWithDuration struct {
Duration duration.Duration
}
func TestDurationJSON(t *testing.T) {
expected := &testWithDuration{
Duration: duration.Duration(time.Hour),
}
data, err := json.Marshal(expected)
if err != nil {
t.Error(err)
return
}
actual := &testWithDuration{}
err = json.Unmarshal(data, &actual)
if err != nil {
t.Error(err)
return
}
if actual.Duration != expected.Duration {
t.Errorf("expected: %s, actual: %s", time.Duration(expected.Duration), time.Duration(actual.Duration))
}
}

View file

@ -2,13 +2,17 @@ package conf
import (
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
)
type ObservatoryConfig struct {
SubjectSelector []string `json:"subjectSelector"`
SubjectSelector []string `json:"subjectSelector"`
ProbeURL string `json:"probeURL"`
ProbeInterval duration.Duration `json:"probeInterval"`
}
func (o ObservatoryConfig) Build() (proto.Message, error) {
return &observatory.Config{SubjectSelector: o.SubjectSelector}, nil
func (o *ObservatoryConfig) Build() (proto.Message, error) {
return &observatory.Config{SubjectSelector: o.SubjectSelector, ProbeUrl: o.ProbeURL, ProbeInterval: int64(o.ProbeInterval)}, nil
}

View file

@ -18,9 +18,16 @@ type RouterRulesConfig struct {
DomainStrategy string `json:"domainStrategy"`
}
// StrategyConfig represents a strategy config
type StrategyConfig struct {
Type string `json:"type"`
Settings *json.RawMessage `json:"settings"`
}
type BalancingRule struct {
Tag string `json:"tag"`
Selectors StringList `json:"selector"`
Tag string `json:"tag"`
Selectors StringList `json:"selector"`
Strategy StrategyConfig `json:"strategy"`
}
func (r *BalancingRule) Build() (*router.BalancingRule, error) {
@ -31,9 +38,20 @@ func (r *BalancingRule) Build() (*router.BalancingRule, error) {
return nil, newError("empty selector list")
}
var strategy string
switch strings.ToLower(r.Strategy.Type) {
case strategyRandom, "":
strategy = strategyRandom
case strategyLeastPing:
strategy = "leastPing"
default:
return nil, newError("unknown balancing strategy: " + r.Strategy.Type)
}
return &router.BalancingRule{
Tag: r.Tag,
OutboundSelector: []string(r.Selectors),
Strategy: strategy,
}, nil
}

View file

@ -0,0 +1,6 @@
package conf
const (
strategyRandom string = "random"
strategyLeastPing string = "leastping"
)

View file

@ -107,6 +107,7 @@ func TestRouterConfig(t *testing.T) {
{
Tag: "b1",
OutboundSelector: []string{"test"},
Strategy: "random",
},
},
Rule: []*router.RoutingRule{

View file

@ -464,6 +464,10 @@ func (c *Config) Override(o *Config, fn string) {
c.FakeDNS = o.FakeDNS
}
if o.Observatory != nil {
c.Observatory = o.Observatory
}
// deprecated attrs... keep them for now
if o.InboundConfig != nil {
c.InboundConfig = o.InboundConfig