mirror of https://github.com/statping/statping
				
				
				
			Merge branch 'dev' into gotify-notify
						commit
						2f8fd9197d
					
				|  | @ -310,25 +310,16 @@ jobs: | |||
|         run: echo ::set-env name=VERSION::$(cat version.txt) | ||||
|         shell: bash | ||||
| 
 | ||||
|       - name: Base Docker Image | ||||
|         uses: elgohr/Publish-Docker-Github-Action@master | ||||
|         with: | ||||
|           name: statping/statping | ||||
|           username: ${{ secrets.DOCKER_USERNAME }} | ||||
|           password: ${{ secrets.DOCKER_PASSWORD }} | ||||
|           dockerfile: Dockerfile.base | ||||
|           tags: "base" | ||||
|       - name: Set up Docker Buildx | ||||
|         uses: crazy-max/ghaction-docker-buildx@v3 | ||||
| 
 | ||||
|       - name: Dev Docker Image | ||||
|         uses: elgohr/Publish-Docker-Github-Action@master | ||||
|       - name: Docker Login | ||||
|         env: | ||||
|           VERSION: ${{ env.VERSION }} | ||||
|           ARCH: amd64 | ||||
|           DOCKER_CLI_EXPERIMENTAL: enabled | ||||
|         with: | ||||
|           name: statping/statping | ||||
|           username: ${{ secrets.DOCKER_USERNAME }} | ||||
|           password: ${{ secrets.DOCKER_PASSWORD }} | ||||
|           dockerfile: Dockerfile | ||||
|           tags: "dev" | ||||
|           buildargs: VERSION,ARCH | ||||
|           DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} | ||||
|           DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | ||||
|         run: echo "${DOCKER_PASSWORD}" | docker login --username "${DOCKER_USERNAME}" --password-stdin | ||||
| 
 | ||||
|       - name: Docker Buildx (push) | ||||
|         run: | | ||||
|           docker buildx create --use | ||||
|           docker buildx build --tag=statping/statping:dev --build-arg=VERSION=${VERSION} --platform=linux/amd64,linux/386,linux/arm64,linux/arm/v7,darwin/amd64 --output type=image,name=docker.io/statping/statping,push=true . | ||||
|  |  | |||
|  | @ -412,28 +412,19 @@ jobs: | |||
|         run: echo ::set-env name=VERSION::$(cat version.txt) | ||||
|         shell: bash | ||||
| 
 | ||||
|       - name: Base Docker Image | ||||
|         uses: elgohr/Publish-Docker-Github-Action@master | ||||
|         with: | ||||
|           name: statping/statping | ||||
|           username: ${{ secrets.DOCKER_USERNAME }} | ||||
|           password: ${{ secrets.DOCKER_PASSWORD }} | ||||
|           dockerfile: Dockerfile.base | ||||
|           tags: "base" | ||||
|       - name: Set up Docker Buildx | ||||
|         uses: crazy-max/ghaction-docker-buildx@v3 | ||||
| 
 | ||||
|       - name: Latest/Version Docker Image | ||||
|         uses: elgohr/Publish-Docker-Github-Action@master | ||||
|       - name: Docker Login | ||||
|         env: | ||||
|           VERSION: ${{ env.VERSION }} | ||||
|           ARCH: amd64 | ||||
|           DOCKER_CLI_EXPERIMENTAL: enabled | ||||
|         with: | ||||
|           name: statping/statping | ||||
|           username: ${{ secrets.DOCKER_USERNAME }} | ||||
|           password: ${{ secrets.DOCKER_PASSWORD }} | ||||
|           dockerfile: Dockerfile | ||||
|           tags: "latest,v${{ env.VERSION }}" | ||||
|           buildargs: VERSION,ARCH | ||||
|           DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} | ||||
|           DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | ||||
|         run: echo "${DOCKER_PASSWORD}" | docker login --username "${DOCKER_USERNAME}" --password-stdin | ||||
| 
 | ||||
|       - name: Docker Buildx (push) | ||||
|         run: | | ||||
|           docker buildx create --use | ||||
|           docker buildx build --tag=statping/statping,statping/statping:v${VERSION} --build-arg=VERSION=${VERSION} --platform=linux/amd64,linux/386,linux/arm64,linux/arm/v7,darwin/amd64 --output type=image,name=docker.io/statping/statping,push=true . | ||||
| 
 | ||||
