Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 9 additions & 28 deletions api/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,23 @@ import (
"github.com/alibaba/sentinel-golang/core/config"
"github.com/alibaba/sentinel-golang/core/log/metric"
"github.com/alibaba/sentinel-golang/core/system"
"github.com/alibaba/sentinel-golang/logging"
)

// InitDefault initializes Sentinel using the configuration from system
// environment and the default value.
func InitDefault() error {
return initSentinel("", "")
return initSentinel("")
}

// Init loads Sentinel general configuration from the given YAML file
// and initializes Sentinel. Note that the logging module will be initialized
// using the configuration from system environment or the default value.
func Init(configPath string) error {
return initSentinel(configPath, "")
return initSentinel(configPath)
}

// InitWithLogDir initializes Sentinel logging module with the given directory.
// Then it loads Sentinel general configuration from the given YAML file
// and initializes Sentinel.
func InitWithLogDir(configPath string, logDir string) error {
return initSentinel(configPath, logDir)
}

func initSentinel(configPath string, logDir string) (err error) {
// The priority: ENV > yaml file > default configuration
func initSentinel(configPath string) (err error) {
defer func() {
if r := recover(); r != nil {
var ok bool
Expand All @@ -38,24 +31,12 @@ func initSentinel(configPath string, logDir string) (err error) {
}
}
}()
err = config.InitConfig(configPath)
initCoreComponents()
return err
}

// First we initialize the logging module.
if logDir == "" {
err = logging.InitializeLogConfigFromEnv()
} else {
err = logging.InitializeLogConfig(logDir, true)
}
if err != nil {
return err
}
// Initialize the general configuration.
err = config.InitConfigFromFile(configPath)
if err != nil {
return err
}

func initCoreComponents() {
metric.InitTask()
system.InitCollector(config.SystemStatCollectIntervalMs())

return err
}
1 change: 1 addition & 0 deletions core/base/global_variable.go → core/base/constant.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package base

// global variable
const (
TotalInBoundResourceName = "__total_inbound_traffic__"

Expand Down
191 changes: 191 additions & 0 deletions core/config/configuration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
package config

import (
"fmt"
"github.com/alibaba/sentinel-golang/logging"
"github.com/alibaba/sentinel-golang/util"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
"io/ioutil"
"log"
"os"
"strconv"
"strings"
"sync"
)

var (
globalCfg = NewDefaultConfig()
initLogOnce sync.Once
)

func InitConfig(configPath string) error {
//Firstly, get config file path
if util.IsBlank(configPath) {
// If the config file path is absent, Sentinel will try to resolve it from the system env.
configPath = os.Getenv(ConfFilePathEnvKey)
}
if util.IsBlank(configPath) {
configPath = DefaultConfigFilename
}
// load config from yaml file
// if use don't set config path, then use default config
err := LoadFromYamlFile(configPath)
if err != nil {
return err
}
// Secondly, use variable from ENV to override config
err = OverrideFromSystemEnv()
if err != nil {
return err
}

err = InitializeLogConfig(LogBaseDir(), LogUsePid())
if err != nil {
return err
}
return nil
}


func LoadFromYamlFile(filePath string) error {
if filePath == DefaultConfigFilename {
if _, err := os.Stat(DefaultConfigFilename); err != nil {
//use default globalCfg.
return nil
}
}
_, err := os.Stat(filePath)
if err != nil && !os.IsExist(err){
return err
}
content, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
err = yaml.Unmarshal(content, globalCfg)
if err != nil {
return err
}
logging.GetDefaultLogger().Infof("Resolving Sentinel globalCfg from file: %s", filePath)
return checkValid(&(globalCfg.Sentinel))
}

func OverrideFromSystemEnv() error{
if appName := os.Getenv(AppNameEnvKey); !util.IsBlank(appName) {
globalCfg.Sentinel.App.Name = appName
}

if appTypeStr := os.Getenv(AppTypeEnvKey); !util.IsBlank(appTypeStr) {
appType, err := strconv.ParseInt(appTypeStr, 10, 32)
if err != nil {
return err
} else {
globalCfg.Sentinel.App.Type = int32(appType)
}
}

if addPidStr := os.Getenv(LogNamePidEnvKey); !util.IsBlank(addPidStr) {
addPid, err := strconv.ParseBool(addPidStr)
if err != nil {
return err
} else {
globalCfg.Sentinel.Log.UsePid = addPid
}
}

if logDir := os.Getenv(LogDirEnvKey); !util.IsBlank(logDir) {
if _, err := os.Stat(logDir); err != nil && !os.IsExist(err) {
return err
}
globalCfg.Sentinel.Log.Dir = logDir
}
return checkValid(&(globalCfg.Sentinel))
}

func InitializeLogConfig(logDir string, usePid bool) (err error) {
if logDir == "" {
return errors.New("Invalid empty log path")
}

initLogOnce.Do(func() {
if err = util.CreateDirIfNotExists(logDir); err != nil {
return
}
err = reconfigureRecordLogger(logDir, usePid)
})
return err
}

func reconfigureRecordLogger(logBaseDir string, withPid bool) error {
logDir := addSeparatorIfNeeded(logBaseDir)
filePath := logDir + logging.RecordLogFileName
if withPid {
filePath = filePath + ".pid" + strconv.Itoa(os.Getpid())
}

defaultLogger := logging.GetDefaultLogger()
if defaultLogger == nil {
return errors.New("Unexpected state: defaultLogger == nil")
}
logFile, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777)
if err != nil {
return err
}

// Note: not thread-safe!
logging.ResetDefaultLogger(log.New(logFile, "", log.LstdFlags), logging.DefaultNamespace)
fmt.Println("INFO: log base directory is: " + logDir)

return nil
}

func GetDefaultLogDir() string {
home, err := os.UserHomeDir()
if err != nil {
return ""
}
return addSeparatorIfNeeded(home) + logging.DefaultDirName
}

func addSeparatorIfNeeded(path string) string {
s := string(os.PathSeparator)
if !strings.HasSuffix(path, s) {
return path + s
}
return path
}



func AppName() string {
return globalCfg.Sentinel.App.Name
}

func AppType() int32 {
return globalCfg.Sentinel.App.Type
}

func LogBaseDir() string {
return globalCfg.Sentinel.Log.Dir
}

func LogUsePid() bool {
return globalCfg.Sentinel.Log.UsePid
}

func MetricLogFlushIntervalSec() uint32 {
return globalCfg.Sentinel.Log.Metric.FlushIntervalSec
}

func MetricLogSingleFileMaxSize() uint64 {
return globalCfg.Sentinel.Log.Metric.SingleFileMaxSize
}

func MetricLogMaxFileAmount() uint32 {
return globalCfg.Sentinel.Log.Metric.MaxFileCount
}

func SystemStatCollectIntervalMs() uint32 {
return globalCfg.Sentinel.Stat.System.CollectIntervalMs
}
69 changes: 69 additions & 0 deletions core/config/configuration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package config

import (
"os"
"testing"
)

const testDataBaseDir = "../../tests/testdata/config/"

func TestLoadFromYamlFile(t *testing.T) {
type args struct {
filePath string
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "TestLoadFromYamlFile",
args: args{
filePath: testDataBaseDir + "sentinel.yml",
},
wantErr: false,
},
{
name: "TestLoadFromYamlFile",
args: args{
filePath: testDataBaseDir + "sentinel.yml.1",
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := LoadFromYamlFile(tt.args.filePath); (err != nil) != tt.wantErr {
t.Errorf("LoadFromYamlFile() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

func TestOverrideFromSystemEnv(t *testing.T) {
tests := []struct {
name string
wantErr bool
}{
{
name: "TestOverrideFromSystemEnv",
wantErr: false,
},
}
err := LoadFromYamlFile(testDataBaseDir + "sentinel.yml")
if err != nil {
t.Errorf("Fail to initialize data.")
}
_ = os.Setenv(AppNameEnvKey, "app-name")
_ = os.Setenv(AppTypeEnvKey, "1")
_ = os.Setenv(LogDirEnvKey, testDataBaseDir + "sentinel.yml.2")
_ = os.Setenv(LogNamePidEnvKey, "true")

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := OverrideFromSystemEnv(); (err != nil) != tt.wantErr {
t.Errorf("OverrideFromSystemEnv() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
20 changes: 20 additions & 0 deletions core/config/constant.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package config

// configuration
const (
UnknownProjectName = "unknown_go_service"

ConfFilePathEnvKey = "SENTINEL_CONFIG_FILE_PATH"
AppNameEnvKey = "SENTINEL_APP_NAME"
AppTypeEnvKey = "SENTINEL_APP_TYPE"
LogDirEnvKey = "SENTINEL_LOG_DIR"
LogNamePidEnvKey = "SENTINEL_LOG_USE_PID"

DefaultConfigFilename = "sentinel.yml"
DefaultAppType int32 = 0

DefaultMetricLogFlushIntervalSec uint32 = 1
DefaultMetricLogSingleFileMaxSize uint64 = 1024 * 1024 * 50
DefaultMetricLogMaxFileAmount uint32 = 8
DefaultSystemStatCollectIntervalMs uint32 = 1000
)
Loading