diff --git a/lib/towerops/proto/agent.pb.ex b/lib/towerops/proto/agent.pb.ex index d1d5e32a..36d26213 100644 --- a/lib/towerops/proto/agent.pb.ex +++ b/lib/towerops/proto/agent.pb.ex @@ -38,6 +38,7 @@ defmodule Towerops.Agent.AgentConfig do field :version, 1, type: :string field :poll_interval_seconds, 2, type: :uint32, json_name: "pollIntervalSeconds" field :devices, 3, repeated: true, type: Towerops.Agent.Device + field :checks, 4, repeated: true, type: Towerops.Agent.Check end defmodule Towerops.Agent.Device do @@ -71,6 +72,7 @@ defmodule Towerops.Agent.SnmpConfig do field :version, 2, type: :string field :community, 3, type: :string field :port, 4, type: :uint32 + field :transport, 5, type: :string end defmodule Towerops.Agent.Sensor.MetadataEntry do @@ -155,6 +157,11 @@ defmodule Towerops.Agent.Metric do type: Towerops.Agent.MonitoringCheck, json_name: "monitoringCheck", oneof: 0 + + field :check_result, 5, + type: Towerops.Agent.CheckResult, + json_name: "checkResult", + oneof: 0 end defmodule Towerops.Agent.SensorReading do @@ -298,6 +305,7 @@ defmodule Towerops.Agent.SnmpDevice do field :v3_auth_password, 8, type: :string, json_name: "v3AuthPassword" field :v3_priv_protocol, 9, type: :string, json_name: "v3PrivProtocol" field :v3_priv_password, 10, type: :string, json_name: "v3PrivPassword" + field :transport, 11, type: :string end defmodule Towerops.Agent.SnmpQuery do @@ -472,3 +480,109 @@ defmodule Towerops.Agent.MikrotikSentence do type: Towerops.Agent.MikrotikSentence.AttributesEntry, map: true end + +# Service Checks (HTTP/TCP/DNS) + +defmodule Towerops.Agent.Check do + @moduledoc false + + use Protobuf, + full_name: "towerops.agent.Check", + protoc_gen_elixir_version: "0.16.0", + syntax: :proto3 + + oneof(:config, 0) + + field :id, 1, type: :string + field :check_type, 2, type: :string, json_name: "checkType" + field :interval_seconds, 3, type: :uint32, json_name: "intervalSeconds" + field :timeout_ms, 4, type: :uint32, json_name: "timeoutMs" + field :http, 5, type: Towerops.Agent.HttpCheckConfig, oneof: 0 + field :tcp, 6, type: Towerops.Agent.TcpCheckConfig, oneof: 0 + field :dns, 7, type: Towerops.Agent.DnsCheckConfig, oneof: 0 +end + +defmodule Towerops.Agent.HttpCheckConfig.HeadersEntry do + @moduledoc false + + use Protobuf, + full_name: "towerops.agent.HttpCheckConfig.HeadersEntry", + map: true, + protoc_gen_elixir_version: "0.16.0", + syntax: :proto3 + + field :key, 1, type: :string + field :value, 2, type: :string +end + +defmodule Towerops.Agent.HttpCheckConfig do + @moduledoc false + + use Protobuf, + full_name: "towerops.agent.HttpCheckConfig", + protoc_gen_elixir_version: "0.16.0", + syntax: :proto3 + + field :url, 1, type: :string + field :method, 2, type: :string + field :expected_status, 3, type: :uint32, json_name: "expectedStatus" + field :verify_ssl, 4, type: :bool, json_name: "verifySsl" + field :headers, 5, repeated: true, type: Towerops.Agent.HttpCheckConfig.HeadersEntry, map: true + field :body, 6, type: :string + field :regex, 7, type: :string + field :follow_redirects, 8, type: :bool, json_name: "followRedirects" +end + +defmodule Towerops.Agent.TcpCheckConfig do + @moduledoc false + + use Protobuf, + full_name: "towerops.agent.TcpCheckConfig", + protoc_gen_elixir_version: "0.16.0", + syntax: :proto3 + + field :host, 1, type: :string + field :port, 2, type: :uint32 + field :send, 3, type: :string + field :expect, 4, type: :string +end + +defmodule Towerops.Agent.DnsCheckConfig do + @moduledoc false + + use Protobuf, + full_name: "towerops.agent.DnsCheckConfig", + protoc_gen_elixir_version: "0.16.0", + syntax: :proto3 + + field :hostname, 1, type: :string + field :server, 2, type: :string + field :record_type, 3, type: :string, json_name: "recordType" + field :expected, 4, type: :string +end + +defmodule Towerops.Agent.CheckResult do + @moduledoc false + + use Protobuf, + full_name: "towerops.agent.CheckResult", + protoc_gen_elixir_version: "0.16.0", + syntax: :proto3 + + field :check_id, 1, type: :string, json_name: "checkId" + field :status, 2, type: :uint32 + field :output, 3, type: :string + field :response_time_ms, 4, type: :double, json_name: "responseTimeMs" + field :timestamp, 5, type: :int64 +end + +defmodule Towerops.Agent.CheckList do + @moduledoc false + + use Protobuf, + full_name: "towerops.agent.CheckList", + protoc_gen_elixir_version: "0.16.0", + syntax: :proto3 + + field :checks, 1, repeated: true, type: Towerops.Agent.Check +end diff --git a/priv/proto/agent.proto b/priv/proto/agent.proto index dcca9113..47cf6b40 100644 --- a/priv/proto/agent.proto +++ b/priv/proto/agent.proto @@ -7,6 +7,7 @@ message AgentConfig { string version = 1; uint32 poll_interval_seconds = 2; repeated Device devices = 3; + repeated Check checks = 4; // Service checks (HTTP/TCP/DNS) } message Device { @@ -26,6 +27,7 @@ message SnmpConfig { string version = 2; string community = 3; uint32 port = 4; + string transport = 5; } message Sensor { @@ -54,6 +56,7 @@ message Metric { InterfaceStat interface_stat = 2; NeighborDiscovery neighbor_discovery = 3; MonitoringCheck monitoring_check = 4; + CheckResult check_result = 5; // Service check results (HTTP/TCP/DNS) } } @@ -96,6 +99,59 @@ message MonitoringCheck { int64 timestamp = 4; // Unix timestamp in seconds } +// Service Checks (HTTP/TCP/DNS) + +message Check { + string id = 1; + string check_type = 2; // "http", "tcp", "dns" + uint32 interval_seconds = 3; + uint32 timeout_ms = 4; + + // Type-specific config (JSON from Phoenix config field) + oneof config { + HttpCheckConfig http = 5; + TcpCheckConfig tcp = 6; + DnsCheckConfig dns = 7; + } +} + +message HttpCheckConfig { + string url = 1; + string method = 2; // GET, POST, etc. + uint32 expected_status = 3; + bool verify_ssl = 4; + map headers = 5; + string body = 6; + string regex = 7; // Content match regex + bool follow_redirects = 8; +} + +message TcpCheckConfig { + string host = 1; + uint32 port = 2; + string send = 3; // Data to send after connection + string expect = 4; // Expected response +} + +message DnsCheckConfig { + string hostname = 1; + string server = 2; // DNS server (optional) + string record_type = 3; // A, AAAA, CNAME, MX, TXT + string expected = 4; // Expected result (optional) +} + +message CheckResult { + string check_id = 1; + uint32 status = 2; // 0=OK, 1=WARNING, 2=CRITICAL, 3=UNKNOWN + string output = 3; + double response_time_ms = 4; + int64 timestamp = 5; // Unix timestamp in seconds +} + +message CheckList { + repeated Check checks = 1; +} + // Heartbeat metadata message HeartbeatMetadata { string version = 1; @@ -149,6 +205,7 @@ message SnmpDevice { string v3_auth_password = 8; // Decrypted before sending string v3_priv_protocol = 9; // "DES" | "AES" | "AES-256" | etc. string v3_priv_password = 10; // Decrypted before sending + string transport = 11; // "udp" | "tcp" } message SnmpQuery { @@ -169,6 +226,7 @@ message AgentHeartbeat { string hostname = 2; uint64 uptime_seconds = 3; string ip_address = 4; + string arch = 5; } message AgentError {