Skip to content

Commit

Permalink
Create the easeprobe.pid file & Accept HUP Signal to Rotate Log (me…
Browse files Browse the repository at this point in the history
…gaease#75)

* add easeprobe pid file

* merge two unit test into one to save the time

* configuration & README.md

* deal with HUP siginal rotate the log file

* exit if cannot create pid file

* set empty pidfile to disable pid file

* write the pid file without check process

* refactory the code to support both self-log and logrotate

* typo fix

* go fmt

* correct the README.md

* Update cmd/easeprobe/main.go

Co-authored-by: Pantelis Roditis <[email protected]>

* Update cmd/easeprobe/main.go

Co-authored-by: Pantelis Roditis <[email protected]>

* refine the sentences

* Update README.md

Co-authored-by: Pantelis Roditis <[email protected]>

* bug-fixing - deal with the stdout writer

Co-authored-by: Pantelis Roditis <[email protected]>
  • Loading branch information
haoel and proditis committed May 13, 2022
1 parent ba0c4f2 commit 74cd6ec
Show file tree
Hide file tree
Showing 12 changed files with 554 additions and 70 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,4 @@ jobs:
- name: Go Get dependencies
run: go get -v -t -d ./...
- name: Go Test
run: go test -cover ./...
- name: Go Race Test
run: go test -race ./...
run: go test -cover -race ./...
72 changes: 70 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ EaseProbe is a simple, standalone, and lightWeight tool that can do health/statu
- [1.1 Probe](#11-probe)
- [1.2 Notification](#12-notification)
- [1.3 Report](#13-report)
- [1.4 Administration](#14-administration)
- [2. Getting Started](#2-getting-started)
- [2.1 Build](#21-build)
- [2.2 Configure](#22-configure)
Expand Down Expand Up @@ -233,6 +234,61 @@ Check the [Notification Configuration](#37-notification-configuration) to see h

For more information, please check the [Global Setting Configuration](#38-global-setting-configuration)


### 1.4 Administration

There are some administration configuration options:

**1) PID file**

The EaseProbe would create a PID file (default `$CWD/easeprobe.pid`) when it starts. it can be configured by:

```YAML
settings:
pid: /var/run/easeprobe.pid
```

- If the file already exists, EaseProbe would overwrite it.
- If the file cannot be written, EaseProbe would exit with an error.

If you want to disable the PID file, you can configure the pid file to "".

```YAML
settings:
pid: "" # EaseProbe won't create a PID file
```

**2) Log file Rotation**

There are two types of log file: **Application Log** and **HTTP Access Log**.

Both Application Log and HTTP Access Log would be StdOut by default. They all can be configured by:

```YAML
log:
file: /path/to/log/file
self_rotate: true # default: true
```

If `self_rotate` is `true`, EaseProbe would rotate the log automatically, and the following options are available:

```YAML
size: 10 # max size of log file. default: 10M
age: 7 # max age days of log file. default: 7 days
backups: 5 # max backup log files. default: 5
compress: true # compress. default: true
```

If `self_rotate` is `false`, EaseProbe would not rotate the log, and the log file would be rotated by the 3rd-party tool (such as `logrotate`) or manually by the administrator.

```shell
mv /path/to/easeprobe.log /path/to/easeprobe.log.0
kill -HUP `cat /path/to/easeprobe.pid`
```

EaseProbe accepts the `HUP` signal to rotate the log.


## 2. Getting Started

### 2.1 Build
Expand Down Expand Up @@ -617,6 +673,12 @@ notify:
# Global settings for all probes and notifiers.
settings:

# Daemon settings

# pid file path, default: $CWD/easeprobe.pid,
# if set to "", will not create pid file.
pid: /var/run/easeprobe.pid

# A HTTP Server configuration
http:
ip: 127.0.0.1 # the IP address of the server. default:"0.0.0.0"
Expand All @@ -625,6 +687,9 @@ settings:
log:
file: /path/to/access.log # access log file. default: Stdout
# Log Rotate Configuration (optional)
self_rotate: true # true: self rotate log file. default: true
# false: managed by outside (e.g logrotate)
# the blow settings will be ignored.
size: 10 # max of access log file size. default: 10m
age: 7 # max of access log file age. default: 7 days
backups: 5 # max of access log file backups. default: 5
Expand Down Expand Up @@ -660,9 +725,12 @@ settings:
# Log Level Configuration
# can be: panic, fatal, error, warn, info, debug.
level: "debug"
# Log Rotate Configuration (optional)
# Log Rotate Configuration (optional)
self_rotate: true # true: self rotate log file. default: true
# false: managed by outside (e.g logrotate)
# the blow settings will be ignored.
size: 10 # max of access log file size. default: 10m
age: 7 # max of access log file age. default: 7 days
age: 7 # max of access log file age. default: 7 days
backups: 5 # max of access log file backups. default: 5
compress: true # compress the access log file. default: true

Expand Down
39 changes: 39 additions & 0 deletions cmd/easeprobe/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ import (
"flag"
"os"
"os/signal"
"strings"
"sync"
"syscall"
"time"

"github.com/megaease/easeprobe/conf"
"github.com/megaease/easeprobe/daemon"
"github.com/megaease/easeprobe/global"
"github.com/megaease/easeprobe/notify"
"github.com/megaease/easeprobe/probe"
Expand Down Expand Up @@ -54,6 +56,21 @@ func main() {
os.Exit(-1)
}

// Create the pid file if the file name is not empty
if len(strings.TrimSpace(c.Settings.PIDFile)) > 0 {
d, err := daemon.NewPIDFile(c.Settings.PIDFile)
if err != nil {
log.Fatalf("Fatal: Cannot create the PID file: %s!", err)
os.Exit(-1)
}
log.Infof("Successfully created the PID file: %s", d.PIDFile)
defer d.RemovePIDFile()
} else {
log.Info("Skipping PID file creation (pidfile empty).")
}

c.InitAllLogs()

// if dry notification mode is specificed in command line, overwrite the configuration
if *dryNotify {
c.Settings.Notify.Dry = *dryNotify
Expand Down Expand Up @@ -106,6 +123,27 @@ func main() {
signal.Notify(done, syscall.SIGTERM)
signal.Notify(done, syscall.SIGINT)

// Rotate the log file
rotateLog := make(chan os.Signal, 1)
doneRotate := make(chan bool, 1)
signal.Notify(rotateLog, syscall.SIGHUP)
go func() {
for {
c := conf.Get()
select {
case <-doneRotate:
log.Info("Received the exit signal, Rotating log file process exiting...")
c.Settings.Log.Close()
c.Settings.HTTPServer.AccessLog.Close()
return
case <-rotateLog:
log.Info("Received SIGHUP, rotating the log file...")
c.Settings.Log.Rotate()
c.Settings.HTTPServer.AccessLog.Rotate()
}
}
}()

select {
case <-done:
log.Infof("Received the exit signal, exiting...")
Expand All @@ -117,6 +155,7 @@ func main() {
wg.Wait()
doneWatch <- true
doneSave <- true
doneRotate <- true
}

log.Info("Graceful Exit Successfully!")
Expand Down
63 changes: 15 additions & 48 deletions conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ type HTTPServer struct {

// Settings is the EaseProbe configuration
type Settings struct {
PIDFile string `yaml:"pid"`
Log Log `yaml:"log"`
TimeFormat string `yaml:"timeformat"`
Probe Probe `yaml:"probe"`
Expand Down Expand Up @@ -176,7 +177,7 @@ func getYamlFile(path string) ([]byte, error) {
}

// New read the configuration from yaml
func New(conf *string) (Conf, error) {
func New(conf *string) (*Conf, error) {
c := Conf{
HTTP: []http.HTTP{},
TCP: []tcp.TCP{},
Expand All @@ -192,6 +193,7 @@ func New(conf *string) (Conf, error) {
},
Notify: notify.Config{},
Settings: Settings{
PIDFile: filepath.Join(global.GetWorkDir(), global.DefaultPIDFile),
Log: NewLog(),
TimeFormat: "2006-01-02 15:04:05 UTC",
Probe: Probe{
Expand Down Expand Up @@ -221,18 +223,18 @@ func New(conf *string) (Conf, error) {
y, err := getYamlFile(*conf)
if err != nil {
log.Errorf("error: %v ", err)
return c, err
return &c, err
}

y = []byte(os.ExpandEnv(string(y)))

err = yaml.Unmarshal(y, &c)
if err != nil {
log.Errorf("error: %v", err)
return c, err
return &c, err
}

c.Init()
c.initData()

ssh.BastionMap.ParseAllBastionHost()
host.BastionMap.ParseAllBastionHost()
Expand All @@ -249,45 +251,20 @@ func New(conf *string) (Conf, error) {
}
}

return c, err
return &c, err
}

// Init initialize the configuration
func (conf *Conf) Init() {
conf.initAppLog()
conf.initAccessLog()
conf.initData()
}
// InitAllLogs initialize all logs
func (conf *Conf) InitAllLogs() {

func (conf *Conf) initAppLog() {
log.SetFormatter(&log.TextFormatter{FullTimestamp: true})
if conf == nil {
log.SetOutput(os.Stdout)
log.SetLevel(log.InfoLevel)
return
}
conf.Settings.Log.InitLog(nil)
conf.Settings.Log.LogInfo("Application")

// if logfile is not set, use stdout
if conf.Settings.Log.File == "" {
log.Infoln("Using Standard Output as the log output...")
log.SetOutput(os.Stdout)
log.SetLevel(conf.Settings.Log.Level.GetLevel())
return
}
conf.Settings.HTTPServer.AccessLog.InitLog(log.New())
conf.Settings.HTTPServer.AccessLog.LogInfo("Web Access")
}

// open the log file
f, err := os.OpenFile(conf.Settings.Log.File, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0660)
if err != nil {
log.Warnf("Cannot open log file (%s): %v", conf.Settings.Log.File, err)
log.Infoln("Using Standard Output as the log output...")
log.SetOutput(os.Stdout)
} else {
f.Close()
conf.Settings.Log.CheckDefault()
log.Infof("Using %s as the log output...", conf.Settings.Log.File)
log.SetOutput(conf.Settings.Log.GetWriter())
}
log.SetLevel(conf.Settings.Log.Level.GetLevel())
func logLogfileInfo(name string, file string) {

}

Expand All @@ -311,16 +288,6 @@ func (conf *Conf) initData() {

}

func (conf *Conf) initAccessLog() {
filename := conf.Settings.HTTPServer.AccessLog.File
if filename != "" {
filename = global.MakeDirectory(filename)
log.Infof("Using %s as the access log output...", filename)
conf.Settings.HTTPServer.AccessLog.File = filename
conf.Settings.HTTPServer.AccessLog.CheckDefault()
}
}

// isProbe checks whether a interface is a probe type
func isProbe(t reflect.Type) bool {
modelType := reflect.TypeOf((*probe.Prober)(nil)).Elem()
Expand Down
Loading

0 comments on commit 74cd6ec

Please sign in to comment.