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{
|
||||
DualStack: true,
|
||||
Timeout: 5 * time.Second,
|
||||
KeepAlive: 30 * time.Second, // Added keep-alive for better network change handling
|
||||
}
|
||||
|
||||
var dualStackClient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
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())
|
||||
defer cancel()
|
||||
|
||||
if conf.Server.NetworkEvents {
|
||||
go monitorNetwork(ctx)
|
||||
go handleNetworkEvents(ctx)
|
||||
}
|
||||
go updateSystemMetrics(ctx)
|
||||
|
||||
if conf.ClamAV.ClamAVEnabled {
|
||||
@ -637,6 +634,9 @@ func main() {
|
||||
log.Fatalf("Server failed: %v", err)
|
||||
}
|
||||
} 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 {
|
||||
log.Fatalf("Server failed: %v", err)
|
||||
}
|
||||
@ -733,7 +733,7 @@ uploadqueuesize = 50
|
||||
# Add file-specific configurations here
|
||||
|
||||
[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 the requested URL for debugging
|
||||
log.Infof("handleRequest: Received URL path: %s", r.URL.String())
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
log.Warn("Failed to parse query parameters")
|
||||
@ -1708,26 +1727,6 @@ func handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
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 {
|
||||
case http.MethodPut:
|
||||
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
|
||||
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)
|
||||
|
||||
// HMAC validation
|
||||
@ -1860,7 +1851,6 @@ func handleUpload(w http.ResponseWriter, r *http.Request, absFilename, fileStore
|
||||
}
|
||||
|
||||
// Respond with 201 Created immediately
|
||||
w.Header().Set("Content-Type", "text/plain") // Ensure correct interpretation
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
if f, ok := w.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
@ -1965,14 +1955,7 @@ func handleDownload(w http.ResponseWriter, r *http.Request, absFilename, fileSto
|
||||
} else {
|
||||
startTime := time.Now()
|
||||
log.Infof("Initiating download for file: %s", absFilename)
|
||||
f, err := os.Open(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)
|
||||
http.ServeFile(w, r, absFilename)
|
||||
downloadDuration.Observe(time.Since(startTime).Seconds())
|
||||
downloadSizeBytes.Observe(float64(fileInfo.Size()))
|
||||
downloadsTotal.Inc()
|
||||
@ -2172,6 +2155,73 @@ func getFileInfo(absFilename string) (os.FileInfo, error) {
|
||||
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) {
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
@ -2757,23 +2807,13 @@ func detectIPVersion(ip string) string {
|
||||
}
|
||||
|
||||
func getOriginalClientIP(r *http.Request) string {
|
||||
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
|
||||
parts := strings.Split(xff, ",")
|
||||
for _, part := range parts {
|
||||
ip := strings.TrimSpace(part)
|
||||
if net.ParseIP(ip) != nil {
|
||||
return ip
|
||||
if ip := r.Header.Get("X-Forwarded-For"); ip != "" {
|
||||
parts := strings.Split(ip, ",")
|
||||
return strings.TrimSpace(parts[0])
|
||||
}
|
||||
if ip := r.Header.Get("X-Real-IP"); ip != "" {
|
||||
return strings.TrimSpace(ip)
|
||||
}
|
||||
}
|
||||
if rip := r.Header.Get("X-Real-IP"); rip != "" {
|
||||
if net.ParseIP(rip) != nil {
|
||||
return strings.TrimSpace(rip)
|
||||
}
|
||||
}
|
||||
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err == nil && host != "" && net.ParseIP(host) != nil {
|
||||
host, _, _ := net.SplitHostPort(r.RemoteAddr)
|
||||
return host
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -27,8 +27,8 @@
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 24,
|
||||
"h": 7,
|
||||
"w": 3,
|
||||
"x": 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",
|
||||
"mode": "html"
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"title": "HMAC Dashboard",
|
||||
"type": "text"
|
||||
},
|
||||
@ -77,8 +77,8 @@
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 6
|
||||
"x": 3,
|
||||
"y": 0
|
||||
},
|
||||
"id": 14,
|
||||
"options": {
|
||||
@ -105,7 +105,7 @@
|
||||
"sizing": "auto",
|
||||
"valueMode": "color"
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
@ -143,8 +143,8 @@
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 6,
|
||||
"x": 6,
|
||||
"y": 6
|
||||
"x": 9,
|
||||
"y": 0
|
||||
},
|
||||
"id": 18,
|
||||
"options": {
|
||||
@ -164,7 +164,7 @@
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
@ -203,9 +203,9 @@
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 4,
|
||||
"x": 12,
|
||||
"y": 6
|
||||
"w": 5,
|
||||
"x": 15,
|
||||
"y": 0
|
||||
},
|
||||
"id": 10,
|
||||
"options": {
|
||||
@ -225,7 +225,7 @@
|
||||
"textMode": "value",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
@ -262,8 +262,8 @@
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 4,
|
||||
"x": 16,
|
||||
"y": 6
|
||||
"x": 20,
|
||||
"y": 0
|
||||
},
|
||||
"id": 17,
|
||||
"options": {
|
||||
@ -283,7 +283,7 @@
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
@ -297,77 +297,6 @@
|
||||
"title": "HMAC GoRoutines",
|
||||
"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": {
|
||||
"default": true,
|
||||
@ -397,7 +326,7 @@
|
||||
"h": 7,
|
||||
"w": 5,
|
||||
"x": 0,
|
||||
"y": 13
|
||||
"y": 7
|
||||
},
|
||||
"id": 11,
|
||||
"options": {
|
||||
@ -417,7 +346,7 @@
|
||||
"textMode": "value",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
@ -460,7 +389,7 @@
|
||||
"h": 7,
|
||||
"w": 5,
|
||||
"x": 5,
|
||||
"y": 13
|
||||
"y": 7
|
||||
},
|
||||
"id": 12,
|
||||
"options": {
|
||||
@ -480,7 +409,7 @@
|
||||
"textMode": "value",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
@ -493,6 +422,77 @@
|
||||
"title": "HMAC Downloads",
|
||||
"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": {
|
||||
"default": true,
|
||||
@ -519,9 +519,9 @@
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 5,
|
||||
"x": 10,
|
||||
"y": 13
|
||||
"w": 3,
|
||||
"x": 13,
|
||||
"y": 7
|
||||
},
|
||||
"id": 13,
|
||||
"options": {
|
||||
@ -541,7 +541,7 @@
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
@ -580,9 +580,9 @@
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 5,
|
||||
"x": 15,
|
||||
"y": 13
|
||||
"w": 3,
|
||||
"x": 16,
|
||||
"y": 7
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
@ -602,7 +602,7 @@
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
@ -641,9 +641,9 @@
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 7,
|
||||
"w": 4,
|
||||
"x": 20,
|
||||
"y": 13
|
||||
"w": 5,
|
||||
"x": 19,
|
||||
"y": 7
|
||||
},
|
||||
"id": 21,
|
||||
"options": {
|
||||
@ -663,7 +663,7 @@
|
||||
"textMode": "value",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
@ -704,7 +704,7 @@
|
||||
"h": 7,
|
||||
"w": 3,
|
||||
"x": 0,
|
||||
"y": 20
|
||||
"y": 14
|
||||
},
|
||||
"id": 19,
|
||||
"options": {
|
||||
@ -724,7 +724,7 @@
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
@ -746,7 +746,21 @@
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"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,
|
||||
"mappings": [],
|
||||
@ -762,7 +776,8 @@
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"unit": "files"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
@ -770,42 +785,37 @@
|
||||
"h": 7,
|
||||
"w": 7,
|
||||
"x": 3,
|
||||
"y": 20
|
||||
"y": 14
|
||||
},
|
||||
"id": 22,
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"percentChangeColorMode": "standard",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"showPercentChange": false,
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
"tooltip": {
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"exemplar": false,
|
||||
"expr": "hmac_active_connections_total",
|
||||
"expr": "increase(hmac_file_server_clamav_scans_total[24h])",
|
||||
"format": "time_series",
|
||||
"instant": false,
|
||||
"instant": true,
|
||||
"interval": "",
|
||||
"legendFormat": "__auto",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "HMAC Active Connection(s)",
|
||||
"type": "stat"
|
||||
"title": "HMAC ClamAV San (24h)",
|
||||
"type": "histogram"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
@ -818,36 +828,17 @@
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"fillOpacity": 80,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"fieldMinMax": false,
|
||||
@ -873,7 +864,7 @@
|
||||
"h": 7,
|
||||
"w": 7,
|
||||
"x": 10,
|
||||
"y": 20
|
||||
"y": 14
|
||||
},
|
||||
"id": 23,
|
||||
"options": {
|
||||
@ -884,17 +875,16 @@
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
"exemplar": false,
|
||||
"expr": "hmac_deduplication_errors_total",
|
||||
"expr": "increase(hmac_file_server_clamav_errors_total[24h])",
|
||||
"format": "time_series",
|
||||
"instant": true,
|
||||
"interval": "",
|
||||
@ -903,8 +893,8 @@
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "HMAC Duplication Error",
|
||||
"type": "timeseries"
|
||||
"title": "HMAC ClamAV SanError(s) (24h)",
|
||||
"type": "histogram"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
@ -951,7 +941,7 @@
|
||||
"h": 7,
|
||||
"w": 7,
|
||||
"x": 17,
|
||||
"y": 20
|
||||
"y": 14
|
||||
},
|
||||
"id": 16,
|
||||
"options": {
|
||||
@ -962,12 +952,11 @@
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "11.5.2",
|
||||
"pluginVersion": "11.4.0",
|
||||
"targets": [
|
||||
{
|
||||
"editorMode": "code",
|
||||
@ -986,20 +975,19 @@
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"refresh": "10s",
|
||||
"schemaVersion": 40,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-5m",
|
||||
"from": "now-24h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "HMAC File Server Metrics",
|
||||
"uid": "de0ye5t0hzq4ge",
|
||||
"version": 158,
|
||||
"version": 153,
|
||||
"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