Chore: Update 2.8 disabled networking policie checks - not needed. upload is perfect
This commit is contained in:
parent
ccf04ede06
commit
a0a117dc11
@ -384,18 +384,11 @@ func createAndMountISO(size, mountpoint, charset string) error {
|
|||||||
var dialer = &net.Dialer{
|
var dialer = &net.Dialer{
|
||||||
DualStack: true,
|
DualStack: true,
|
||||||
Timeout: 5 * time.Second,
|
Timeout: 5 * time.Second,
|
||||||
KeepAlive: 30 * time.Second, // Added keep-alive for better network change handling
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var dualStackClient = &http.Client{
|
var dualStackClient = &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
DialContext: dialer.DialContext,
|
DialContext: dialer.DialContext,
|
||||||
ForceAttemptHTTP2: true, // Enforce HTTP/2
|
|
||||||
IdleConnTimeout: 90 * time.Second, // Longer idle connections
|
|
||||||
DisableKeepAlives: false, // Ensure keep-alives are enabled
|
|
||||||
MaxIdleConns: 100,
|
|
||||||
MaxIdleConnsPerHost: 10,
|
|
||||||
// ...existing code...
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,6 +535,10 @@ func main() {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
if conf.Server.NetworkEvents {
|
||||||
|
go monitorNetwork(ctx)
|
||||||
|
go handleNetworkEvents(ctx)
|
||||||
|
}
|
||||||
go updateSystemMetrics(ctx)
|
go updateSystemMetrics(ctx)
|
||||||
|
|
||||||
if conf.ClamAV.ClamAVEnabled {
|
if conf.ClamAV.ClamAVEnabled {
|
||||||
@ -637,6 +634,9 @@ func main() {
|
|||||||
log.Fatalf("Server failed: %v", err)
|
log.Fatalf("Server failed: %v", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if conf.Server.ListenPort == "0.0.0.0" {
|
||||||
|
log.Info("Binding to 0.0.0.0. Any net/http logs you see are normal for this universal address.")
|
||||||
|
}
|
||||||
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||||
log.Fatalf("Server failed: %v", err)
|
log.Fatalf("Server failed: %v", err)
|
||||||
}
|
}
|
||||||
@ -733,7 +733,7 @@ uploadqueuesize = 50
|
|||||||
# Add file-specific configurations here
|
# Add file-specific configurations here
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
version = "2.8-Stable"
|
version = "2.7-Stable"
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1700,7 +1700,26 @@ func handleRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
log.WithFields(logrus.Fields{"method": r.Method, "url": r.URL.String(), "remote": clientIP}).Info("Incoming request")
|
log.WithFields(logrus.Fields{"method": r.Method, "url": r.URL.String(), "remote": clientIP}).Info("Incoming request")
|
||||||
|
|
||||||
|
// Log the requested URL for debugging
|
||||||
|
log.Infof("handleRequest: Received URL path: %s", r.URL.String())
|
||||||
|
|
||||||
p := r.URL.Path
|
p := r.URL.Path
|
||||||
|
fileStorePath := strings.TrimPrefix(p, "/")
|
||||||
|
if fileStorePath == "" || fileStorePath == "/" {
|
||||||
|
log.WithField("path", fileStorePath).Warn("No file specified in URL")
|
||||||
|
// Updated to return 404 with a clear message instead of forbidden.
|
||||||
|
http.Error(w, "File not specified in URL. Please include the file path after the host.", http.StatusNotFound)
|
||||||
|
flushLogMessages()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// NEW: Compute absolute file path from storage path and fileStorePath.
|
||||||
|
absFilename, err := sanitizeFilePath(conf.Server.StoragePath, fileStorePath)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Warn("Invalid file path")
|
||||||
|
http.Error(w, "Invalid file path", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
a, err := url.ParseQuery(r.URL.RawQuery)
|
a, err := url.ParseQuery(r.URL.RawQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("Failed to parse query parameters")
|
log.Warn("Failed to parse query parameters")
|
||||||
@ -1708,26 +1727,6 @@ func handleRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fileStorePath := strings.TrimPrefix(p, "/")
|
|
||||||
if fileStorePath == "" || fileStorePath == "/" {
|
|
||||||
log.WithFields(logrus.Fields{
|
|
||||||
"event": "AccessAttempt",
|
|
||||||
"severity": "warning",
|
|
||||||
}).Warn("Access to root directory is forbidden")
|
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
|
||||||
flushLogMessages()
|
|
||||||
return
|
|
||||||
} else if fileStorePath[0] == '/' {
|
|
||||||
fileStorePath = fileStorePath[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
absFilename, err := sanitizeFilePath(conf.Server.StoragePath, fileStorePath)
|
|
||||||
if err != nil {
|
|
||||||
log.WithFields(logrus.Fields{"file": fileStorePath, "error": err}).Warn("Invalid file path")
|
|
||||||
http.Error(w, "Invalid file path", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodPut:
|
case http.MethodPut:
|
||||||
handleUpload(w, r, absFilename, fileStorePath, a)
|
handleUpload(w, r, absFilename, fileStorePath, a)
|
||||||
@ -1745,14 +1744,6 @@ func handleRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// handleUpload handles PUT requests for file uploads
|
// handleUpload handles PUT requests for file uploads
|
||||||
func handleUpload(w http.ResponseWriter, r *http.Request, absFilename, fileStorePath string, a url.Values) {
|
func handleUpload(w http.ResponseWriter, r *http.Request, absFilename, fileStorePath string, a url.Values) {
|
||||||
clientIP := getOriginalClientIP(r)
|
|
||||||
parsedIP := net.ParseIP(clientIP)
|
|
||||||
if parsedIP == nil {
|
|
||||||
log.Warnf("Invalid client IP address: %s", clientIP)
|
|
||||||
} else {
|
|
||||||
log.Infof("Handling upload from IP: %s (%s)", parsedIP.String(), detectIPVersion(parsedIP.String()))
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Using storage path: %s", conf.Server.StoragePath)
|
log.Infof("Using storage path: %s", conf.Server.StoragePath)
|
||||||
|
|
||||||
// HMAC validation
|
// HMAC validation
|
||||||
@ -1860,7 +1851,6 @@ func handleUpload(w http.ResponseWriter, r *http.Request, absFilename, fileStore
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Respond with 201 Created immediately
|
// Respond with 201 Created immediately
|
||||||
w.Header().Set("Content-Type", "text/plain") // Ensure correct interpretation
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
if f, ok := w.(http.Flusher); ok {
|
if f, ok := w.(http.Flusher); ok {
|
||||||
f.Flush()
|
f.Flush()
|
||||||
@ -1965,14 +1955,7 @@ func handleDownload(w http.ResponseWriter, r *http.Request, absFilename, fileSto
|
|||||||
} else {
|
} else {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
log.Infof("Initiating download for file: %s", absFilename)
|
log.Infof("Initiating download for file: %s", absFilename)
|
||||||
f, err := os.Open(absFilename)
|
http.ServeFile(w, r, absFilename)
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Couldn't open file: %v", err)
|
|
||||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
http.ServeContent(w, r, filepath.Base(absFilename), fileInfo.ModTime(), f)
|
|
||||||
downloadDuration.Observe(time.Since(startTime).Seconds())
|
downloadDuration.Observe(time.Since(startTime).Seconds())
|
||||||
downloadSizeBytes.Observe(float64(fileInfo.Size()))
|
downloadSizeBytes.Observe(float64(fileInfo.Size()))
|
||||||
downloadsTotal.Inc()
|
downloadsTotal.Inc()
|
||||||
@ -2172,6 +2155,73 @@ func getFileInfo(absFilename string) (os.FileInfo, error) {
|
|||||||
return fileInfo, nil
|
return fileInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func monitorNetwork(ctx context.Context) {
|
||||||
|
currentIP := getCurrentIPAddress()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.Info("Stopping network monitor.")
|
||||||
|
return
|
||||||
|
case <-time.After(10 * time.Second):
|
||||||
|
newIP := getCurrentIPAddress()
|
||||||
|
if newIP != currentIP && newIP != "" {
|
||||||
|
currentIP = newIP
|
||||||
|
select {
|
||||||
|
case networkEvents <- NetworkEvent{Type: "IP_CHANGE", Details: currentIP}:
|
||||||
|
log.WithField("new_ip", currentIP).Info("Queued IP_CHANGE event")
|
||||||
|
default:
|
||||||
|
log.Warn("Network event channel full. Dropping IP_CHANGE event.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleNetworkEvents(ctx context.Context) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.Info("Stopping network event handler.")
|
||||||
|
return
|
||||||
|
case event, ok := <-networkEvents:
|
||||||
|
if !ok {
|
||||||
|
log.Info("Network events channel closed.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch event.Type {
|
||||||
|
case "IP_CHANGE":
|
||||||
|
log.WithField("new_ip", event.Details).Info("Network change detected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCurrentIPAddress() string {
|
||||||
|
interfaces, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("Failed to get network interfaces")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, iface := range interfaces {
|
||||||
|
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
addrs, err := iface.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Errorf("Failed to get addresses for interface %s", iface.Name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.IsGlobalUnicast() && ipnet.IP.To4() != nil {
|
||||||
|
return ipnet.IP.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func setupGracefulShutdown(server *http.Server, cancel context.CancelFunc) {
|
func setupGracefulShutdown(server *http.Server, cancel context.CancelFunc) {
|
||||||
quit := make(chan os.Signal, 1)
|
quit := make(chan os.Signal, 1)
|
||||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||||
@ -2757,23 +2807,13 @@ func detectIPVersion(ip string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getOriginalClientIP(r *http.Request) string {
|
func getOriginalClientIP(r *http.Request) string {
|
||||||
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
|
if ip := r.Header.Get("X-Forwarded-For"); ip != "" {
|
||||||
parts := strings.Split(xff, ",")
|
parts := strings.Split(ip, ",")
|
||||||
for _, part := range parts {
|
return strings.TrimSpace(parts[0])
|
||||||
ip := strings.TrimSpace(part)
|
|
||||||
if net.ParseIP(ip) != nil {
|
|
||||||
return ip
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if rip := r.Header.Get("X-Real-IP"); rip != "" {
|
if ip := r.Header.Get("X-Real-IP"); ip != "" {
|
||||||
if net.ParseIP(rip) != nil {
|
return strings.TrimSpace(ip)
|
||||||
return strings.TrimSpace(rip)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
host, _, _ := net.SplitHostPort(r.RemoteAddr)
|
||||||
if err == nil && host != "" && net.ParseIP(host) != nil {
|
return host
|
||||||
return host
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,8 @@
|
|||||||
"overrides": []
|
"overrides": []
|
||||||
},
|
},
|
||||||
"gridPos": {
|
"gridPos": {
|
||||||
"h": 6,
|
"h": 7,
|
||||||
"w": 24,
|
"w": 3,
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 0
|
"y": 0
|
||||||
},
|
},
|
||||||
@ -42,7 +42,7 @@
|
|||||||
"content": "<div style=\"text-align: center; background-color: transparent; padding: 20px;\">\n <h3 style=\"color: white; font-family: 'Arial', sans-serif; font-weight: bold;\">HMAC Dashboard</h3>\n <img src=\"https://git.uuxo.net/uuxo/hmac-file-server/raw/branch/main/dashboard/hmac_icon.png\" alt=\"HMAC Icon\" style=\"width: 50px; height: 50px; display: block; margin: 10px auto;\">\n <p style=\"font-family: 'Verdana', sans-serif; color: white;\">\n This dashboard monitors <strong style=\"color: #FF5733;\">key metrics</strong> for the \n <span style=\"font-style: italic; color: #007BFF;\">HMAC File Server</span>.\n </p>\n</div>\n",
|
"content": "<div style=\"text-align: center; background-color: transparent; padding: 20px;\">\n <h3 style=\"color: white; font-family: 'Arial', sans-serif; font-weight: bold;\">HMAC Dashboard</h3>\n <img src=\"https://git.uuxo.net/uuxo/hmac-file-server/raw/branch/main/dashboard/hmac_icon.png\" alt=\"HMAC Icon\" style=\"width: 50px; height: 50px; display: block; margin: 10px auto;\">\n <p style=\"font-family: 'Verdana', sans-serif; color: white;\">\n This dashboard monitors <strong style=\"color: #FF5733;\">key metrics</strong> for the \n <span style=\"font-style: italic; color: #007BFF;\">HMAC File Server</span>.\n </p>\n</div>\n",
|
||||||
"mode": "html"
|
"mode": "html"
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"title": "HMAC Dashboard",
|
"title": "HMAC Dashboard",
|
||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
@ -77,8 +77,8 @@
|
|||||||
"gridPos": {
|
"gridPos": {
|
||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 6,
|
"w": 6,
|
||||||
"x": 0,
|
"x": 3,
|
||||||
"y": 6
|
"y": 0
|
||||||
},
|
},
|
||||||
"id": 14,
|
"id": 14,
|
||||||
"options": {
|
"options": {
|
||||||
@ -105,7 +105,7 @@
|
|||||||
"sizing": "auto",
|
"sizing": "auto",
|
||||||
"valueMode": "color"
|
"valueMode": "color"
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
@ -143,8 +143,8 @@
|
|||||||
"gridPos": {
|
"gridPos": {
|
||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 6,
|
"w": 6,
|
||||||
"x": 6,
|
"x": 9,
|
||||||
"y": 6
|
"y": 0
|
||||||
},
|
},
|
||||||
"id": 18,
|
"id": 18,
|
||||||
"options": {
|
"options": {
|
||||||
@ -164,7 +164,7 @@
|
|||||||
"textMode": "auto",
|
"textMode": "auto",
|
||||||
"wideLayout": true
|
"wideLayout": true
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
@ -203,9 +203,9 @@
|
|||||||
},
|
},
|
||||||
"gridPos": {
|
"gridPos": {
|
||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 4,
|
"w": 5,
|
||||||
"x": 12,
|
"x": 15,
|
||||||
"y": 6
|
"y": 0
|
||||||
},
|
},
|
||||||
"id": 10,
|
"id": 10,
|
||||||
"options": {
|
"options": {
|
||||||
@ -225,7 +225,7 @@
|
|||||||
"textMode": "value",
|
"textMode": "value",
|
||||||
"wideLayout": true
|
"wideLayout": true
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
@ -262,8 +262,8 @@
|
|||||||
"gridPos": {
|
"gridPos": {
|
||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 4,
|
"w": 4,
|
||||||
"x": 16,
|
"x": 20,
|
||||||
"y": 6
|
"y": 0
|
||||||
},
|
},
|
||||||
"id": 17,
|
"id": 17,
|
||||||
"options": {
|
"options": {
|
||||||
@ -283,7 +283,7 @@
|
|||||||
"textMode": "auto",
|
"textMode": "auto",
|
||||||
"wideLayout": true
|
"wideLayout": true
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
@ -297,77 +297,6 @@
|
|||||||
"title": "HMAC GoRoutines",
|
"title": "HMAC GoRoutines",
|
||||||
"type": "stat"
|
"type": "stat"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"datasource": {
|
|
||||||
"default": true,
|
|
||||||
"type": "prometheus"
|
|
||||||
},
|
|
||||||
"fieldConfig": {
|
|
||||||
"defaults": {
|
|
||||||
"color": {
|
|
||||||
"mode": "thresholds"
|
|
||||||
},
|
|
||||||
"mappings": [],
|
|
||||||
"thresholds": {
|
|
||||||
"mode": "absolute",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"color": "green",
|
|
||||||
"value": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"color": "red",
|
|
||||||
"value": 80
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"unit": "s"
|
|
||||||
},
|
|
||||||
"overrides": []
|
|
||||||
},
|
|
||||||
"gridPos": {
|
|
||||||
"h": 7,
|
|
||||||
"w": 4,
|
|
||||||
"x": 20,
|
|
||||||
"y": 6
|
|
||||||
},
|
|
||||||
"id": 15,
|
|
||||||
"options": {
|
|
||||||
"colorMode": "value",
|
|
||||||
"graphMode": "area",
|
|
||||||
"justifyMode": "auto",
|
|
||||||
"orientation": "auto",
|
|
||||||
"percentChangeColorMode": "standard",
|
|
||||||
"reduceOptions": {
|
|
||||||
"calcs": [
|
|
||||||
"lastNotNull"
|
|
||||||
],
|
|
||||||
"fields": "",
|
|
||||||
"values": false
|
|
||||||
},
|
|
||||||
"showPercentChange": false,
|
|
||||||
"textMode": "auto",
|
|
||||||
"wideLayout": true
|
|
||||||
},
|
|
||||||
"pluginVersion": "11.5.2",
|
|
||||||
"targets": [
|
|
||||||
{
|
|
||||||
"datasource": {
|
|
||||||
"type": "prometheus",
|
|
||||||
"uid": "bduehd5vqv1moa"
|
|
||||||
},
|
|
||||||
"editorMode": "code",
|
|
||||||
"expr": "hmac_file_server_upload_duration_seconds_sum + hmac_file_server_download_duration_seconds_sum",
|
|
||||||
"hide": false,
|
|
||||||
"instant": false,
|
|
||||||
"legendFormat": "__auto",
|
|
||||||
"range": true,
|
|
||||||
"refId": "B"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"title": "HMAC Up/Down Duration",
|
|
||||||
"type": "stat"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"datasource": {
|
"datasource": {
|
||||||
"default": true,
|
"default": true,
|
||||||
@ -397,7 +326,7 @@
|
|||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 5,
|
"w": 5,
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 13
|
"y": 7
|
||||||
},
|
},
|
||||||
"id": 11,
|
"id": 11,
|
||||||
"options": {
|
"options": {
|
||||||
@ -417,7 +346,7 @@
|
|||||||
"textMode": "value",
|
"textMode": "value",
|
||||||
"wideLayout": true
|
"wideLayout": true
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
@ -460,7 +389,7 @@
|
|||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 5,
|
"w": 5,
|
||||||
"x": 5,
|
"x": 5,
|
||||||
"y": 13
|
"y": 7
|
||||||
},
|
},
|
||||||
"id": 12,
|
"id": 12,
|
||||||
"options": {
|
"options": {
|
||||||
@ -480,7 +409,7 @@
|
|||||||
"textMode": "value",
|
"textMode": "value",
|
||||||
"wideLayout": true
|
"wideLayout": true
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
@ -493,6 +422,77 @@
|
|||||||
"title": "HMAC Downloads",
|
"title": "HMAC Downloads",
|
||||||
"type": "stat"
|
"type": "stat"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"default": true,
|
||||||
|
"type": "prometheus"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 7,
|
||||||
|
"w": 3,
|
||||||
|
"x": 10,
|
||||||
|
"y": 7
|
||||||
|
},
|
||||||
|
"id": 15,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"percentChangeColorMode": "standard",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"showPercentChange": false,
|
||||||
|
"textMode": "auto",
|
||||||
|
"wideLayout": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "11.4.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "bduehd5vqv1moa"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "hmac_file_server_upload_duration_seconds_sum + hmac_file_server_download_duration_seconds_sum",
|
||||||
|
"hide": false,
|
||||||
|
"instant": false,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"range": true,
|
||||||
|
"refId": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "HMAC Up/Down Duration",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"datasource": {
|
"datasource": {
|
||||||
"default": true,
|
"default": true,
|
||||||
@ -519,9 +519,9 @@
|
|||||||
},
|
},
|
||||||
"gridPos": {
|
"gridPos": {
|
||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 5,
|
"w": 3,
|
||||||
"x": 10,
|
"x": 13,
|
||||||
"y": 13
|
"y": 7
|
||||||
},
|
},
|
||||||
"id": 13,
|
"id": 13,
|
||||||
"options": {
|
"options": {
|
||||||
@ -541,7 +541,7 @@
|
|||||||
"textMode": "auto",
|
"textMode": "auto",
|
||||||
"wideLayout": true
|
"wideLayout": true
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
@ -580,9 +580,9 @@
|
|||||||
},
|
},
|
||||||
"gridPos": {
|
"gridPos": {
|
||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 5,
|
"w": 3,
|
||||||
"x": 15,
|
"x": 16,
|
||||||
"y": 13
|
"y": 7
|
||||||
},
|
},
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"options": {
|
"options": {
|
||||||
@ -602,7 +602,7 @@
|
|||||||
"textMode": "auto",
|
"textMode": "auto",
|
||||||
"wideLayout": true
|
"wideLayout": true
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
@ -641,9 +641,9 @@
|
|||||||
},
|
},
|
||||||
"gridPos": {
|
"gridPos": {
|
||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 4,
|
"w": 5,
|
||||||
"x": 20,
|
"x": 19,
|
||||||
"y": 13
|
"y": 7
|
||||||
},
|
},
|
||||||
"id": 21,
|
"id": 21,
|
||||||
"options": {
|
"options": {
|
||||||
@ -663,7 +663,7 @@
|
|||||||
"textMode": "value",
|
"textMode": "value",
|
||||||
"wideLayout": true
|
"wideLayout": true
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
@ -704,7 +704,7 @@
|
|||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 3,
|
"w": 3,
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 20
|
"y": 14
|
||||||
},
|
},
|
||||||
"id": 19,
|
"id": 19,
|
||||||
"options": {
|
"options": {
|
||||||
@ -724,7 +724,7 @@
|
|||||||
"textMode": "auto",
|
"textMode": "auto",
|
||||||
"wideLayout": true
|
"wideLayout": true
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
@ -746,7 +746,21 @@
|
|||||||
"fieldConfig": {
|
"fieldConfig": {
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"color": {
|
"color": {
|
||||||
"mode": "thresholds"
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"fillOpacity": 80,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"lineWidth": 1,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"fieldMinMax": false,
|
"fieldMinMax": false,
|
||||||
"mappings": [],
|
"mappings": [],
|
||||||
@ -762,7 +776,8 @@
|
|||||||
"value": 80
|
"value": 80
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"unit": "files"
|
||||||
},
|
},
|
||||||
"overrides": []
|
"overrides": []
|
||||||
},
|
},
|
||||||
@ -770,42 +785,37 @@
|
|||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 7,
|
"w": 7,
|
||||||
"x": 3,
|
"x": 3,
|
||||||
"y": 20
|
"y": 14
|
||||||
},
|
},
|
||||||
"id": 22,
|
"id": 22,
|
||||||
"options": {
|
"options": {
|
||||||
"colorMode": "value",
|
"legend": {
|
||||||
"graphMode": "area",
|
"calcs": [],
|
||||||
"justifyMode": "auto",
|
"displayMode": "list",
|
||||||
"orientation": "auto",
|
"placement": "bottom",
|
||||||
"percentChangeColorMode": "standard",
|
"showLegend": true
|
||||||
"reduceOptions": {
|
|
||||||
"calcs": [
|
|
||||||
"lastNotNull"
|
|
||||||
],
|
|
||||||
"fields": "",
|
|
||||||
"values": false
|
|
||||||
},
|
},
|
||||||
"showPercentChange": false,
|
"tooltip": {
|
||||||
"textMode": "auto",
|
"mode": "single",
|
||||||
"wideLayout": true
|
"sort": "none"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
"exemplar": false,
|
"exemplar": false,
|
||||||
"expr": "hmac_active_connections_total",
|
"expr": "increase(hmac_file_server_clamav_scans_total[24h])",
|
||||||
"format": "time_series",
|
"format": "time_series",
|
||||||
"instant": false,
|
"instant": true,
|
||||||
"interval": "",
|
"interval": "",
|
||||||
"legendFormat": "__auto",
|
"legendFormat": "__auto",
|
||||||
"range": true,
|
"range": true,
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"title": "HMAC Active Connection(s)",
|
"title": "HMAC ClamAV San (24h)",
|
||||||
"type": "stat"
|
"type": "histogram"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"datasource": {
|
"datasource": {
|
||||||
@ -818,36 +828,17 @@
|
|||||||
"mode": "palette-classic"
|
"mode": "palette-classic"
|
||||||
},
|
},
|
||||||
"custom": {
|
"custom": {
|
||||||
"axisBorderShow": false,
|
"fillOpacity": 80,
|
||||||
"axisCenteredZero": false,
|
|
||||||
"axisColorMode": "text",
|
|
||||||
"axisLabel": "",
|
|
||||||
"axisPlacement": "auto",
|
|
||||||
"barAlignment": 0,
|
|
||||||
"barWidthFactor": 0.6,
|
|
||||||
"drawStyle": "line",
|
|
||||||
"fillOpacity": 0,
|
|
||||||
"gradientMode": "none",
|
"gradientMode": "none",
|
||||||
"hideFrom": {
|
"hideFrom": {
|
||||||
"legend": false,
|
"legend": false,
|
||||||
"tooltip": false,
|
"tooltip": false,
|
||||||
"viz": false
|
"viz": false
|
||||||
},
|
},
|
||||||
"insertNulls": false,
|
|
||||||
"lineInterpolation": "linear",
|
|
||||||
"lineWidth": 1,
|
"lineWidth": 1,
|
||||||
"pointSize": 5,
|
|
||||||
"scaleDistribution": {
|
|
||||||
"type": "linear"
|
|
||||||
},
|
|
||||||
"showPoints": "auto",
|
|
||||||
"spanNulls": false,
|
|
||||||
"stacking": {
|
"stacking": {
|
||||||
"group": "A",
|
"group": "A",
|
||||||
"mode": "none"
|
"mode": "none"
|
||||||
},
|
|
||||||
"thresholdsStyle": {
|
|
||||||
"mode": "off"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fieldMinMax": false,
|
"fieldMinMax": false,
|
||||||
@ -873,7 +864,7 @@
|
|||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 7,
|
"w": 7,
|
||||||
"x": 10,
|
"x": 10,
|
||||||
"y": 20
|
"y": 14
|
||||||
},
|
},
|
||||||
"id": 23,
|
"id": 23,
|
||||||
"options": {
|
"options": {
|
||||||
@ -884,17 +875,16 @@
|
|||||||
"showLegend": true
|
"showLegend": true
|
||||||
},
|
},
|
||||||
"tooltip": {
|
"tooltip": {
|
||||||
"hideZeros": false,
|
|
||||||
"mode": "single",
|
"mode": "single",
|
||||||
"sort": "none"
|
"sort": "none"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
"exemplar": false,
|
"exemplar": false,
|
||||||
"expr": "hmac_deduplication_errors_total",
|
"expr": "increase(hmac_file_server_clamav_errors_total[24h])",
|
||||||
"format": "time_series",
|
"format": "time_series",
|
||||||
"instant": true,
|
"instant": true,
|
||||||
"interval": "",
|
"interval": "",
|
||||||
@ -903,8 +893,8 @@
|
|||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"title": "HMAC Duplication Error",
|
"title": "HMAC ClamAV SanError(s) (24h)",
|
||||||
"type": "timeseries"
|
"type": "histogram"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"datasource": {
|
"datasource": {
|
||||||
@ -951,7 +941,7 @@
|
|||||||
"h": 7,
|
"h": 7,
|
||||||
"w": 7,
|
"w": 7,
|
||||||
"x": 17,
|
"x": 17,
|
||||||
"y": 20
|
"y": 14
|
||||||
},
|
},
|
||||||
"id": 16,
|
"id": 16,
|
||||||
"options": {
|
"options": {
|
||||||
@ -962,12 +952,11 @@
|
|||||||
"showLegend": true
|
"showLegend": true
|
||||||
},
|
},
|
||||||
"tooltip": {
|
"tooltip": {
|
||||||
"hideZeros": false,
|
|
||||||
"mode": "single",
|
"mode": "single",
|
||||||
"sort": "none"
|
"sort": "none"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pluginVersion": "11.5.2",
|
"pluginVersion": "11.4.0",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"editorMode": "code",
|
"editorMode": "code",
|
||||||
@ -986,20 +975,19 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"preload": false,
|
"preload": false,
|
||||||
"refresh": "10s",
|
|
||||||
"schemaVersion": 40,
|
"schemaVersion": 40,
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"templating": {
|
"templating": {
|
||||||
"list": []
|
"list": []
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
"from": "now-5m",
|
"from": "now-24h",
|
||||||
"to": "now"
|
"to": "now"
|
||||||
},
|
},
|
||||||
"timepicker": {},
|
"timepicker": {},
|
||||||
"timezone": "",
|
"timezone": "",
|
||||||
"title": "HMAC File Server Metrics",
|
"title": "HMAC File Server Metrics",
|
||||||
"uid": "de0ye5t0hzq4ge",
|
"uid": "de0ye5t0hzq4ge",
|
||||||
"version": 158,
|
"version": 153,
|
||||||
"weekStart": ""
|
"weekStart": ""
|
||||||
}
|
}
|
||||||
|
69
lib/maps/iter.go
Normal file
69
lib/maps/iter.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package maps
|
||||||
|
|
||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
type Seq2[K comparable, V any] func(yield func(K, V) bool)
|
||||||
|
type Seq[K any] func(yield func(K) bool)
|
||||||
|
|
||||||
|
func All[Map ~map[K]V, K comparable, V any](m Map) Seq2[K, V] {
|
||||||
|
return func(yield func(K, V) bool) {
|
||||||
|
for k, v := range m {
|
||||||
|
if !yield(k, v) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All returns an iterator over key-value pairs from m.
|
||||||
|
// The iteration order is not specified and is not guaranteed
|
||||||
|
// to be the same from one call to the next.
|
||||||
|
|
||||||
|
func Insert[Map ~map[K]V, K comparable, V any](m Map, seq Seq2[K, V]) {
|
||||||
|
seq(func(k K, v V) bool {
|
||||||
|
m[k] = v
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert adds the key-value pairs from seq to m.
|
||||||
|
// If a key in seq already exists in m, its value will be overwritten.
|
||||||
|
|
||||||
|
func Collect[K comparable, V any](seq Seq2[K, V]) map[K]V {
|
||||||
|
m := make(map[K]V)
|
||||||
|
Insert(m, seq)
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect collects key-value pairs from seq into a new map
|
||||||
|
// and returns it.
|
||||||
|
|
||||||
|
func Keys[Map ~map[K]V, K comparable, V any](m Map) Seq[K] {
|
||||||
|
return func(yield func(K) bool) {
|
||||||
|
for k := range m {
|
||||||
|
if !yield(k) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns an iterator over keys in m.
|
||||||
|
// The iteration order is not specified and is not guaranteed
|
||||||
|
// to be the same from one call to the next.
|
||||||
|
|
||||||
|
func Values[Map ~map[K]V, K comparable, V any](m Map) Seq[V] {
|
||||||
|
return func(yield func(V) bool) {
|
||||||
|
for _, v := range m {
|
||||||
|
if !yield(v) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns an iterator over values in m.
|
||||||
|
// The iteration order is not specified and is not guaranteed
|
||||||
|
// to be the same from one call to the next.
|
Loading…
x
Reference in New Issue
Block a user