server_stats 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README_EN.md ADDED
@@ -0,0 +1,405 @@
1
+ # server_stats
2
+
3
+ [English](README_EN.md) | [Tiếng Việt](README.md)
4
+
5
+ A lightweight, **zero-dependency** Ruby gem designed to collect server statistics and resource utilization on **Ubuntu (Linux)** and **macOS**.
6
+
7
+ Supports both a **Command Line Interface (CLI)** and a **Ruby API** for direct integration into Rails, Sinatra, monitoring scripts, Sidekiq background jobs, health-check endpoints, and more.
8
+
9
+ ---
10
+
11
+ ## 🚀 Key Features
12
+
13
+ - **CPU Metrics**:
14
+ - Total CPU core count (Logical cores & Physical cores).
15
+ - CPU usage percentage (`usage_percent`).
16
+ - CPU model / chip architecture (Apple Silicon, Intel, AMD).
17
+ - System load averages (1m, 5m, 15m).
18
+ - **Memory (RAM) Metrics**:
19
+ - Total RAM (`total_bytes` & `total_human`).
20
+ - Actual free RAM (`free_bytes` & `free_human`).
21
+ - Available RAM (`available_bytes` & `available_human`).
22
+ - Used RAM (`used_bytes` & `used_human`).
23
+ - RAM usage percentage (`usage_percent`).
24
+ - Deep breakdown: Buffers, Cached, Swap (Linux) / Wired, Active, Inactive, Compressed (macOS).
25
+ - **Disk Storage Metrics**:
26
+ - Total disk space (`total_bytes` & `total_human`).
27
+ - Available / Free disk space (`available_bytes` & `available_human`).
28
+ - Used disk space (`used_bytes` & `used_human`).
29
+ - Disk usage percentage (`usage_percent`).
30
+ - Filesystem & mount path (inspect any custom mount point, defaults to `/`).
31
+ - **Operating System & Hardware Info**:
32
+ - OS name and release version (Ubuntu 20.04/22.04/24.04, macOS Sonoma/Sequoia,...).
33
+ - Server hostname.
34
+ - Architecture (x86_64, arm64, aarch64,...).
35
+ - Kernel release.
36
+ - System uptime (`uptime_seconds` & `uptime_human`).
37
+ - **Zero Dependencies**: Pure Ruby standard library implementation (`optparse`, `json`, `etc`, `socket`), requiring no native C extensions or third-party gem installations.
38
+
39
+ ---
40
+
41
+ ## 📋 System Requirements
42
+
43
+ - Ruby `>= 2.5.0` (fully compatible with Ruby 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4+).
44
+ - Operating Systems:
45
+ - **Ubuntu / Debian / Linux** (x86_64, aarch64).
46
+ - **macOS** (both Apple Silicon M1/M2/M3/M4 and Intel).
47
+
48
+ ---
49
+
50
+ ## 📦 Installation
51
+
52
+ ### Method 1: Install directly via `gem`
53
+ ```bash
54
+ gem install server_stats
55
+ ```
56
+
57
+ ### Method 2: Add to your application's `Gemfile`
58
+ Add the following line to your `Gemfile`:
59
+ ```ruby
60
+ gem 'server_stats'
61
+ ```
62
+ Then install via Bundler:
63
+ ```bash
64
+ bundle install
65
+ ```
66
+
67
+ ### Method 3: Build from source
68
+ ```bash
69
+ git clone https://github.com/ntamvl/server_stats.git
70
+ cd server_stats
71
+ gem build server_stats.gemspec
72
+ gem install server_stats-0.1.0.gem
73
+ ```
74
+
75
+ ---
76
+
77
+ ## 🖥️ Command Line Interface (CLI) Usage
78
+
79
+ After installing, run `server_stats` (or its alias `server-stats`).
80
+
81
+ ### 1. Full System Overview (Default)
82
+ ```bash
83
+ server_stats
84
+ ```
85
+ **Example Output:**
86
+ ```text
87
+ ============================================================
88
+ SERVER STATS REPORT
89
+ ============================================================
90
+ OS: macOS 26.7.1 (arm64)
91
+ Hostname: Tams-MacBook-Pro-M3-Max.local
92
+ Uptime: 2h 49m 36s (Kernel: 25.6.0)
93
+ ------------------------------------------------------------
94
+ CPU Cores: 16 cores (Physical: 16)
95
+ CPU Model: Apple M3 Max
96
+ CPU Usage: 13.00%
97
+ Load Avg: 2.89 (1m), 3.35 (5m), 3.43 (15m)
98
+ ------------------------------------------------------------
99
+ RAM Total: 48.00 GB
100
+ RAM Used: 32.08 GB (66.83%)
101
+ RAM Available: 15.92 GB
102
+ RAM Free: 822.83 MB
103
+ ------------------------------------------------------------
104
+ Disk Total: 926.35 GB (Mount: /)
105
+ Disk Used: 11.78 GB (1.27%)
106
+ Disk Available: 50.84 GB
107
+ Filesystem: /dev/disk3s1s1
108
+ ============================================================
109
+ ```
110
+
111
+ ### 2. CPU Metrics Only
112
+ ```bash
113
+ server_stats --cpu
114
+ ```
115
+ **Example Output:**
116
+ ```text
117
+ CPU Cores: 16 (Physical: 16)
118
+ CPU Model: Apple M3 Max
119
+ CPU Usage: 14.00%
120
+ Load Average: 2.97 (1m), 3.33 (5m), 3.42 (15m)
121
+ ```
122
+
123
+ ### 3. Memory (RAM) Metrics Only
124
+ ```bash
125
+ server_stats --memory
126
+ ```
127
+ **Example Output:**
128
+ ```text
129
+ RAM Total: 48.00 GB
130
+ RAM Used: 32.42 GB (67.54%)
131
+ RAM Available: 15.58 GB
132
+ RAM Free: 509.45 MB
133
+ ```
134
+
135
+ Display raw bytes instead of human-readable units:
136
+ ```bash
137
+ server_stats --memory --raw
138
+ ```
139
+ ```text
140
+ RAM Total: 51539607552 bytes
141
+ RAM Used: 34326265856 bytes (66.60%)
142
+ RAM Available: 17213341696 bytes
143
+ RAM Free: 602013696 bytes
144
+ ```
145
+
146
+ ### 4. Disk Storage Metrics Only
147
+ Check root partition (`/`):
148
+ ```bash
149
+ server_stats --disk
150
+ ```
151
+ Check a specific mount point (e.g. `/data` or `/var`):
152
+ ```bash
153
+ server_stats --disk /data
154
+ ```
155
+ **Example Output:**
156
+ ```text
157
+ Mount Path: /data
158
+ Filesystem: /dev/sdb1
159
+ Disk Total: 500.00 GB
160
+ Disk Used: 120.50 GB (24.10%)
161
+ Disk Available: 379.50 GB
162
+ Disk Free: 379.50 GB
163
+ ```
164
+
165
+ ### 5. Operating System & System Info Only
166
+ ```bash
167
+ server_stats --system
168
+ ```
169
+ **Example Output:**
170
+ ```text
171
+ OS: macOS 26.7.1
172
+ Hostname: Tams-MacBook-Pro-M3-Max.local
173
+ Architecture: arm64
174
+ Kernel: 25.6.0
175
+ Uptime: 2h 50m 3s (10203s)
176
+ ```
177
+
178
+ ### 6. JSON Output (Ideal for Prometheus, Datadog, Zabbix, or CI/CD pipelines)
179
+ Output formatted JSON:
180
+ ```bash
181
+ server_stats --json
182
+ ```
183
+ **Example JSON Output:**
184
+ ```json
185
+ {
186
+ "timestamp": "2026-10-05T18:06:48Z",
187
+ "system": {
188
+ "os": "macOS",
189
+ "os_family": "macos",
190
+ "os_version": "26.7.1",
191
+ "hostname": "Tams-MacBook-Pro-M3-Max.local",
192
+ "architecture": "arm64",
193
+ "kernel": "25.6.0",
194
+ "uptime_seconds": 10196,
195
+ "uptime_human": "2h 49m 56s"
196
+ },
197
+ "cpu": {
198
+ "cores": 16,
199
+ "physical_cores": 16,
200
+ "usage_percent": 14.0,
201
+ "load_average": {
202
+ "one_minute": 3.14,
203
+ "five_minutes": 3.37,
204
+ "fifteen_minutes": 3.43
205
+ },
206
+ "model": "Apple M3 Max"
207
+ },
208
+ "memory": {
209
+ "total_bytes": 51539607552,
210
+ "free_bytes": 638238720,
211
+ "available_bytes": 17006346240,
212
+ "used_bytes": 34533261312,
213
+ "usage_percent": 67.0,
214
+ "total_human": "48.00 GB",
215
+ "free_human": "608.67 MB",
216
+ "available_human": "15.84 GB",
217
+ "used_human": "32.16 GB",
218
+ "details": {
219
+ "page_size_bytes": 16384,
220
+ "active_bytes": 16198729728,
221
+ "inactive_bytes": 16148070400,
222
+ "wired_bytes": 4961730560,
223
+ "purgeable_bytes": 220037120,
224
+ "compressed_bytes": 12622397440
225
+ }
226
+ },
227
+ "disk": {
228
+ "path": "/",
229
+ "filesystem": "/dev/disk3s1s1",
230
+ "total_bytes": 994662584320,
231
+ "used_bytes": 12647350272,
232
+ "free_bytes": 54586494976,
233
+ "available_bytes": 54586494976,
234
+ "usage_percent": 1.27,
235
+ "total_human": "926.35 GB",
236
+ "used_human": "11.78 GB",
237
+ "free_human": "50.84 GB",
238
+ "available_human": "50.84 GB"
239
+ }
240
+ }
241
+ ```
242
+
243
+ Filter specific components with JSON output:
244
+ ```bash
245
+ server_stats --cpu --json
246
+ server_stats --memory --json
247
+ server_stats --disk /data --json
248
+ ```
249
+
250
+ Output single-line compact JSON:
251
+ ```bash
252
+ server_stats --json --compact
253
+ ```
254
+
255
+ ### 7. Custom CPU Sampling Interval
256
+ Sample CPU over 1.0 second for higher accuracy:
257
+ ```bash
258
+ server_stats --cpu --interval 1.0
259
+ ```
260
+
261
+ ### 8. CLI Options Reference
262
+
263
+ | Flag | Short | Description | Default |
264
+ |---|---|---|---|
265
+ | `--all` | `-a` | Display all server statistics | Default |
266
+ | `--cpu` | `-c` | Show CPU metrics only | - |
267
+ | `--memory`, `--ram` | `-m` | Show RAM/memory metrics only | - |
268
+ | `--disk [PATH]` | `-d` | Show disk storage metrics for path | `/` |
269
+ | `--system` | `-s` | Show operating system & hardware info | - |
270
+ | `--json` | `-j` | Format output as JSON | `false` |
271
+ | `--compact` | | Format JSON as a single line (when used with `-j`) | `false` |
272
+ | `--raw` | `-r` | Show raw byte numbers instead of human-readable units | `false` |
273
+ | `--interval SEC` | `-i` | CPU sampling interval in seconds | `0.5` |
274
+ | `--version` | `-v` | Display version | - |
275
+ | `--help` | `-h` | Display help banner | - |
276
+
277
+ ---
278
+
279
+ ## 🛠️ Ruby Application Integration (Ruby API)
280
+
281
+ ### 1. Basic Usage
282
+ ```ruby
283
+ require 'server_stats'
284
+
285
+ # 1. CPU Metrics
286
+ cpu = ServerStats.cpu
287
+ puts "CPU Cores: #{cpu.cores} (Physical: #{cpu.physical_cores})"
288
+ puts "CPU Usage: #{cpu.usage_percent}%"
289
+ puts "Load (1m): #{cpu.load_average[:one_minute]}"
290
+
291
+ # 2. RAM / Memory Metrics
292
+ mem = ServerStats.memory # or ServerStats.ram
293
+ puts "RAM Total: #{mem.total_human} (#{mem.total_bytes} bytes)"
294
+ puts "RAM Available: #{mem.available_human}"
295
+ puts "RAM Free: #{mem.free_human}"
296
+ puts "RAM Used: #{mem.used_human} (#{mem.usage_percent}%)"
297
+
298
+ # 3. Disk Storage Metrics
299
+ disk = ServerStats.disk('/') # or custom mount: ServerStats.disk('/mnt/data')
300
+ puts "Disk Total: #{disk.total_human}"
301
+ puts "Disk Available: #{disk.available_human}"
302
+ puts "Disk Used: #{disk.used_human} (#{disk.usage_percent}%)"
303
+
304
+ # 4. OS & Hardware Info
305
+ sys = ServerStats.system
306
+ puts "OS: #{sys.os} #{sys.os_version} (#{sys.architecture})"
307
+ puts "Hostname: #{sys.hostname}"
308
+ puts "Uptime: #{sys.uptime_human}"
309
+ ```
310
+
311
+ ### 2. Hash and JSON Serialization
312
+ ```ruby
313
+ require 'server_stats'
314
+
315
+ # Convert entire snapshot into a Ruby Hash
316
+ stats_hash = ServerStats.to_h
317
+
318
+ # Export as a JSON string
319
+ json_data = ServerStats.to_json
320
+
321
+ # Pretty-printed JSON string
322
+ pretty_json = ServerStats.to_json(pretty: true)
323
+
324
+ # Formatted ASCII summary table
325
+ puts ServerStats.summary
326
+ ```
327
+
328
+ ### 3. Example: Rails Health-Check Endpoint
329
+ ```ruby
330
+ # app/controllers/health_controller.rb
331
+ class HealthController < ApplicationController
332
+ def show
333
+ stats = ServerStats.all
334
+
335
+ # Return HTTP 503 if RAM or Disk usage exceeds 90%
336
+ status = if stats.memory.usage_percent > 90.0 || stats.disk.usage_percent > 90.0
337
+ :service_unavailable
338
+ else
339
+ :ok
340
+ end
341
+
342
+ render json: {
343
+ status: status == :ok ? "healthy" : "warning",
344
+ stats: stats.to_h
345
+ }, status: status
346
+ end
347
+ end
348
+ ```
349
+
350
+ ### 4. Example: Resource Alerting Script (Slack / Telegram / Discord)
351
+ ```ruby
352
+ require 'server_stats'
353
+ require 'net/http'
354
+ require 'json'
355
+
356
+ cpu = ServerStats.cpu(interval: 1.0)
357
+ mem = ServerStats.memory
358
+ disk = ServerStats.disk('/')
359
+
360
+ if cpu.usage_percent > 85.0 || mem.usage_percent > 85.0
361
+ message = <<~MSG
362
+ ⚠️ SERVER RESOURCE ALERT: #{ServerStats.system.hostname}
363
+ - CPU: #{cpu.usage_percent}% (#{cpu.cores} cores)
364
+ - RAM: #{mem.used_human} / #{mem.total_human} (#{mem.usage_percent}%)
365
+ - Disk: #{disk.used_human} / #{disk.total_human} (#{disk.usage_percent}%)
366
+ MSG
367
+ puts message
368
+ # Send webhook request to Slack / Telegram / Discord here...
369
+ end
370
+ ```
371
+
372
+ ---
373
+
374
+ ## 🔬 Technical Data Collection Mechanisms
375
+
376
+ | Component | Ubuntu / Linux | macOS |
377
+ |---|---|---|
378
+ | **RAM Total & Free** | Reads `/proc/meminfo` directly (`MemTotal`, `MemAvailable`, `MemFree`, `Buffers`, `Cached`). | `sysctl -n hw.memsize` combined with page calculation from `vm_stat` (`Pages free`, `inactive`, `speculative`, `purgeable`). |
379
+ | **CPU Cores** | `Etc.nprocessors` combined with `/proc/cpuinfo` for physical cores. | `sysctl -n hw.ncpu` and `sysctl -n hw.physicalcpu`. |
380
+ | **CPU Usage %** | Two consecutive samples from `/proc/stat` calculating `delta_idle` and `delta_total`. Zero subprocesses required. | Sampled using `iostat -c 2` (or snapshot `top`), reliable within sandbox. |
381
+ | **Disk Space** | POSIX standard: `df -P -k <path>`, parses 1024-byte blocks precisely. | POSIX standard: `df -P -k <path>`. |
382
+ | **Uptime** | Reads directly from `/proc/uptime`. | Computed from boot timestamp via `sysctl -n kern.boottime`. |
383
+ | **OS Info** | Parsed from standard `/etc/os-release`. | Gathered via `sw_vers` and `uname`. |
384
+
385
+ ---
386
+
387
+ ## 🧪 Running Tests
388
+
389
+ The test suite is completely standalone and requires no external testing gems:
390
+
391
+ ```bash
392
+ # Run test suite directly
393
+ ruby test/run_all.rb
394
+ ```
395
+
396
+ Or via Rake:
397
+ ```bash
398
+ rake test
399
+ ```
400
+
401
+ ---
402
+
403
+ ## 📄 License
404
+
405
+ Distributed under the [MIT License](LICENSE).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks" if defined?(Bundler)
4
+
5
+ task default: :test
6
+
7
+ desc "Run the test suite"
8
+ task :test do
9
+ ruby "test/run_all.rb"
10
+ end
data/bin/server-stats ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "server_stats"
data/bin/server_stats ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ lib = File.expand_path("../lib", __dir__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+
7
+ require "server_stats/cli"
8
+
9
+ ServerStats::CLI.start(ARGV)
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "optparse"
4
+ require "json"
5
+ require_relative "../server_stats"
6
+
7
+ module ServerStats
8
+ class CLI
9
+ def self.start(args = ARGV)
10
+ new(args).run
11
+ end
12
+
13
+ def initialize(args = ARGV)
14
+ @args = args.dup
15
+ @options = {
16
+ mode: :all,
17
+ format: :text,
18
+ disk_path: "/",
19
+ interval: 0.5,
20
+ raw: false,
21
+ pretty: true
22
+ }
23
+ end
24
+
25
+ def parse_options
26
+ opt_parser = OptionParser.new do |opts|
27
+ opts.banner = "Cách dùng: server_stats [tuỳ chọn]"
28
+ opts.separator ""
29
+ opts.separator "Tuỳ chọn hiển thị:"
30
+
31
+ opts.on("-a", "--all", "Hiển thị đầy đủ thông số hệ thống (mặc định)") do
32
+ @options[:mode] = :all
33
+ end
34
+
35
+ opts.on("-c", "--cpu", "Chỉ hiển thị thông số CPU") do
36
+ @options[:mode] = :cpu
37
+ end
38
+
39
+ opts.on("-m", "--memory", "--ram", "Chỉ hiển thị thông số RAM") do
40
+ @options[:mode] = :memory
41
+ end
42
+
43
+ opts.on("-d", "--disk [PATH]", "Chỉ hiển thị thông số ổ cứng (mặc định: /)") do |path|
44
+ @options[:mode] = :disk
45
+ @options[:disk_path] = path if path && !path.empty?
46
+ end
47
+
48
+ opts.on("-s", "--system", "Chỉ hiển thị thông tin hệ điều hành và phần cứng") do
49
+ @options[:mode] = :system
50
+ end
51
+
52
+ opts.separator ""
53
+ opts.separator "Tuỳ chọn định dạng:"
54
+
55
+ opts.on("-j", "--json", "Xuất dữ liệu ở định dạng JSON") do
56
+ @options[:format] = :json
57
+ end
58
+
59
+ opts.on("--compact", "Xuất JSON trên 1 dòng (khi dùng với -j)") do
60
+ @options[:pretty] = false
61
+ end
62
+
63
+ opts.on("-r", "--raw", "Hiển thị dung lượng dạng byte thô thay vì đơn vị đọc được (GB/MB)") do
64
+ @options[:raw] = true
65
+ end
66
+
67
+ opts.on("-i", "--interval SECONDS", Float, "Thời gian lấy mẫu CPU tính bằng giây (mặc định: 0.5)") do |sec|
68
+ @options[:interval] = [sec.to_f, 0.1].max
69
+ end
70
+
71
+ opts.separator ""
72
+ opts.separator "Thông tin chung:"
73
+
74
+ opts.on("-v", "--version", "Hiển thị phiên bản gem") do
75
+ puts "server_stats version #{ServerStats::VERSION}"
76
+ exit 0
77
+ end
78
+
79
+ opts.on("-h", "--help", "Hiển thị hướng dẫn sử dụng") do
80
+ puts opts
81
+ exit 0
82
+ end
83
+ end
84
+
85
+ opt_parser.parse!(@args)
86
+ # If extra non-option argument given, treat as disk path if disk mode was selected
87
+ @options[:disk_path] = @args.first if @options[:mode] == :disk && @args.first
88
+ @options
89
+ end
90
+
91
+ def run
92
+ parse_options
93
+ execute_command
94
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
95
+ warn "Lỗi cú pháp: #{e.message}"
96
+ warn "Chạy 'server_stats --help' để xem danh sách tuỳ chọn."
97
+ exit 1
98
+ rescue StandardError => e
99
+ warn "Lỗi khi lấy thông số: #{e.message}"
100
+ exit 1
101
+ end
102
+
103
+ def execute_command
104
+ case @options[:format]
105
+ when :json
106
+ output_json
107
+ else
108
+ output_text
109
+ end
110
+ end
111
+
112
+ private
113
+
114
+ def output_json
115
+ data = case @options[:mode]
116
+ when :cpu
117
+ ServerStats.cpu(interval: @options[:interval]).to_h
118
+ when :memory
119
+ ServerStats.memory.to_h
120
+ when :disk
121
+ ServerStats.disk(path: @options[:disk_path]).to_h
122
+ when :system
123
+ ServerStats.system.to_h
124
+ else
125
+ ServerStats.to_h(path: @options[:disk_path], interval: @options[:interval])
126
+ end
127
+
128
+ puts @options[:pretty] ? JSON.pretty_generate(data) : data.to_json
129
+ end
130
+
131
+ def output_text
132
+ case @options[:mode]
133
+ when :cpu
134
+ print_cpu(ServerStats.cpu(interval: @options[:interval]))
135
+ when :memory
136
+ print_memory(ServerStats.memory)
137
+ when :disk
138
+ print_disk(ServerStats.disk(path: @options[:disk_path]))
139
+ when :system
140
+ print_system(ServerStats.system)
141
+ else
142
+ puts ServerStats.summary(path: @options[:disk_path], interval: @options[:interval])
143
+ end
144
+ end
145
+
146
+ def print_cpu(cpu)
147
+ puts "CPU Cores: #{cpu.cores} (Physical: #{cpu.physical_cores})"
148
+ puts "CPU Model: #{cpu.model || 'Unknown'}" if cpu.model
149
+ puts "CPU Usage: #{Formatter.format_percent(cpu.usage_percent)}"
150
+ if cpu.load_average.any?
151
+ puts "Load Average: #{cpu.load_average[:one_minute]} (1m), #{cpu.load_average[:five_minutes]} (5m), #{cpu.load_average[:fifteen_minutes]} (15m)"
152
+ end
153
+ end
154
+
155
+ def print_memory(mem)
156
+ if @options[:raw]
157
+ puts "RAM Total: #{mem.total_bytes} bytes"
158
+ puts "RAM Used: #{mem.used_bytes} bytes (#{Formatter.format_percent(mem.usage_percent)})"
159
+ puts "RAM Available: #{mem.available_bytes} bytes"
160
+ puts "RAM Free: #{mem.free_bytes} bytes"
161
+ else
162
+ puts "RAM Total: #{mem.total_human}"
163
+ puts "RAM Used: #{mem.used_human} (#{Formatter.format_percent(mem.usage_percent)})"
164
+ puts "RAM Available: #{mem.available_human}"
165
+ puts "RAM Free: #{mem.free_human}"
166
+ end
167
+ end
168
+
169
+ def print_disk(disk)
170
+ puts "Mount Path: #{disk.path}"
171
+ puts "Filesystem: #{disk.filesystem}"
172
+ if @options[:raw]
173
+ puts "Disk Total: #{disk.total_bytes} bytes"
174
+ puts "Disk Used: #{disk.used_bytes} bytes (#{Formatter.format_percent(disk.usage_percent)})"
175
+ puts "Disk Available: #{disk.available_bytes} bytes"
176
+ puts "Disk Free: #{disk.free_bytes} bytes"
177
+ else
178
+ puts "Disk Total: #{disk.total_human}"
179
+ puts "Disk Used: #{disk.used_human} (#{Formatter.format_percent(disk.usage_percent)})"
180
+ puts "Disk Available: #{disk.available_human}"
181
+ puts "Disk Free: #{disk.free_human}"
182
+ end
183
+ end
184
+
185
+ def print_system(sys)
186
+ puts "OS: #{sys.os} #{sys.os_version}"
187
+ puts "Hostname: #{sys.hostname}"
188
+ puts "Architecture: #{sys.architecture}"
189
+ puts "Kernel: #{sys.kernel}"
190
+ puts "Uptime: #{sys.uptime_human} (#{sys.uptime_seconds}s)"
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "os"
4
+ require_relative "models"
5
+ require_relative "providers/base"
6
+ require_relative "providers/linux"
7
+ require_relative "providers/macos"
8
+
9
+ module ServerStats
10
+ class Collector
11
+ attr_accessor :provider
12
+
13
+ def initialize(provider: nil)
14
+ @provider = provider || default_provider
15
+ end
16
+
17
+ def cpu(interval: 0.5)
18
+ @provider.cpu(interval)
19
+ end
20
+
21
+ def memory
22
+ @provider.memory
23
+ end
24
+
25
+ alias ram memory
26
+
27
+ def disk(path = "/")
28
+ path = path[:path] if path.is_a?(Hash) && path.key?(:path)
29
+ @provider.disk(path)
30
+ end
31
+
32
+ def system
33
+ @provider.system
34
+ end
35
+
36
+ def snapshot(path: "/", interval: 0.5)
37
+ Snapshot.new(
38
+ cpu: cpu(interval: interval),
39
+ memory: memory,
40
+ disk: disk(path: path),
41
+ system: system
42
+ )
43
+ end
44
+
45
+ alias all snapshot
46
+
47
+ private
48
+
49
+ def default_provider
50
+ case OS.type
51
+ when :macos
52
+ Providers::MacOs.new
53
+ when :linux
54
+ Providers::Linux.new
55
+ else
56
+ # Fallback to Linux-like or base provider
57
+ File.exist?("/proc/meminfo") ? Providers::Linux.new : Providers::Base.new
58
+ end
59
+ end
60
+ end
61
+ end