Procházet zdrojové kódy

auto update script executed

Toby Chui před 1 rokem
rodič
revize
ccafdbc9ca
4 změnil soubory, kde provedl 365 přidání a 4 odebrání
  1. 201 0
      mod/uptime/uptime.go
  2. 2 2
      web/components/status.html
  3. 157 0
      web/components/uptime.html
  4. 5 2
      web/index.html

+ 201 - 0
mod/uptime/uptime.go

@@ -0,0 +1,201 @@
+package uptime
+
+import (
+	"encoding/json"
+	"log"
+	"net/http"
+	"time"
+
+	"imuslab.com/zoraxy/mod/utils"
+)
+
+type Record struct {
+	Timestamp  int64
+	ID         string
+	Name       string
+	URL        string
+	Protocol   string
+	Online     bool
+	StatusCode int
+	Latency    int64
+}
+
+type Target struct {
+	ID       string
+	Name     string
+	URL      string
+	Protocol string
+}
+
+type Config struct {
+	Targets       []*Target
+	Interval      int
+	RecordsInJson int
+	LogToFile     bool
+}
+
+type Monitor struct {
+	Config          *Config
+	OnlineStatusLog map[string][]*Record
+}
+
+// Default configs
+var exampleTarget = Target{
+	ID:       "example",
+	Name:     "Example",
+	URL:      "example.com",
+	Protocol: "https",
+}
+
+//Create a new uptime monitor
+func NewUptimeMonitor(config *Config) (*Monitor, error) {
+	//Create new monitor object
+	thisMonitor := Monitor{
+		Config:          config,
+		OnlineStatusLog: map[string][]*Record{},
+	}
+	//Start the endpoint listener
+	ticker := time.NewTicker(time.Duration(config.Interval) * time.Second)
+	done := make(chan bool)
+
+	//Start the uptime check once first before entering loop
+	thisMonitor.ExecuteUptimeCheck()
+
+	go func() {
+		for {
+			select {
+			case <-done:
+				return
+			case t := <-ticker.C:
+				log.Println("Uptime updated - ", t.Unix())
+				thisMonitor.ExecuteUptimeCheck()
+			}
+		}
+	}()
+
+	return &thisMonitor, nil
+}
+
+func (m *Monitor) ExecuteUptimeCheck() {
+	for _, target := range m.Config.Targets {
+		//For each target to check online, do the following
+		var thisRecord Record
+		if target.Protocol == "http" || target.Protocol == "https" {
+			online, laterncy, statusCode := getWebsiteStatusWithLatency(target.URL)
+			thisRecord = Record{
+				Timestamp:  time.Now().Unix(),
+				ID:         target.ID,
+				Name:       target.Name,
+				URL:        target.URL,
+				Protocol:   target.Protocol,
+				Online:     online,
+				StatusCode: statusCode,
+				Latency:    laterncy,
+			}
+
+			//fmt.Println(thisRecord)
+
+		} else {
+			log.Println("Unknown protocol: " + target.Protocol + ". Skipping")
+			continue
+		}
+
+		thisRecords, ok := m.OnlineStatusLog[target.ID]
+		if !ok {
+			//First record. Create the array
+			m.OnlineStatusLog[target.ID] = []*Record{&thisRecord}
+		} else {
+			//Append to the previous record
+			thisRecords = append(thisRecords, &thisRecord)
+
+			m.OnlineStatusLog[target.ID] = thisRecords
+		}
+	}
+
+	//TODO: Write results to db
+}
+
+func (m *Monitor) AddTargetToMonitor(target *Target) {
+	// Add target to Config
+	m.Config.Targets = append(m.Config.Targets, target)
+
+	// Add target to OnlineStatusLog
+	m.OnlineStatusLog[target.ID] = []*Record{}
+}
+
+func (m *Monitor) RemoveTargetFromMonitor(targetId string) {
+	// Remove target from Config
+	for i, target := range m.Config.Targets {
+		if target.ID == targetId {
+			m.Config.Targets = append(m.Config.Targets[:i], m.Config.Targets[i+1:]...)
+			break
+		}
+	}
+
+	// Remove target from OnlineStatusLog
+	delete(m.OnlineStatusLog, targetId)
+}
+
+/*
+	Web Interface Handler
+*/
+
+func (m *Monitor) HandleUptimeLogRead(w http.ResponseWriter, r *http.Request) {
+	id, _ := utils.GetPara(r, "id")
+	if id == "" {
+		js, _ := json.Marshal(m.OnlineStatusLog)
+		w.Header().Set("Content-Type", "application/json")
+		w.Write(js)
+	} else {
+		//Check if that id exists
+		log, ok := m.OnlineStatusLog[id]
+		if !ok {
+			http.NotFound(w, r)
+			return
+		}
+
+		js, _ := json.MarshalIndent(log, "", " ")
+		w.Header().Set("Content-Type", "application/json")
+		w.Write(js)
+	}
+
+}
+
+/*
+	Utilities
+*/
+
+// Get website stauts with latency given URL, return is conn succ and its latency and status code
+func getWebsiteStatusWithLatency(url string) (bool, int64, int) {
+	start := time.Now().UnixNano() / int64(time.Millisecond)
+	statusCode, err := getWebsiteStatus(url)
+	end := time.Now().UnixNano() / int64(time.Millisecond)
+	if err != nil {
+		log.Println(err.Error())
+		return false, 0, 0
+	} else {
+		diff := end - start
+		succ := false
+		if statusCode >= 200 && statusCode < 300 {
+			//OK
+			succ = true
+		} else if statusCode >= 300 && statusCode < 400 {
+			//Redirection code
+			succ = true
+		} else {
+			succ = false
+		}
+
+		return succ, diff, statusCode
+	}
+
+}
+
+func getWebsiteStatus(url string) (int, error) {
+	resp, err := http.Get(url)
+	if err != nil {
+		return 0, err
+	}
+	status_code := resp.StatusCode
+	return status_code, nil
+}

