Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 851985a9d0 | |||
| 48469b03db | |||
| 29860bd098 | |||
| f820c641b4 |
@@ -2,48 +2,21 @@ services:
|
|||||||
watcher:
|
watcher:
|
||||||
image: git.triggermeelmo.com/triggermeelmo/watcher-server:latest
|
image: git.triggermeelmo.com/triggermeelmo/watcher-server:latest
|
||||||
container_name: watcher
|
container_name: watcher
|
||||||
|
|
||||||
# Resource Management
|
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 200M
|
memory: 200M
|
||||||
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
user: "1000:1000"
|
||||||
# Security - User/Group ID aus Umgebungsvariablen
|
|
||||||
user: "${USER_UID:-1000}:${USER_GID:-1000}"
|
|
||||||
|
|
||||||
# Health Check
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
|
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 40s
|
start_period: 40s
|
||||||
|
|
||||||
# Environment
|
|
||||||
environment:
|
environment:
|
||||||
# Non-Root User
|
|
||||||
- USER_UID=1000 # Standard 1000
|
|
||||||
- USER_GID=1000 # Standard 1000
|
|
||||||
|
|
||||||
# Timezone
|
|
||||||
- TZ=Europe/Berlin
|
|
||||||
|
|
||||||
# Update Check
|
|
||||||
- UPDATE_CHECK_ENABLED=true
|
|
||||||
- UPDATE_CHECK_INTERVAL_HOURS=24
|
|
||||||
- UPDATE_CHECK_REPOSITORY_URL=https://git.triggermeelmo.com/api/v1/repos/Watcher/watcher/releases/latest
|
|
||||||
|
|
||||||
# Data Retention Policy
|
|
||||||
- METRIC_RETENTION_DAYS=30
|
|
||||||
- METRIC_CLEANUP_INTERVAL_HOURS=24
|
|
||||||
- METRIC_CLEANUP_ENABLED=true
|
|
||||||
|
|
||||||
# Aktualisierungsrate Frontend
|
# Aktualisierungsrate Frontend
|
||||||
- FRONTEND_REFRESH_INTERVAL_SECONDS=30
|
- FRONTEND_REFRESH_INTERVAL_SECONDS=30
|
||||||
|
|
||||||
# OIDC-Authentifizierung (Optional)
|
# OIDC-Authentifizierung (Optional)
|
||||||
# - OIDC_ENABLED=true
|
# - OIDC_ENABLED=true
|
||||||
# - OIDC_AUTHORITY=https://auth.example.com/realms/myrealm
|
# - OIDC_AUTHORITY=https://auth.example.com/realms/myrealm
|
||||||
@@ -54,23 +27,19 @@ services:
|
|||||||
# - OIDC_CLAIM_USERNAME=preferred_username
|
# - OIDC_CLAIM_USERNAME=preferred_username
|
||||||
# - OIDC_CLAIM_EMAIL=email
|
# - OIDC_CLAIM_EMAIL=email
|
||||||
# - OIDC_AUTO_PROVISION_USERS=true
|
# - OIDC_AUTO_PROVISION_USERS=true
|
||||||
|
|
||||||
# Ports
|
|
||||||
ports:
|
ports:
|
||||||
- "5000:5000"
|
- "5000:5000"
|
||||||
|
|
||||||
# Volumes
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/db:/app/persistence
|
- ./data/db:/app/persistence
|
||||||
- ./data/dumps:/app/wwwroot/downloads/sqlite
|
- ./data/dumps:/app/wwwroot/downloads/sqlite
|
||||||
- ./data/logs:/app/logs
|
- ./data/logs:/app/logs
|
||||||
|
|
||||||
# Labels (Traefik Integration)
|
|
||||||
labels:
|
labels:
|
||||||
|
# Traefik konfiguration
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.watcher.rule=Host(`watcher.example.com`)"
|
- "traefik.http.routers.watcher.rule=Host(`watcher.example.com`)"
|
||||||
- "traefik.http.routers.watcher.entrypoints=websecure"
|
- "traefik.http.routers.watcher.entrypoints=websecure"
|
||||||
- "traefik.http.routers.watcher.tls.certresolver=letsencrypt"
|
- "traefik.http.routers.watcher.tls.certresolver=letsencrypt"
|
||||||
- "traefik.http.services.watcher.loadbalancer.server.port=5000"
|
- "traefik.http.services.watcher.loadbalancer.server.port=5000"
|
||||||
|
# Labels, die von watcher-agent verwendet werden
|
||||||
- "com.watcher.description=Server Monitoring Application"
|
- "com.watcher.description=Server Monitoring Application"
|
||||||
- "com.watcher.version=${IMAGE_VERSION:-latest}"
|
- "com.watcher.version=${IMAGE_VERSION:-latest}"
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class APIController : Controller
|
|||||||
GpuType = serverDto.GpuType,
|
GpuType = serverDto.GpuType,
|
||||||
RamSize = serverDto.RamSize,
|
RamSize = serverDto.RamSize,
|
||||||
DiskSpace = serverDto.DiskSpace,
|
DiskSpace = serverDto.DiskSpace,
|
||||||
IsOnline = serverDto.IsOnline,
|
State = serverDto.State,
|
||||||
IsVerified = serverDto.IsVerified
|
IsVerified = serverDto.IsVerified
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ public class HomeController : Controller
|
|||||||
servers = _servers,
|
servers = _servers,
|
||||||
containers = _containers,
|
containers = _containers,
|
||||||
serversCount = _servers.Count,
|
serversCount = _servers.Count,
|
||||||
serversOnline = (from server in _servers where server.IsOnline select server).Count(),
|
serversOnline = (from server in _servers where server.State=="online" select server).Count(),
|
||||||
serversOffline = _servers.Count - (from server in _servers where server.IsOnline select server).Count()
|
serversOffline = (from server in _servers where server.State=="offline" select server).Count()
|
||||||
};
|
};
|
||||||
|
|
||||||
return View(homeVm);
|
return View(homeVm);
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using System.Diagnostics;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using watcher_monitoring.Models;
|
||||||
|
|
||||||
using watcher_monitoring.Data;
|
using watcher_monitoring.Data;
|
||||||
|
using watcher_monitoring.ViewModels;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace watcher_monitoring.Controllers;
|
namespace watcher_monitoring.Controllers;
|
||||||
|
|
||||||
@@ -28,7 +32,12 @@ public class MonitoringController : Controller
|
|||||||
[HttpGet("server")]
|
[HttpGet("server")]
|
||||||
public async Task <IActionResult> ServerIndex()
|
public async Task <IActionResult> ServerIndex()
|
||||||
{
|
{
|
||||||
return View();
|
var ServerIndexViewModel = new ServerIndexViewModel
|
||||||
|
{
|
||||||
|
servers = await _context.Servers.ToListAsync()
|
||||||
|
};
|
||||||
|
|
||||||
|
return View(ServerIndexViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
186
watcher-monitoring/Migrations/20260121112553_changedServerAndContainerAttributeState.Designer.cs
generated
Normal file
186
watcher-monitoring/Migrations/20260121112553_changedServerAndContainerAttributeState.Designer.cs
generated
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using watcher_monitoring.Data;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace watcher_monitoring.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(WatcherDbContext))]
|
||||||
|
[Migration("20260121112553_changedServerAndContainerAttributeState")]
|
||||||
|
partial class changedServerAndContainerAttributeState
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder.HasAnnotation("ProductVersion", "8.0.6");
|
||||||
|
|
||||||
|
modelBuilder.Entity("watcher_monitoring.Models.ApiKey", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("ExpiresAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("IsActive")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastUsedAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("ApiKeys");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("watcher_monitoring.Models.Container", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("ContainerName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Containers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("watcher_monitoring.Models.Server", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("CpuCores")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("CpuType")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("DiskSpace")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("GpuType")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("IPAddress")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("IsVerified")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastSeen")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<double>("RamSize")
|
||||||
|
.HasColumnType("REAL");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Servers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("watcher_monitoring.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("IsActive")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastLogin")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("OidcSubject")
|
||||||
|
.HasMaxLength(255)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Password")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("watcher_monitoring.Models.ApiKey", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("watcher_monitoring.Models.User", "User")
|
||||||
|
.WithMany("ApiKeys")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("watcher_monitoring.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ApiKeys");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace watcher_monitoring.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class changedServerAndContainerAttributeState : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "IsOnline",
|
||||||
|
table: "Servers");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "State",
|
||||||
|
table: "Servers",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "State",
|
||||||
|
table: "Containers",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "State",
|
||||||
|
table: "Servers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "State",
|
||||||
|
table: "Containers");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "IsOnline",
|
||||||
|
table: "Servers",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -69,6 +69,10 @@ namespace watcher_monitoring.Migrations
|
|||||||
.HasMaxLength(50)
|
.HasMaxLength(50)
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("Containers");
|
b.ToTable("Containers");
|
||||||
@@ -99,9 +103,6 @@ namespace watcher_monitoring.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b.Property<bool>("IsOnline")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<bool>("IsVerified")
|
b.Property<bool>("IsVerified")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
@@ -115,6 +116,10 @@ namespace watcher_monitoring.Migrations
|
|||||||
b.Property<double>("RamSize")
|
b.Property<double>("RamSize")
|
||||||
.HasColumnType("REAL");
|
.HasColumnType("REAL");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("Servers");
|
b.ToTable("Servers");
|
||||||
|
|||||||
@@ -13,4 +13,6 @@ public class Container
|
|||||||
[StringLength(50)]
|
[StringLength(50)]
|
||||||
public required string ContainerName { get; set; } = null!;
|
public required string ContainerName { get; set; } = null!;
|
||||||
|
|
||||||
|
public required string State { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class Server
|
|||||||
// Metadata
|
// Metadata
|
||||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||||
|
|
||||||
public bool IsOnline { get; set; } = false;
|
public string State { get; set; }
|
||||||
|
|
||||||
public DateTime LastSeen { get; set; }
|
public DateTime LastSeen { get; set; }
|
||||||
|
|
||||||
|
|||||||
10
watcher-monitoring/ViewModels/ServerIndexViewModel.cs
Normal file
10
watcher-monitoring/ViewModels/ServerIndexViewModel.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using watcher_monitoring.Data;
|
||||||
|
using watcher_monitoring.Models;
|
||||||
|
|
||||||
|
namespace watcher_monitoring.ViewModels;
|
||||||
|
|
||||||
|
public class ServerIndexViewModel
|
||||||
|
{
|
||||||
|
public List<Server> servers { get; set; } = new();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,16 +14,20 @@
|
|||||||
|
|
||||||
<div class="row g-4 mb-4">
|
<div class="row g-4 mb-4">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="metric-card">
|
<a href="/monitoring/server" style="text-decoration: none;">
|
||||||
<div class="metric-label">Total Servers</div>
|
<div class="metric-card">
|
||||||
<div class="metric-value">@Model.serversCount</div>
|
<div class="metric-label">Total Servers</div>
|
||||||
</div>
|
<div class="metric-value">@Model.serversCount</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="metric-card">
|
<a href="/monitoring/container" style="text-decoration: none;">
|
||||||
<div class="metric-label">Online</div>
|
<div class="metric-card">
|
||||||
<div class="metric-value" style="color: var(--success)">@Model.serversOnline</div>
|
<div class="metric-label">Online</div>
|
||||||
</div>
|
<div class="metric-value" style="color: var(--success)">@Model.serversOnline</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="metric-card">
|
<div class="metric-card">
|
||||||
@@ -42,21 +46,24 @@
|
|||||||
<div class="row g-4">
|
<div class="row g-4">
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2 class="card-title"><a href="/Monitoring/server" style="text-decoration: none;">Monitored Servers</a></h2>
|
<h2 class="card-title"><a href="/Monitoring/server" style="text-decoration: none;">Server Issues</a></h2>
|
||||||
<ul class="server-list">
|
<ul class="server-list">
|
||||||
@if (Model.servers != null && Model.servers.Count > 0)
|
@if (Model.servers != null && Model.servers.Count > 0)
|
||||||
{
|
{
|
||||||
@foreach (var server in Model.servers)
|
@foreach (var server in Model.servers)
|
||||||
{
|
{
|
||||||
<li class="server-item">
|
@if (server.State != "online")
|
||||||
|
{
|
||||||
|
<li class="server-item">
|
||||||
<div class="server-info">
|
<div class="server-info">
|
||||||
<span class="server-name">@server.Name</span>
|
<span class="server-name">@server.Name</span>
|
||||||
<span class="server-ip">@server.IPAddress</span>
|
<span class="server-ip">@server.IPAddress</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="status-badge @(server.IsOnline ? "status-online" : "status-offline")">
|
<span class="status-badge @(server.State=="warning" ? "status-warning" : "status-offline")">
|
||||||
@(server.IsOnline ? "Online" : "Offline")
|
@(server.State=="warning" ? "Warning" : "Offline")
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -70,18 +77,20 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2 class="card-title"><a href="/Monitoring/server" style="text-decoration: none;">Monitored Containers</a></h2>
|
<h2 class="card-title"><a href="/Monitoring/server" style="text-decoration: none;">Container Issues</a></h2>
|
||||||
<ul class="server-list">
|
<ul class="server-list">
|
||||||
@if (Model.containers != null && Model.containers.Count > 0)
|
@if (Model.containers != null && Model.containers.Count > 0)
|
||||||
{
|
{
|
||||||
@foreach (var container in Model.containers)
|
@foreach (var container in Model.containers)
|
||||||
{
|
{
|
||||||
<li class="server-item">
|
@if (container.State != "online") {
|
||||||
<div class="server-info">
|
<li class="server-item">
|
||||||
<span class="server-name">@container.Name</span>
|
<div class="server-info">
|
||||||
<span class="server-ip">Container Image</span>
|
<span class="server-name">@container.Name</span>
|
||||||
</div>
|
<span class="server-ip">Container Image</span>
|
||||||
</li>
|
</div>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -11,251 +11,48 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row g-4">
|
<div class="row g-4">
|
||||||
<!-- Server Card 1 -->
|
@foreach (var server in Model.servers)
|
||||||
<div class="col-xl-4 col-lg-6">
|
{
|
||||||
<div class="card server-detail-card">
|
<div class="col-xl-4 col-lg-6">
|
||||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
<div class="card server-detail-card">
|
||||||
<div>
|
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||||
<h2 class="card-title mb-1">test</h2>
|
<div>
|
||||||
<span class="server-ip">192.168.1.100</span>
|
<h2 class="card-title mb-1">@server.Name</h2>
|
||||||
</div>
|
<span class="server-ip">@server.IPAddress</span>
|
||||||
<span class="status-badge status-online">Online</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="server-metrics">
|
|
||||||
<!-- CPU Load -->
|
|
||||||
<div class="metric-section mb-3">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
||||||
<span class="metric-label-small">CPU Load</span>
|
|
||||||
<span class="metric-value-small">400%</span>
|
|
||||||
</div>
|
</div>
|
||||||
<canvas id="cpuChart1" class="chart-canvas"></canvas>
|
<span class="status-badge status-online">@server.State</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- RAM Load -->
|
<div class="server-metrics">
|
||||||
<div class="metric-section mb-3">
|
<!-- CPU Load -->
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
<div class="metric-section mb-3">
|
||||||
<span class="metric-label-small">RAM Load</span>
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||||
<span class="metric-value-small">400 MB</span>
|
<span class="metric-label-small">CPU Load</span>
|
||||||
|
<span class="metric-value-small">400%</span>
|
||||||
|
</div>
|
||||||
|
<canvas id="cpuChart1" class="chart-canvas"></canvas>
|
||||||
</div>
|
</div>
|
||||||
<canvas id="ramChart1" class="chart-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Uptime -->
|
<!-- RAM Load -->
|
||||||
<div class="metric-section">
|
<div class="metric-section mb-3">
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||||
<span class="metric-label-small">Uptime</span>
|
<span class="metric-label-small">RAM Load</span>
|
||||||
<span class="metric-value-small">400 days</span>
|
<span class="metric-value-small">400 MB</span>
|
||||||
|
</div>
|
||||||
|
<canvas id="ramChart1" class="chart-canvas"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Uptime -->
|
||||||
|
<div class="metric-section">
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
<span class="metric-label-small">Uptime</span>
|
||||||
|
<span class="metric-value-small">400 days</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
|
|
||||||
<!-- Server Card 2 -->
|
|
||||||
<div class="col-xl-4 col-lg-6">
|
|
||||||
<div class="card server-detail-card">
|
|
||||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
|
||||||
<div>
|
|
||||||
<h2 class="card-title mb-1">test</h2>
|
|
||||||
<span class="server-ip">192.168.1.101</span>
|
|
||||||
</div>
|
|
||||||
<span class="status-badge status-online">Online</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="server-metrics">
|
|
||||||
<!-- CPU Load -->
|
|
||||||
<div class="metric-section mb-3">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
||||||
<span class="metric-label-small">CPU Load</span>
|
|
||||||
<span class="metric-value-small">400%</span>
|
|
||||||
</div>
|
|
||||||
<canvas id="cpuChart2" class="chart-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- RAM Load -->
|
|
||||||
<div class="metric-section mb-3">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
||||||
<span class="metric-label-small">RAM Load</span>
|
|
||||||
<span class="metric-value-small">400 MB</span>
|
|
||||||
</div>
|
|
||||||
<canvas id="ramChart2" class="chart-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Uptime -->
|
|
||||||
<div class="metric-section">
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<span class="metric-label-small">Uptime</span>
|
|
||||||
<span class="metric-value-small">400 days</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Server Card 3 -->
|
|
||||||
<div class="col-xl-4 col-lg-6">
|
|
||||||
<div class="card server-detail-card">
|
|
||||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
|
||||||
<div>
|
|
||||||
<h2 class="card-title mb-1">test</h2>
|
|
||||||
<span class="server-ip">192.168.1.102</span>
|
|
||||||
</div>
|
|
||||||
<span class="status-badge status-warning">Warning</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="server-metrics">
|
|
||||||
<!-- CPU Load -->
|
|
||||||
<div class="metric-section mb-3">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
||||||
<span class="metric-label-small">CPU Load</span>
|
|
||||||
<span class="metric-value-small">400%</span>
|
|
||||||
</div>
|
|
||||||
<canvas id="cpuChart3" class="chart-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- RAM Load -->
|
|
||||||
<div class="metric-section mb-3">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
||||||
<span class="metric-label-small">RAM Load</span>
|
|
||||||
<span class="metric-value-small">400 MB</span>
|
|
||||||
</div>
|
|
||||||
<canvas id="ramChart3" class="chart-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Uptime -->
|
|
||||||
<div class="metric-section">
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<span class="metric-label-small">Uptime</span>
|
|
||||||
<span class="metric-value-small">400 days</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Server Card 4 -->
|
|
||||||
<div class="col-xl-4 col-lg-6">
|
|
||||||
<div class="card server-detail-card">
|
|
||||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
|
||||||
<div>
|
|
||||||
<h2 class="card-title mb-1">test</h2>
|
|
||||||
<span class="server-ip">192.168.1.103</span>
|
|
||||||
</div>
|
|
||||||
<span class="status-badge status-online">Online</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="server-metrics">
|
|
||||||
<!-- CPU Load -->
|
|
||||||
<div class="metric-section mb-3">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
||||||
<span class="metric-label-small">CPU Load</span>
|
|
||||||
<span class="metric-value-small">400%</span>
|
|
||||||
</div>
|
|
||||||
<canvas id="cpuChart4" class="chart-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- RAM Load -->
|
|
||||||
<div class="metric-section mb-3">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
||||||
<span class="metric-label-small">RAM Load</span>
|
|
||||||
<span class="metric-value-small">400 MB</span>
|
|
||||||
</div>
|
|
||||||
<canvas id="ramChart4" class="chart-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Uptime -->
|
|
||||||
<div class="metric-section">
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<span class="metric-label-small">Uptime</span>
|
|
||||||
<span class="metric-value-small">400 days</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Server Card 5 -->
|
|
||||||
<div class="col-xl-4 col-lg-6">
|
|
||||||
<div class="card server-detail-card">
|
|
||||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
|
||||||
<div>
|
|
||||||
<h2 class="card-title mb-1">test</h2>
|
|
||||||
<span class="server-ip">192.168.1.104</span>
|
|
||||||
</div>
|
|
||||||
<span class="status-badge status-offline">Offline</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="server-metrics">
|
|
||||||
<!-- CPU Load -->
|
|
||||||
<div class="metric-section mb-3">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
||||||
<span class="metric-label-small">CPU Load</span>
|
|
||||||
<span class="metric-value-small">400%</span>
|
|
||||||
</div>
|
|
||||||
<canvas id="cpuChart5" class="chart-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- RAM Load -->
|
|
||||||
<div class="metric-section mb-3">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
||||||
<span class="metric-label-small">RAM Load</span>
|
|
||||||
<span class="metric-value-small">400 MB</span>
|
|
||||||
</div>
|
|
||||||
<canvas id="ramChart5" class="chart-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Uptime -->
|
|
||||||
<div class="metric-section">
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<span class="metric-label-small">Uptime</span>
|
|
||||||
<span class="metric-value-small">400 days</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Server Card 6 -->
|
|
||||||
<div class="col-xl-4 col-lg-6">
|
|
||||||
<div class="card server-detail-card">
|
|
||||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
|
||||||
<div>
|
|
||||||
<h2 class="card-title mb-1">test</h2>
|
|
||||||
<span class="server-ip">192.168.1.105</span>
|
|
||||||
</div>
|
|
||||||
<span class="status-badge status-online">Online</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="server-metrics">
|
|
||||||
<!-- CPU Load -->
|
|
||||||
<div class="metric-section mb-3">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
||||||
<span class="metric-label-small">CPU Load</span>
|
|
||||||
<span class="metric-value-small">400%</span>
|
|
||||||
</div>
|
|
||||||
<canvas id="cpuChart6" class="chart-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- RAM Load -->
|
|
||||||
<div class="metric-section mb-3">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
||||||
<span class="metric-label-small">RAM Load</span>
|
|
||||||
<span class="metric-value-small">400 MB</span>
|
|
||||||
</div>
|
|
||||||
<canvas id="ramChart6" class="chart-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Uptime -->
|
|
||||||
<div class="metric-section">
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<span class="metric-label-small">Uptime</span>
|
|
||||||
<span class="metric-value-small">400 days</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -346,7 +143,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Auto-refresh every 30 seconds
|
// Auto-refresh every 30 seconds
|
||||||
setInterval(function() {
|
setInterval(function () {
|
||||||
location.reload();
|
location.reload();
|
||||||
}, 30000);
|
}, 30000);
|
||||||
</script>
|
</script>
|
||||||
@@ -395,4 +192,4 @@
|
|||||||
max-height: 50px !important;
|
max-height: 50px !important;
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
Reference in New Issue
Block a user