|   sentry-release: | ||||
|     needs: upload-release | ||||
|  |  | |||
|  | @ -1,3 +1,8 @@ | |||
| # 0.90.58 (07-09-2020) | ||||
| - Fixed ICMP latency/ping durations | ||||
| - Fixed webhook notifier | ||||
| - Modified file structure for Vue admin dashboard components. | ||||
| 
 | ||||
| # 0.90.57 (07-04-2020) | ||||
| - Fixed login issue | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										6
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										6
									
								
								Makefile
								
								
								
								
							|  | @ -331,5 +331,9 @@ certs: | |||
| 	  -keyout key.pem \
 | ||||
| 	  -subj "/C=US/ST=California/L=Santa Monica/O=Statping/OU=Development/CN=localhost" | ||||
| 
 | ||||
| .PHONY: all build build-all build-alpine test-all test test-api docker frontend up down print_details lite sentry-release snapcraft build-linux build-mac build-win build-all postman | ||||
| buildx: | ||||
| 	docker buildx create --use | ||||
| 	docker buildx build --tag=statping/statping:dev --build-arg=VERSION=${VERSION} --platform=linux/amd64,linux/386,linux/arm64,linux/arm/v7 --output type=image,name=docker.io/statping/statping,push=true . | ||||
| 
 | ||||
