Skip to content

Commit ecf9e56

Browse files
author
Swapnil Dinkar
committed
plugins/amzn: add stats support
this patch adds support to pull stats from amzn ebs nvme devices. Signed-off-by: Swapnil Dinkar <[email protected]>
1 parent 10e3119 commit ecf9e56

File tree

2 files changed

+209
-0
lines changed

2 files changed

+209
-0
lines changed

plugins/amzn/amzn-nvme.c

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,54 @@
1414
#define CREATE_CMD
1515
#include "amzn-nvme.h"
1616

17+
#define AMZN_NVME_STATS_LOGPAGE_ID 0xD0
18+
#define AMZN_NVME_STATS_MAGIC 0x3C23B510
19+
20+
#define array_add_obj json_array_add_value_object
21+
#define obj_add_array json_object_add_value_array
22+
#define obj_add_obj json_object_add_value_object
23+
#define obj_add_uint json_object_add_value_uint
24+
#define obj_add_uint64 json_object_add_value_uint64
25+
1726
struct nvme_vu_id_ctrl_field {
1827
__u8 bdev[32];
1928
__u8 reserved0[992];
2029
};
2130

31+
struct amzn_latency_histogram_bin {
32+
__u64 lower;
33+
__u64 upper;
34+
__u32 count;
35+
__u32 reserved;
36+
} __packed;
37+
38+
struct amzn_latency_histogram {
39+
__u64 num_bins;
40+
struct amzn_latency_histogram_bin bins[64];
41+
} __packed;
42+
43+
struct amzn_latency_log_page {
44+
__u32 magic;
45+
__u32 reserved0;
46+
__u64 total_read_ops;
47+
__u64 total_write_ops;
48+
__u64 total_read_bytes;
49+
__u64 total_write_bytes;
50+
__u64 total_read_time;
51+
__u64 total_write_time;
52+
__u64 ebs_volume_performance_exceeded_iops;
53+
__u64 ebs_volume_performance_exceeded_tp;
54+
__u64 ec2_instance_ebs_performance_exceeded_iops;
55+
__u64 ec2_instance_ebs_performance_exceeded_tp;
56+
__u64 volume_queue_length;
57+
__u8 reserved1[416];
58+
59+
struct amzn_latency_histogram read_io_latency_histogram;
60+
struct amzn_latency_histogram write_io_latency_histogram;
61+
62+
__u8 reserved2[496];
63+
} __packed;
64+
2265
static void json_amzn_id_ctrl(struct nvme_vu_id_ctrl_field *id,
2366
char *bdev,
2467
struct json_object *root)
@@ -52,3 +95,168 @@ static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *pl
5295
{
5396
return __id_ctrl(argc, argv, cmd, plugin, amzn_id_ctrl);
5497
}
98+
99+
static void amzn_print_latency_histogram(struct amzn_latency_histogram *hist)
100+
{
101+
printf("=================================\n");
102+
printf("Lower Upper IO Count\n");
103+
printf("=================================\n");
104+
105+
for (int b = 0; b < hist->num_bins && b < 64; b++) {
106+
struct amzn_latency_histogram_bin *bin = &hist->bins[b];
107+
108+
printf("[%-8llu - %-8llu] => %-8u\n",
109+
bin->lower, bin->upper, bin->count);
110+
}
111+
112+
printf("=================================\n\n");
113+
}
114+
115+
static void amzn_json_add_histogram(struct json_object *root,
116+
struct amzn_latency_histogram *hist)
117+
{
118+
struct json_object *bins = json_create_array();
119+
120+
obj_add_uint64(root, "num_bins", hist->num_bins);
121+
obj_add_array(root, "bins", bins);
122+
123+
for (int b = 0; b < hist->num_bins && b < 64; b++) {
124+
struct amzn_latency_histogram_bin *bin = &hist->bins[b];
125+
struct json_object *json_bin = json_create_object();
126+
127+
obj_add_uint64(json_bin, "lower", bin->lower);
128+
obj_add_uint64(json_bin, "upper", bin->upper);
129+
obj_add_uint(json_bin, "count", bin->count);
130+
131+
array_add_obj(bins, json_bin);
132+
}
133+
}
134+
135+
static void amzn_print_json_stats(struct amzn_latency_log_page *log)
136+
{
137+
struct json_object *root = json_create_object();
138+
struct json_object *r_hist = json_create_object();
139+
struct json_object *w_hist = json_create_object();
140+
141+
obj_add_uint64(root, "total_read_ops", log->total_read_ops);
142+
obj_add_uint64(root, "total_write_ops", log->total_write_ops);
143+
obj_add_uint64(root, "total_read_bytes", log->total_read_bytes);
144+
obj_add_uint64(root, "total_write_bytes", log->total_write_bytes);
145+
obj_add_uint64(root, "total_read_time", log->total_read_time);
146+
obj_add_uint64(root, "total_write_time", log->total_write_time);
147+
obj_add_uint64(root, "ebs_volume_performance_exceeded_iops",
148+
log->ebs_volume_performance_exceeded_iops);
149+
obj_add_uint64(root, "ebs_volume_performance_exceeded_tp",
150+
log->ebs_volume_performance_exceeded_tp);
151+
obj_add_uint64(root,
152+
"ec2_instance_ebs_performance_exceeded_iops",
153+
log->ec2_instance_ebs_performance_exceeded_iops);
154+
obj_add_uint64(root, "ec2_instance_ebs_performance_exceeded_tp",
155+
log->ec2_instance_ebs_performance_exceeded_tp);
156+
obj_add_uint64(root, "volume_queue_length", log->volume_queue_length);
157+
158+
amzn_json_add_histogram(r_hist, &log->read_io_latency_histogram);
159+
obj_add_obj(root, "read_io_latency_histogram", r_hist);
160+
amzn_json_add_histogram(w_hist, &log->write_io_latency_histogram);
161+
obj_add_obj(root, "write_io_latency_histogram", w_hist);
162+
163+
json_print_object(root, NULL);
164+
printf("\n");
165+
166+
json_free_object(root);
167+
}
168+
169+
static void amzn_print_normal_stats(struct amzn_latency_log_page *log)
170+
{
171+
printf("Total Ops:\n");
172+
printf(" Read: %llu\n", log->total_read_ops);
173+
printf(" Write: %llu\n", log->total_write_ops);
174+
printf("Total Bytes:\n");
175+
printf(" Read: %llu\n", log->total_read_bytes);
176+
printf(" Write: %llu\n", log->total_write_bytes);
177+
printf("Total Time (us):\n");
178+
printf(" Read: %llu\n", log->total_read_time);
179+
printf(" Write: %llu\n\n", log->total_write_time);
180+
181+
printf("EBS Volume Performance Exceeded (us):\n");
182+
printf(" IOPS: %llu\n", log->ebs_volume_performance_exceeded_iops);
183+
printf(" Throughput: %llu\n\n",
184+
log->ebs_volume_performance_exceeded_tp);
185+
printf("EC2 Instance EBS Performance Exceeded (us):\n");
186+
printf(" IOPS: %llu\n",
187+
log->ec2_instance_ebs_performance_exceeded_iops);
188+
printf(" Throughput: %llu\n\n",
189+
log->ec2_instance_ebs_performance_exceeded_tp);
190+
191+
printf("Queue Length (point in time): %llu\n\n",
192+
log->volume_queue_length);
193+
194+
printf("Read IO Latency Histogram\n");
195+
amzn_print_latency_histogram(&log->read_io_latency_histogram);
196+
197+
printf("Write IO Latency Histogram\n");
198+
amzn_print_latency_histogram(&log->write_io_latency_histogram);
199+
}
200+
201+
static int get_stats(int argc, char **argv, struct command *cmd,
202+
struct plugin *plugin)
203+
{
204+
const char *desc = "display command latency statistics";
205+
struct nvme_dev *dev;
206+
struct amzn_latency_log_page log = { 0 };
207+
int rc;
208+
209+
struct config {
210+
char *output_format;
211+
};
212+
213+
struct config cfg = {
214+
.output_format = "normal",
215+
};
216+
217+
OPT_ARGS(opts) = {
218+
OPT_FMT("output-format", 'o', &cfg.output_format,
219+
"Output Format: normal|json"),
220+
OPT_END()};
221+
222+
rc = parse_and_open(&dev, argc, argv, desc, opts);
223+
if (rc)
224+
return rc;
225+
226+
struct nvme_get_log_args args = {
227+
.args_size = sizeof(args),
228+
.fd = dev_fd(dev),
229+
.lid = AMZN_NVME_STATS_LOGPAGE_ID,
230+
.nsid = 1,
231+
.lpo = 0,
232+
.lsp = NVME_LOG_LSP_NONE,
233+
.lsi = 0,
234+
.rae = false,
235+
.uuidx = 0,
236+
.csi = NVME_CSI_NVM,
237+
.ot = false,
238+
.len = sizeof(log),
239+
.log = &log,
240+
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
241+
.result = NULL,
242+
};
243+
244+
rc = nvme_get_log(&args);
245+
if (rc != 0) {
246+
fprintf(stderr, "[ERROR] %s: Failed to get log page, rc = %d",
247+
__func__, rc);
248+
return rc;
249+
}
250+
251+
if (log.magic != AMZN_NVME_STATS_MAGIC) {
252+
fprintf(stderr, "[ERROR] %s: Not an EBS device", __func__);
253+
return -ENOTSUP;
254+
}
255+
256+
if (!strcmp(cfg.output_format, "json"))
257+
amzn_print_json_stats(&log);
258+
else
259+
amzn_print_normal_stats(&log);
260+
261+
return 0;
262+
}

plugins/amzn/amzn-nvme.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
PLUGIN(NAME("amzn", "Amazon vendor specific extensions", NVME_VERSION),
1111
COMMAND_LIST(
1212
ENTRY("id-ctrl", "Send NVMe Identify Controller", id_ctrl)
13+
ENTRY("stats", "Get EBS volume stats", get_stats)
1314
)
1415
);
1516

0 commit comments

Comments
 (0)