Example #1
0
// cronPrintCurrentStatus logs the regular status check banner
func cronPrintCurrentStatus() {
	// Grab server status
	stat := common.GetServerStatus()
	if stat == (common.ServerStatus{}) {
		log.Println("Could not print current status")
		return
	}

	// Regular status banner
	log.Printf("status - [goroutines: %d] [memory: %02.3f MB]", stat.NumGoroutine, stat.MemoryMB)

	// HTTP stats
	if common.Static.Config.HTTP {
		log.Printf("  http - [current: %d] [total: %d]", stat.HTTP.Current, stat.HTTP.Total)

		// Reset current HTTP counter
		atomic.StoreInt64(&common.Static.HTTP.Current, 0)
	}

	// UDP stats
	if common.Static.Config.UDP {
		log.Printf("   udp - [current: %d] [total: %d]", stat.UDP.Current, stat.UDP.Total)

		// Reset current UDP counter
		atomic.StoreInt64(&common.Static.UDP.Current, 0)
	}
}
Example #2
0
// TestGetStatusJSON verifies that /api/status returns proper JSON output
func TestGetStatusJSON(t *testing.T) {
	log.Println("TestGetStatusJSON()")

	// Get status directly
	status := common.GetServerStatus()

	// Request output JSON from API for this status
	var status2 common.ServerStatus
	err := json.Unmarshal(getStatusJSON(), &status2)
	if err != nil {
		t.Fatalf("Failed to unmarshal result JSON")
	}

	// Verify objects are the same
	if status.PID != status2.PID {
		t.Fatalf("PID, expected %d, got %d", status.PID, status2.PID)
	}

	if status.Hostname != status2.Hostname {
		t.Fatalf("Hostname, expected %s, got %s", status.Hostname, status2.Hostname)
	}

	if status.Platform != status2.Platform {
		t.Fatalf("Platform, expected %s, got %s", status.Platform, status2.Platform)
	}

	if status.Architecture != status2.Architecture {
		t.Fatalf("Architecture, expected %s, got %s", status.Architecture, status2.Architecture)
	}

	if status.NumCPU != status2.NumCPU {
		t.Fatalf("NumCPU, expected %d, got %d", status.NumCPU, status2.NumCPU)
	}
}
Example #3
0
// cronPrintCurrentStatus logs the regular status check banner
func cronPrintCurrentStatus() {
	// Grab server status
	stat, err := common.GetServerStatus()
	if err != nil {
		log.Println(err.Error())
		return
	}

	// Regular status banner
	log.Printf("status - [goroutines: %d] [memory: %02.3f MB]", stat.NumGoroutine, stat.MemoryMB)

	// API stats
	if common.Static.Config.API {
		log.Printf("   api - [1 min: %03d | 30 min: %03d | 60 min: %03d] [total: %03d]", stat.API.Minute, stat.API.HalfHour, stat.API.Hour, stat.API.Total)
	}

	// HTTP stats
	if common.Static.Config.HTTP {
		log.Printf("  http - [1 min: %03d | 30 min: %03d | 60 min: %03d] [total: %03d]", stat.HTTP.Minute, stat.HTTP.HalfHour, stat.HTTP.Hour, stat.HTTP.Total)
	}

	// UDP stats
	if common.Static.Config.UDP {
		log.Printf("   udp - [1 min: %03d | 30 min: %03d | 60 min: %03d] [total: %03d]", stat.UDP.Minute, stat.UDP.HalfHour, stat.UDP.Hour, stat.UDP.Total)
	}
}
Example #4
0
// getStatusJSON returns a JSON representation of server status
func getStatusJSON() []byte {
	// Marshal into JSON from request
	res, err := json.Marshal(common.GetServerStatus())
	if err != nil {
		log.Println(err.Error())
		return nil
	}

	// Return status
	return res
}
Example #5
0
// getStatusJSON returns a JSON representation of server status
func getStatusJSON() ([]byte, error) {
	// Retrieve status
	status, err := common.GetServerStatus()
	if err != nil {
		return nil, err
	}

	// Marshal into JSON from request
	res, err := json.Marshal(status)
	if err != nil {
		return nil, err
	}

	// Return status
	return res, nil
}
Example #6
0
// Manager is responsible for coordinating the application
func Manager(killChan chan bool, exitChan chan int) {
	// Capture startup time
	common.Static.StartTime = time.Now().Unix()

	// Set up logging flags
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	log.Println("Starting " + App + " " + Version)

	// Grab initial server status
	stat := common.GetServerStatus()
	if stat == (common.ServerStatus{}) {
		log.Println("Could not print get startup status")
	} else {
		log.Printf("%s - %s_%s (%d CPU) [pid: %d]", stat.Hostname, stat.Platform, stat.Architecture, stat.NumCPU, stat.PID)
	}

	// Load configuration
	config := common.LoadConfig()
	if config == (common.Conf{}) {
		panic("Cannot load configuration, panicking")
	}
	common.Static.Config = config

	// Check for sane announce interval (10 minutes or more)
	if common.Static.Config.Interval <= 600 {
		panic("Announce interval must be at least 600 seconds, panicking")
	}

	// Attempt database connection
	if !data.DBPing() {
		panic(fmt.Errorf("cannot connect to database %s; panicking", data.DBName()))
	}
	log.Println("Database", data.DBName(), ": OK")

	// If configured, attempt redis connection
	if common.Static.Config.Redis.Enabled {
		if !data.RedisPing() {
			panic("Cannot connect to Redis, panicking")
		}
		log.Println("Redis : OK")
	}

	// Start cron manager
	go cronManager()

	// Set up graceful shutdown channels
	httpSendChan := make(chan bool)
	httpRecvChan := make(chan bool)
	httpsSendChan := make(chan bool)
	httpsRecvChan := make(chan bool)
	udpSendChan := make(chan bool)
	udpRecvChan := make(chan bool)

	// Set up HTTP(S) route
	http.HandleFunc("/", parseHTTP)

	// Launch listeners as configured
	if common.Static.Config.HTTP {
		go listenHTTP(httpSendChan, httpRecvChan)
		log.Println("HTTP listener launched on port " + strconv.Itoa(common.Static.Config.Port))
	}
	if common.Static.Config.SSL.Enabled {
		go listenHTTPS(httpsSendChan, httpsRecvChan)
		log.Println("HTTPS listener launched on port " + strconv.Itoa(common.Static.Config.SSL.Port))
	}
	if common.Static.Config.UDP {
		go listenUDP(udpSendChan, udpRecvChan)
		log.Println("UDP listener launched on port " + strconv.Itoa(common.Static.Config.Port))
	}

	// Wait for shutdown signal
	for {
		select {
		case <-killChan:
			// Trigger a graceful shutdown
			log.Println("Triggering graceful shutdown, press Ctrl+C again to force halt")

			// If program hangs for more than 10 seconds, trigger a force halt
			go func() {
				<-time.After(10 * time.Second)
				log.Println("Timeout reached, triggering force halt")
				if err := syscall.Kill(os.Getpid(), syscall.SIGTERM); err != nil {
					log.Println(err.Error())
				}
			}()

			// Stop listeners
			if common.Static.Config.HTTP {
				log.Println("Stopping HTTP listener")
				httpSendChan <- true
				<-httpRecvChan
			}
			if common.Static.Config.SSL.Enabled {
				log.Println("Stopping HTTPS listener")
				httpsSendChan <- true
				<-httpsRecvChan
			}
			if common.Static.Config.UDP {
				log.Println("Stopping UDP listener")
				udpSendChan <- true
				<-udpRecvChan
			}

			log.Println("Closing database connection")
			data.DBCloseFunc()

			// Report that program should exit gracefully
			exitChan <- 0
		}
	}
}