| .PHONY: all build build-all buildx build-alpine test-all test test-api docker frontend up down print_details lite sentry-release snapcraft build-linux build-mac build-win build-all postman | ||||
| .SILENT: travis_s3_creds | ||||
|  |  | |||
							
								
								
									
										61
									
								
								cmd/cli.go
								
								
								
								
							
							
						
						
									
										61
									
								
								cmd/cli.go
								
								
								
								
							|  | @ -153,8 +153,10 @@ func onceCli() error { | |||
| func importCli(args []string) error { | ||||
| 	var err error | ||||
| 	var data []byte | ||||
| 	filename := args[1] | ||||
| 	if data, err = ioutil.ReadFile(filename); err != nil { | ||||
| 	if len(args) < 1 { | ||||
| 		return errors.New("invalid command arguments") | ||||
| 	} | ||||
| 	if data, err = ioutil.ReadFile(args[0]); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	var exportData ExportData | ||||
|  | @ -162,11 +164,40 @@ func importCli(args []string) error { | |||
| 		return err | ||||
| 	} | ||||
| 	log.Printf("=== %s ===\n", exportData.Core.Name) | ||||
| 	log.Printf("Services:   %d\n", len(exportData.Services)) | ||||
| 	log.Printf("Checkins:   %d\n", len(exportData.Checkins)) | ||||
| 	log.Printf("Groups:     %d\n", len(exportData.Groups)) | ||||
| 	log.Printf("Messages:   %d\n", len(exportData.Messages)) | ||||
| 	log.Printf("Users:      %d\n", len(exportData.Users)) | ||||
| 	if exportData.Config != nil { | ||||
| 		log.Printf("Configs:     %s\n", exportData.Config.DbConn) | ||||
| 		if exportData.Config.DbUser != "" { | ||||
| 			log.Printf("   - Host:   %s\n", exportData.Config.DbHost) | ||||
| 			log.Printf("   - User:   %s\n", exportData.Config.DbUser) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(exportData.Services) > 0 { | ||||
| 		log.Printf("Services:   %d\n", len(exportData.Services)) | ||||
| 	} | ||||
| 	if len(exportData.Checkins) > 0 { | ||||
| 		log.Printf("Checkins:   %d\n", len(exportData.Checkins)) | ||||
| 	} | ||||
| 	if len(exportData.Groups) > 0 { | ||||
| 		log.Printf("Groups:     %d\n", len(exportData.Groups)) | ||||
| 	} | ||||
| 	if len(exportData.Messages) > 0 { | ||||
| 		log.Printf("Messages:   %d\n", len(exportData.Messages)) | ||||
| 	} | ||||
| 	if len(exportData.Users) > 0 { | ||||
| 		log.Printf("Users:      %d\n", len(exportData.Users)) | ||||
| 	} | ||||
| 
 | ||||
| 	if exportData.Config != nil { | ||||
| 		if ask("Create config.yml file from Configs?") { | ||||
| 			log.Printf("Database User:   %s\n", exportData.Config.DbUser) | ||||
| 			log.Printf("Database Password:   %s\n", exportData.Config.DbPass) | ||||
| 			log.Printf("Database Host:   %s\n", exportData.Config.DbHost) | ||||
| 			log.Printf("Database Port:   %d\n", exportData.Config.DbPort) | ||||
| 			if err := exportData.Config.Save(utils.Directory); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	config, err := configs.LoadConfigs(configFile) | ||||
| 	if err != nil { | ||||
|  | @ -175,8 +206,10 @@ func importCli(args []string) error { | |||
| 	if err = configs.ConnectConfigs(config, false); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if data, err = ExportSettings(); err != nil { | ||||
| 		return fmt.Errorf("could not export settings: %v", err.Error()) | ||||
| 	if ask("Create database rows and sample data?") { | ||||
| 		if err := config.ResetCore(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if ask("Import Core settings?") { | ||||
|  | @ -221,7 +254,7 @@ func importCli(args []string) error { | |||
| 		if ask(fmt.Sprintf("Import User '%s'?", s.Username)) { | ||||
| 			s.Id = 0 | ||||
| 			if err := s.Create(); err != nil { | ||||
| 				return err | ||||
| 				log.Errorln(err) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | @ -376,6 +409,7 @@ type gitUploader struct { | |||
| // ExportChartsJs renders the charts for the index page
 | ||||
| 
 | ||||
| type ExportData struct { | ||||
| 	Config    *configs.DbConfig   `json:"config"` | ||||
| 	Core      *core.Core          `json:"core"` | ||||
| 	Services  []services.Service  `json:"services"` | ||||
| 	Messages  []*messages.Message `json:"messages"` | ||||
|  | @ -403,7 +437,14 @@ func ExportSettings() ([]byte, error) { | |||
| 		s.Failures = nil | ||||
| 		srvs = append(srvs, s) | ||||
| 	} | ||||
| 
 | ||||
| 	cfg, err := configs.LoadConfigs(configFile) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	data := ExportData{ | ||||
| 		Config:    cfg, | ||||
| 		Core:      c, | ||||
| 		Notifiers: core.App.Notifications, | ||||
| 		Checkins:  checkins.All(), | ||||
|  |  | |||
							
								
								
									
										35
									
								
								cmd/main.go
								
								
								
								
							
							
						
						
									
										35
									
								
								cmd/main.go
								
								
								
								
							|  | @ -96,39 +96,8 @@ func start() { | |||
| 		exit(err) | ||||
| 	} | ||||
| 
 | ||||
| 	if !confgs.Db.HasTable("core") { | ||||
| 		var srvs int64 | ||||
| 		if confgs.Db.HasTable(&services.Service{}) { | ||||
| 			confgs.Db.Model(&services.Service{}).Count(&srvs) | ||||
| 			if srvs > 0 { | ||||
| 				exit(errors.Wrap(err, "there are already services setup.")) | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if err := confgs.DropDatabase(); err != nil { | ||||
| 			exit(errors.Wrap(err, "error dropping database")) | ||||
| 		} | ||||
| 
 | ||||
| 		if err := confgs.CreateDatabase(); err != nil { | ||||
| 			exit(errors.Wrap(err, "error creating database")) | ||||
| 		} | ||||
| 
 | ||||
| 		if err := configs.CreateAdminUser(confgs); err != nil { | ||||
| 			exit(errors.Wrap(err, "error creating default admin user")) | ||||
| 		} | ||||
| 
 | ||||
| 		if utils.Params.GetBool("SAMPLE_DATA") { | ||||
| 			log.Infoln("Adding Sample Data") | ||||
| 			if err := configs.TriggerSamples(); err != nil { | ||||
| 				exit(errors.Wrap(err, "error adding sample data")) | ||||
| 			} | ||||
| 		} else { | ||||
| 			if err := core.Samples(); err != nil { | ||||
| 				exit(errors.Wrap(err, "error added core details")) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 	if err = confgs.ResetCore(); err != nil { | ||||
| 		exit(err) | ||||
| 	} | ||||
| 
 | ||||
| 	if err = confgs.DatabaseChanges(); err != nil { | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ | |||
| </template> | ||||
| 
 | ||||
| <script> | ||||
|   const ServiceInfo = () => import('@/components/Service/ServiceInfo') | ||||
|   const ServiceInfo = () => import('@/components/Dashboard/ServiceInfo') | ||||
| 
 | ||||
|   export default { | ||||
|       name: 'DashboardIndex', | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ | |||
|                 <div v-if="false" class="row mb-4 align-content-center"> | ||||
| 
 | ||||
|                     <div v-if="!service.online" class="col-3 text-left"> | ||||
|                         <span class="text-danger font-5 font-weight-bold"></span> | ||||
|                         <span css="text-danger font-5 font-weight-bold"></span> | ||||
|                         <span class="font-2 d-block">Current Downtime</span> | ||||
|                     </div> | ||||
| 
 | ||||
|  | @ -103,7 +103,7 @@ | |||
|   import Checkin from '../../forms/Checkin'; | ||||
|   import FormIncident from '../../forms/Incident'; | ||||
|   import FormMessage from '../../forms/Message'; | ||||
|   import ServiceFailures from './ServiceFailures'; | ||||
|   import ServiceFailures from '../Service/ServiceFailures'; | ||||
|   import ServiceSparkLine from "./ServiceSparkLine"; | ||||
|   import Api from "../../API"; | ||||
| 
 | ||||
|  | @ -65,7 +65,7 @@ | |||
|             offsetY: 0, | ||||
|           }, | ||||
|           x: { | ||||
|             show: false, | ||||
|             show: true, | ||||
|           }, | ||||
|           y: { | ||||
|             formatter: (value) => { return value + " %" }, | ||||
|  | @ -14,7 +14,7 @@ | |||
| 
 | ||||
| <script> | ||||
|     import MiniSparkLine from './MiniSparkLine'; | ||||
|     import ServiceSparkLine from './ServiceSparkLine'; | ||||
|     import ServiceSparkLine from '../Dashboard/ServiceSparkLine'; | ||||
| 
 | ||||
|     export default { | ||||
|         name: 'Analytics', | ||||
|  |  | |||
|  | @ -10,20 +10,6 @@ | |||
| 
 | ||||
|                     <ServiceTopStats :service="service"/> | ||||
| 
 | ||||
|                         <div v-if="expanded" class="row"> | ||||
|                             <Analytics title="Last Failure" :func="stats.total_failures"/> | ||||
|                             <Analytics title="Total Failures" :func="stats.total_failures"/> | ||||
|                             <Analytics title="Highest Latency" :func="stats.high_latency"/> | ||||
|                             <Analytics title="Lowest Latency" :func="stats.lowest_latency"/> | ||||
|                             <Analytics title="Total Uptime" :func="stats.high_ping"/> | ||||
|                             <Analytics title="Total Downtime" :func="stats.low_ping"/> | ||||
| 
 | ||||
|                             <div class="col-12"> | ||||
|                                 <router-link :to="serviceLink(service)" class="btn btn-block btn-outline-success mt-4" :class="{'btn-outline-success': service.online, 'btn-outline-danger': !service.online}"> | ||||
|                                     View More Details | ||||
|                                 </router-link> | ||||
|                             </div> | ||||
|                          </div> | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|  |  | |||
|  | @ -82,24 +82,27 @@ func (w *webhooker) Select() *notifications.Notification { | |||
| func (w *webhooker) sendHttpWebhook(body string) (*http.Response, error) { | ||||
| 	utils.Log.Infoln(fmt.Sprintf("sending body: '%v' to %v as a %v request", body, w.Host, w.Var1)) | ||||
| 	client := new(http.Client) | ||||
| 	client.Timeout = time.Duration(10 * time.Second) | ||||
| 	buf := bytes.NewBuffer(nil) | ||||
| 	if w.Var2 != "" { | ||||
| 		buf = bytes.NewBuffer([]byte(body)) | ||||
| 	} | ||||
| 	req, err := http.NewRequest(w.Var1, w.Host, buf) | ||||
| 	client.Timeout = 10 * time.Second | ||||
| 	req, err := http.NewRequest(w.Var1, w.Host, bytes.NewBufferString(body)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if w.ApiSecret != "" { | ||||
| 		splitArray := strings.Split(w.ApiSecret, ",") | ||||
| 		for _, a := range splitArray { | ||||
| 			split := strings.Split(a, "=") | ||||
| 			req.Header.Add(split[0], split[1]) | ||||
| 		keyVal := strings.SplitN(w.ApiSecret, "=", 2) | ||||
| 		if len(keyVal) == 2 { | ||||
| 			if keyVal[0] != "" && keyVal[1] != "" { | ||||
| 				if strings.ToLower(keyVal[0]) == "host" { | ||||
| 					req.Host = strings.TrimSpace(keyVal[1]) | ||||
| 				} else { | ||||
| 					req.Header.Set(keyVal[0], keyVal[1]) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if w.ApiKey != "" { | ||||
| 		req.Header.Add("Content-Type", w.ApiKey) | ||||
| 	} else { | ||||
| 		req.Header.Add("Content-Type", "application/json") | ||||
| 	} | ||||
| 	req.Header.Set("User-Agent", "Statping") | ||||
| 	req.Header.Set("Statping-Version", utils.Version) | ||||
|  |  | |||
|  | @ -21,18 +21,6 @@ func ConnectConfigs(configs *DbConfig, retry bool) error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func LoadConfigs(cfgFile string) (*DbConfig, error) { | ||||
| 	writeAble, err := utils.DirWritable(utils.Directory) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if !writeAble { | ||||
| 		return nil, errors.Errorf("Directory %s is not writable!", utils.Directory) | ||||
| 	} | ||||
| 
 | ||||
| 	return LoadConfigFile(cfgFile) | ||||
| } | ||||
| 
 | ||||
| func findDbFile(configs *DbConfig) (string, error) { | ||||
| 	location := utils.Directory + "/" + SqliteFilename | ||||
| 	if configs == nil { | ||||
|  |  | |||
|  | @ -1,21 +1,28 @@ | |||
| package configs | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/statping/statping/types/errors" | ||||
| 	"errors" | ||||
| 	"github.com/statping/statping/utils" | ||||
| 	"gopkg.in/yaml.v2" | ||||
| 	"os" | ||||
| ) | ||||
| 
 | ||||
| func LoadConfigFile(configFile string) (*DbConfig, error) { | ||||
| func LoadConfigs(cfgFile string) (*DbConfig, error) { | ||||
| 	writeAble, err := utils.DirWritable(utils.Directory) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if !writeAble { | ||||
| 		return nil, errors.New("Directory %s is not writable: " + utils.Directory) | ||||
| 	} | ||||
| 	p := utils.Params | ||||
| 	log.Infof("Attempting to read config file at: %s", configFile) | ||||
| 	p.SetConfigFile(configFile) | ||||
| 	log.Infof("Attempting to read config file at: %s", cfgFile) | ||||
| 	p.SetConfigFile(cfgFile) | ||||
| 	p.SetConfigType("yaml") | ||||
| 	p.ReadInConfig() | ||||
| 
 | ||||
| 	db := new(DbConfig) | ||||
| 	content, err := utils.OpenFile(configFile) | ||||
| 	content, err := utils.OpenFile(cfgFile) | ||||
| 	if err == nil { | ||||
| 		if err := yaml.Unmarshal([]byte(content), &db); err != nil { | ||||
| 			return nil, err | ||||
|  | @ -74,7 +81,7 @@ func LoadConfigFile(configFile string) (*DbConfig, error) { | |||
| 		Language:    p.GetString("LANGUAGE"), | ||||
| 		SendReports: p.GetBool("ALLOW_REPORTS"), | ||||
| 	} | ||||
| 	log.WithFields(utils.ToFields(configs)).Debugln("read config file: " + configFile) | ||||
| 	log.WithFields(utils.ToFields(configs)).Debugln("read config file: " + cfgFile) | ||||
| 
 | ||||
| 	if configs.DbConn == "" { | ||||
| 		return configs, errors.New("Starting in setup mode") | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import ( | |||
| 	_ "github.com/jinzhu/gorm/dialects/mysql" | ||||
| 	_ "github.com/jinzhu/gorm/dialects/postgres" | ||||
| 	_ "github.com/mattn/go-sqlite3" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/statping/statping/source" | ||||
| 	"github.com/statping/statping/types/notifications" | ||||
| 	"github.com/statping/statping/utils" | ||||
|  | @ -20,6 +21,39 @@ import ( | |||
| 	"github.com/statping/statping/types/users" | ||||
| ) | ||||
| 
 | ||||
| func (d *DbConfig) ResetCore() error { | ||||
| 	if d.Db.HasTable("core") { | ||||
| 		return nil | ||||
| 	} | ||||
| 	var srvs int64 | ||||
| 	if d.Db.HasTable(&services.Service{}) { | ||||
| 		d.Db.Model(&services.Service{}).Count(&srvs) | ||||
| 		if srvs > 0 { | ||||
| 			return errors.New("there are already services setup.") | ||||
| 		} | ||||
| 	} | ||||
| 	if err := d.DropDatabase(); err != nil { | ||||
| 		return errors.Wrap(err, "error dropping database") | ||||
| 	} | ||||
| 	if err := d.CreateDatabase(); err != nil { | ||||
| 		return errors.Wrap(err, "error creating database") | ||||
| 	} | ||||
| 	if err := CreateAdminUser(d); err != nil { | ||||
| 		return errors.Wrap(err, "error creating default admin user") | ||||
| 	} | ||||
| 	if utils.Params.GetBool("SAMPLE_DATA") { | ||||
| 		log.Infoln("Adding Sample Data") | ||||
| 		if err := TriggerSamples(); err != nil { | ||||
| 			return errors.Wrap(err, "error adding sample data") | ||||
| 		} | ||||
| 	} else { | ||||
| 		if err := core.Samples(); err != nil { | ||||
| 			return errors.Wrap(err, "error added core details") | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (d *DbConfig) DatabaseChanges() error { | ||||
| 	var cr core.Core | ||||
| 	d.Db.Model(&core.Core{}).Find(&cr) | ||||
|  |  | |||
|  | @ -91,14 +91,21 @@ func CheckIcmp(s *Service, record bool) (*Service, error) { | |||
| 	timer := prometheus.NewTimer(metrics.ServiceTimer(s.Name)) | ||||
| 	defer timer.ObserveDuration() | ||||
| 
 | ||||
| 	if err := utils.Ping(s.Domain, s.Timeout); err != nil { | ||||
| 	dur, err := utils.Ping(s.Domain, s.Timeout) | ||||
| 	if err != nil { | ||||
| 		if record { | ||||
| 			recordFailure(s, fmt.Sprintf("Could not send ICMP to service %v, %v", s.Domain, err)) | ||||
| 		} | ||||
| 		return s, err | ||||
| 	} | ||||
| 
 | ||||
| 	s.PingTime = dur | ||||
| 	s.Latency = dur | ||||
| 	s.LastResponse = "" | ||||
| 	s.Online = true | ||||
| 	if record { | ||||
| 		recordSuccess(s) | ||||
| 	} | ||||
| 	return s, nil | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -105,7 +105,6 @@ func (t Timestamp) Ago() string { | |||
| // Command will run a terminal command with 'sh -c COMMAND' and return stdout and errOut as strings
 | ||||
| //		in, out, err := Command("sass assets/scss assets/css/base.css")
 | ||||
| func Command(name string, args ...string) (string, string, error) { | ||||
| 	Log.Info("Running command: " + name + " " + strings.Join(args, " ")) | ||||
| 	testCmd := exec.Command(name, args...) | ||||
| 	var stdout, stderr []byte | ||||
| 	var errStdout, errStderr error | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ import ( | |||
| 	"errors" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"regexp" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
|  | @ -36,20 +37,27 @@ func DirWritable(path string) (bool, error) { | |||
| 	return true, nil | ||||
| } | ||||
| 
 | ||||
| func Ping(address string, secondsTimeout int) error { | ||||
| func Ping(address string, secondsTimeout int) (int64, error) { | ||||
| 	ping, err := exec.LookPath("ping") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	out, _, err := Command(ping, address, "-c", "1", "-W", strconv.Itoa(secondsTimeout)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	if strings.Contains(out, "Unknown host") { | ||||
| 		return errors.New("unknown host") | ||||
| 		return 0, errors.New("unknown host") | ||||
| 	} | ||||
| 	if strings.Contains(out, "100.0% packet loss") { | ||||
| 		return errors.New("destination host unreachable") | ||||
| 		return 0, errors.New("destination host unreachable") | ||||
| 	} | ||||
| 	return nil | ||||
| 
 | ||||
| 	r := regexp.MustCompile(`time=(.*) ms`) | ||||
| 	strs := r.FindStringSubmatch(out) | ||||
| 	if len(strs) < 2 { | ||||
| 		return 0, errors.New("could not parse ping duration") | ||||
| 	} | ||||
| 	f, _ := strconv.ParseFloat(strs[1], 64) | ||||
| 	return int64(f * 1000), nil | ||||
| } | ||||
|  |  | |||
|  | @ -1 +1 @@ | |||
| 0.90.57 | ||||
| 0.90.58 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Hunter Long
						Hunter Long