+ 2 - 2
web/components/status.html

@@ -85,7 +85,7 @@
 <div class="ui two column stackable grid">
     <div class="column">
       <p>Visitor Counts</p>
-      <table class="ui basic unstackable table">
+      <table class="ui unstackable celled table">
         <thead>
           <tr>
             <th>Country ISO Code</th>
@@ -101,7 +101,7 @@
     </div>
     <div class="column">
       <p>Proxy Request Types</p>
-      <table class="ui basic unstackable table">
+      <table class="ui unstackable celled table">
         <thead>
           <tr>
             <th>Proxy Type</th>

+ 157 - 0
web/components/uptime.html

@@ -0,0 +1,157 @@
+<!-- css override -->
+<style>
+    #utm{
+        background-color: white;
+        border-radius: 1em;
+    }
+
+
+    .domain{
+        margin-bottom: 1em;
+        position: relative;
+    }
+
+    .statusDot{
+        height: 1.8em;
+        border-radius: 0.4em;
+        width: 0.4em;
+        background-color: #e8e8e8;
+        display:inline-block;
+        cursor: pointer;
+        margin-left: 0.1em;
+    }
+    
+    .online.statusDot{
+        background-color: #3bd671;
+    }
+    .error.statusDot{
+        background-color: #f29030;
+    }
+    .offline.statusDot{
+        background-color: #df484a;
+    }
+    .padding.statusDot{
+        cursor: auto;
+    }
+    
+</style>
+<div id="utm" class="ui basic segment">
+    <div class="ui basic segment">
+        <h4 class="ui header">
+            <i class="red remove icon"></i>
+            <div class="content">
+                Uptime Monitoring service is currently unavailable
+                <div class="sub header">This might cause by an error in cluster communication within the host servers. Please wait for administrator to resolve the issue.</div>
+            </div>
+        </h4> 
+    </div>
+</div>
+
+<script>
+    AOS.init();
+    
+    function initUptimeTable(){
+        
+    }
+    let records = JSON.parse(`<?php echo file_get_contents("http://localhost:8089/")?>`);
+    renderRecords(records);
+
+    //For every 5 minutes
+    setInterval(function(){
+        $.get("api.php?token=fbda065b-3662-415b-af4d-41cb998e619d", function(data){
+            console.log("Status Updated");
+            records = data;
+            renderRecords();
+        });
+    }, (300 * 1000));
+    
+    function renderRecords(){
+        $("#utm").html("");
+        for (let [key, value] of Object.entries(records)) {
+            renderUptimeData(key, value);
+        }
+    }
+
+    function format_time(s) {
+        const date = new Date(s * 1e3);
+        return(date.toLocaleString());
+    }
+
+
+    function renderUptimeData(key, value){
+        if (value.length == 0){
+            return
+        }
+
+        let id = value[0].ID;
+        let name = value[0].Name;
+        let url = value[0].URL;
+        let protocol = value[0].Protocol;
+
+        //Generate the status dot
+        let statusDotList = ``;
+        for(var i = 0; i < (288 - value.length); i++){
+            //Padding
+            statusDotList += `<div class="padding statusDot"></div>`
+        }
+
+        let ontimeRate = 0;
+        for (var i = 0; i < value.length; i++){
+            //Render status to html
+            let thisStatus = value[i];
+            let dotType = "";
+            if (thisStatus.Online){
+                if (thisStatus.StatusCode < 200 || thisStatus.StatusCode >= 300){
+                    dotType = "error";
+                }else{
+                    dotType = "online";
+                }
+                ontimeRate++;
+            }else{
+                dotType = "offline";
+            }
+
+            let datetime = format_time(thisStatus.Timestamp);
+            statusDotList += `<div title="${datetime}" class="${dotType} statusDot"></div>`
+        }
+
+        ontimeRate = ontimeRate / value.length * 100;
+        let ontimeColor = "#df484a"
+        if (ontimeRate > 0.8){
+            ontimeColor = "#3bd671";
+        }else if(ontimeRate > 0.5) {
+            ontimeColor = "#f29030";
+        }
+        //Check of online status now
+        let currentOnlineStatus = "Unknown";
+        let onlineStatusCss = ``;
+        if (value[value.length - 1].Online){
+            currentOnlineStatus = `<i class="circle icon"></i> Online`;
+            onlineStatusCss = `color: #3bd671;`;
+        }else{
+            currentOnlineStatus = `<i class="circle icon"></i> Offline`;
+            onlineStatusCss = `color: #df484a;`;
+        }
+
+        //Generate the html
+        $("#utm").append(`<div class="ui basic segment statusbar">
+            <div class="domain">
+                <div style="position: absolute; top: 0; right: 0.4em;">
+                    <p class="onlineStatus" style="display: inline-block; font-size: 1.3em; padding-right: 0.5em; padding-left: 0.3em; ${onlineStatusCss}">${currentOnlineStatus}</p>
+                </div>
+                <div>
+                    <h3 class="ui header" style="margin-bottom: 0.2em;">${name}</h3>
+                    <a href="${url}" target="_blank">${url}</a> | <span style="color: ${ontimeColor};">${(ontimeRate).toFixed(2)}%<span>
+                </div>
+                <div class="ui basic label protocol" style="position: absolute; bottom: 0; right: 0.2em; margin-bottom: -0.6em;">
+                    proto: ${protocol}
+                </div>
+            </div>
+            <div class="status" style="marign-top: 1em;">
+                ${statusDotList}
+            </div>
+            <div class="ui divider"></div>
+        </div>`);
+    }
+    
+</script>

+ 5 - 2
web/index.html

@@ -66,8 +66,8 @@
                         <i class="remove icon"></i> HTTP over Websocket
                     </a>
                     <div class="ui divider menudivider">Others</div>
-                    <a class="item" tag="">
-                        <i class="remove icon"></i> Uptime Monitor
+                    <a class="item" tag="utm">
+                        <i class="green time icon"></i> Uptime Monitor
                     </a>
                     <a class="item" tag="">
                         <i class="remove icon"></i> Network Tools
@@ -108,6 +108,9 @@
                 <!-- UPnP based port fowarding -->
                 <div id="upnp" class="functiontab" target="upnp.html"></div>
 
+                <!-- Up Time Monitor -->
+                <div id="utm" class="functiontab" target="uptime.html"></div>
+
                 <!-- Utilities -->
                 <div id="utils" class="functiontab" target="utils.html"></div>
             </div>