diff --git a/Tests/test.json b/Tests/test.json new file mode 100644 index 0000000..8fa1f06 --- /dev/null +++ b/Tests/test.json @@ -0,0 +1,117 @@ +{ + "server_id": 1, + "containers": [ + { + "cpu": { + "cpu_load": 0.0 + }, + "network": { + "net_in": null, + "net_out": null + }, + "ram": { + "ram_load": 0.0 + }, + "container_id": "aaaaaaaa", + "status": { + "status": "exited" + } + }, + { + "cpu": { + "cpu_load": 0.0 + }, + "network": { + "net_in": null, + "net_out": null + }, + "ram": { + "ram_load": 0.0 + }, + "container_id": "aaaaaaaa", + "status": { + "status": "exited" + } + }, + { + "cpu": { + "cpu_load": 0.0 + }, + "network": { + "net_in": null, + "net_out": null + }, + "ram": { + "ram_load": 0.0 + }, + "container_id": "aaaaaaaa", + "status": { + "status": "exited" + } + }, + { + "cpu": { + "cpu_load": 0.0 + }, + "network": { + "net_in": null, + "net_out": null + }, + "ram": { + "ram_load": 0.0 + }, + "container_id": "aaaaaaaa", + "status": { + "status": "exited" + } + }, + { + "cpu": { + "cpu_load": 0.0 + }, + "network": { + "net_in": null, + "net_out": null + }, + "ram": { + "ram_load": 0.0 + }, + "container_id": "aaaaaaaa", + "status": { + "status": "exited" + } + }, + { + "cpu": { + "cpu_load": 0.0 + }, + "network": { + "net_in": null, + "net_out": null + }, + "ram": { + "ram_load": 0.0 + }, + "container_id": "aaaaaaaa", + "status": { + "status": "exited" + } + }, + { + "cpu": { + "cpu_load": 0.0 + }, + "network": { + "net_in": null, + "net_out": null + }, + "ram": { + "ram_load": 0.0 + }, + "container_id": "aaaaaaaa", + "status": { + "status": "exited" + } + } + ] +} \ No newline at end of file diff --git a/Watcher/Controllers/MonitoringController.cs b/Watcher/Controllers/MonitoringController.cs index 59f4fb9..cea7e9b 100644 --- a/Watcher/Controllers/MonitoringController.cs +++ b/Watcher/Controllers/MonitoringController.cs @@ -90,7 +90,8 @@ public class DockerServiceDto public class DockerServiceMetricDto { - + public required int Server_id { get; set; } // Vom Watcher-Server zugewiesene ID des Hosts + public required JsonElement Containers { get; set; } } [ApiController] @@ -330,17 +331,20 @@ public class MonitoringController : Controller return BadRequest(new { error = "Invalid Payload", details = errors }); } - // Liste an Metrics aus der dto erstellen + // Liste der eingegangenen Metric List metrics = new List(); + // Json Parser -> Metric Objekt erstellen + + // Metrics in die Datenbank eintragen try { - foreach (ContainerMetric m in metrics) + foreach (ContainerMetric cm in metrics) { - _context.ContainerMetrics.Add(m); + _context.ContainerMetrics.Add(cm); await _context.SaveChangesAsync(); - // _logger.LogInformation(m. + " added for Host " + c.ServerId); + _logger.LogInformation(cm.ContainerId + " Metric received"); return Ok(); } } diff --git a/Watcher/Migrations/20251030093420_ContainerMetricChange.Designer.cs b/Watcher/Migrations/20251030093420_ContainerMetricChange.Designer.cs new file mode 100644 index 0000000..df3a4e6 --- /dev/null +++ b/Watcher/Migrations/20251030093420_ContainerMetricChange.Designer.cs @@ -0,0 +1,397 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Watcher.Data; + +#nullable disable + +namespace Watcher.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20251030093420_ContainerMetricChange")] + partial class ContainerMetricChange + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.6"); + + modelBuilder.Entity("Watcher.Models.Container", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ContainerId") + .HasColumnType("TEXT") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("Image") + .HasColumnType("TEXT") + .HasAnnotation("Relational:JsonPropertyName", "image"); + + b.Property("ImageId") + .HasColumnType("INTEGER"); + + b.Property("IsRunning") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT") + .HasAnnotation("Relational:JsonPropertyName", "name"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasAnnotation("Relational:JsonPropertyName", "Server_id"); + + b.Property("TagId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ImageId"); + + b.HasIndex("TagId"); + + b.ToTable("Containers"); + }); + + modelBuilder.Entity("Watcher.Models.ContainerMetric", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CPU_Load") + .HasColumnType("REAL") + .HasAnnotation("Relational:JsonPropertyName", "cpu_load"); + + b.Property("ContainerId") + .HasColumnType("INTEGER") + .HasAnnotation("Relational:JsonPropertyName", "container_id"); + + b.Property("NET_in") + .HasColumnType("REAL") + .HasAnnotation("Relational:JsonPropertyName", "net_in"); + + b.Property("NET_out") + .HasColumnType("REAL") + .HasAnnotation("Relational:JsonPropertyName", "net_out"); + + b.Property("RAM_Load") + .HasColumnType("REAL") + .HasAnnotation("Relational:JsonPropertyName", "ram_load"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasAnnotation("Relational:JsonPropertyName", "server_id"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ContainerMetrics"); + }); + + modelBuilder.Entity("Watcher.Models.Image", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Tag") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Images"); + }); + + modelBuilder.Entity("Watcher.Models.LogEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ContainerId") + .HasColumnType("INTEGER"); + + b.Property("Level") + .HasColumnType("TEXT"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ContainerId"); + + b.HasIndex("ServerId"); + + b.ToTable("LogEvents"); + }); + + modelBuilder.Entity("Watcher.Models.Metric", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CPU_Load") + .HasColumnType("REAL"); + + b.Property("CPU_Temp") + .HasColumnType("REAL"); + + b.Property("DISK_Size") + .HasColumnType("REAL"); + + b.Property("DISK_Temp") + .HasColumnType("REAL"); + + b.Property("DISK_Usage") + .HasColumnType("REAL"); + + b.Property("GPU_Load") + .HasColumnType("REAL"); + + b.Property("GPU_Temp") + .HasColumnType("REAL"); + + b.Property("GPU_Vram_Size") + .HasColumnType("REAL"); + + b.Property("GPU_Vram_Usage") + .HasColumnType("REAL"); + + b.Property("NET_In") + .HasColumnType("REAL"); + + b.Property("NET_Out") + .HasColumnType("REAL"); + + b.Property("RAM_Load") + .HasColumnType("REAL"); + + b.Property("RAM_Size") + .HasColumnType("REAL"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Metrics"); + }); + + modelBuilder.Entity("Watcher.Models.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CPU_Load_Critical") + .HasColumnType("REAL"); + + b.Property("CPU_Load_Warning") + .HasColumnType("REAL"); + + b.Property("CPU_Temp_Critical") + .HasColumnType("REAL"); + + b.Property("CPU_Temp_Warning") + .HasColumnType("REAL"); + + b.Property("CpuCores") + .HasColumnType("INTEGER"); + + b.Property("CpuType") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DISK_Temp_Critical") + .HasColumnType("REAL"); + + b.Property("DISK_Temp_Warning") + .HasColumnType("REAL"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("DiskSpace") + .HasColumnType("TEXT"); + + b.Property("Disk_Usage_Critical") + .HasColumnType("REAL"); + + b.Property("Disk_Usage_Warning") + .HasColumnType("REAL"); + + b.Property("GPU_Load_Critical") + .HasColumnType("REAL"); + + b.Property("GPU_Load_Warning") + .HasColumnType("REAL"); + + b.Property("GPU_Temp_Critical") + .HasColumnType("REAL"); + + b.Property("GPU_Temp_Warning") + .HasColumnType("REAL"); + + b.Property("GpuType") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsOnline") + .HasColumnType("INTEGER"); + + b.Property("IsVerified") + .HasColumnType("INTEGER"); + + b.Property("LastSeen") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("RAM_Load_Critical") + .HasColumnType("REAL"); + + b.Property("RAM_Load_Warning") + .HasColumnType("REAL"); + + b.Property("RamSize") + .HasColumnType("REAL"); + + b.Property("TagId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("TagId"); + + b.ToTable("Servers"); + }); + + modelBuilder.Entity("Watcher.Models.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("Watcher.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("IdentityProvider") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LastLogin") + .HasColumnType("TEXT"); + + b.Property("OIDC_Id") + .HasColumnType("TEXT"); + + b.Property("Password") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Watcher.Models.Container", b => + { + b.HasOne("Watcher.Models.Image", null) + .WithMany("Containers") + .HasForeignKey("ImageId"); + + b.HasOne("Watcher.Models.Tag", null) + .WithMany("Containers") + .HasForeignKey("TagId"); + }); + + modelBuilder.Entity("Watcher.Models.LogEvent", b => + { + b.HasOne("Watcher.Models.Container", "Container") + .WithMany() + .HasForeignKey("ContainerId"); + + b.HasOne("Watcher.Models.Server", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.Navigation("Container"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Watcher.Models.Server", b => + { + b.HasOne("Watcher.Models.Tag", null) + .WithMany("Servers") + .HasForeignKey("TagId"); + }); + + modelBuilder.Entity("Watcher.Models.Image", b => + { + b.Navigation("Containers"); + }); + + modelBuilder.Entity("Watcher.Models.Tag", b => + { + b.Navigation("Containers"); + + b.Navigation("Servers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Watcher/Migrations/20251030093420_ContainerMetricChange.cs b/Watcher/Migrations/20251030093420_ContainerMetricChange.cs new file mode 100644 index 0000000..86bb52e --- /dev/null +++ b/Watcher/Migrations/20251030093420_ContainerMetricChange.cs @@ -0,0 +1,41 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Watcher.Migrations +{ + /// + public partial class ContainerMetricChange : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ContainerMetrics", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Timestamp = table.Column(type: "TEXT", nullable: false), + ContainerId = table.Column(type: "INTEGER", nullable: true), + ServerId = table.Column(type: "INTEGER", nullable: true), + CPU_Load = table.Column(type: "REAL", nullable: false), + RAM_Load = table.Column(type: "REAL", nullable: false), + NET_in = table.Column(type: "REAL", nullable: false), + NET_out = table.Column(type: "REAL", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ContainerMetrics", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ContainerMetrics"); + } + } +} diff --git a/Watcher/Migrations/AppDbContextModelSnapshot.cs b/Watcher/Migrations/AppDbContextModelSnapshot.cs index b642f34..e14d48f 100644 --- a/Watcher/Migrations/AppDbContextModelSnapshot.cs +++ b/Watcher/Migrations/AppDbContextModelSnapshot.cs @@ -24,10 +24,12 @@ namespace Watcher.Migrations .HasColumnType("INTEGER"); b.Property("ContainerId") - .HasColumnType("TEXT"); + .HasColumnType("TEXT") + .HasAnnotation("Relational:JsonPropertyName", "id"); b.Property("Image") - .HasColumnType("TEXT"); + .HasColumnType("TEXT") + .HasAnnotation("Relational:JsonPropertyName", "image"); b.Property("ImageId") .HasColumnType("INTEGER"); @@ -36,10 +38,12 @@ namespace Watcher.Migrations .HasColumnType("INTEGER"); b.Property("Name") - .HasColumnType("TEXT"); + .HasColumnType("TEXT") + .HasAnnotation("Relational:JsonPropertyName", "name"); b.Property("ServerId") - .HasColumnType("INTEGER"); + .HasColumnType("INTEGER") + .HasAnnotation("Relational:JsonPropertyName", "Server_id"); b.Property("TagId") .HasColumnType("INTEGER"); @@ -53,6 +57,44 @@ namespace Watcher.Migrations b.ToTable("Containers"); }); + modelBuilder.Entity("Watcher.Models.ContainerMetric", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CPU_Load") + .HasColumnType("REAL") + .HasAnnotation("Relational:JsonPropertyName", "cpu_load"); + + b.Property("ContainerId") + .HasColumnType("INTEGER") + .HasAnnotation("Relational:JsonPropertyName", "container_id"); + + b.Property("NET_in") + .HasColumnType("REAL") + .HasAnnotation("Relational:JsonPropertyName", "net_in"); + + b.Property("NET_out") + .HasColumnType("REAL") + .HasAnnotation("Relational:JsonPropertyName", "net_out"); + + b.Property("RAM_Load") + .HasColumnType("REAL") + .HasAnnotation("Relational:JsonPropertyName", "ram_load"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasAnnotation("Relational:JsonPropertyName", "server_id"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ContainerMetrics"); + }); + modelBuilder.Entity("Watcher.Models.Image", b => { b.Property("Id") diff --git a/Watcher/Models/ContainerMetric.cs b/Watcher/Models/ContainerMetric.cs index 5c95d99..06cc59a 100644 --- a/Watcher/Models/ContainerMetric.cs +++ b/Watcher/Models/ContainerMetric.cs @@ -1,3 +1,5 @@ +using System.Text.Json.Serialization; + namespace Watcher.Models; public class ContainerMetric @@ -6,19 +8,26 @@ public class ContainerMetric public int Id { get; set; } public DateTime Timestamp { get; set; } - - // Zuordnung zu einem Container -- Foreign Key + // allgemeine Conainer Informationen + [JsonPropertyName("container_id")] public int? ContainerId { get; set; } + [JsonPropertyName("server_id")] + public int? ServerId { get; set; } // CPU-Daten + [JsonPropertyName("cpu_load")] public double CPU_Load { get; set; } = 0.0; // % - public double CPU_Temp { get; set; } = 0.0; // deg C - // RAM-Daten - public double RAM_Size { get; set; } = 0.0; // GB - + [JsonPropertyName("ram_load")] public double RAM_Load { get; set; } = 0.0; // % + // Network-Daten + [JsonPropertyName("net_in")] + public double NET_in { get; set; } = 0.0; // Bit + + [JsonPropertyName("net_out")] + public double NET_out { get; set; } = 0.0; // Bit + }