Compare commits

..

2 Commits

Author SHA1 Message Date
Vitaliy Filippov 2e592a2f22 Fix undefined variable "timeout"
Test / test_snapshot_ec (push) Successful in 44s Details
Test / test_rm (push) Successful in 17s Details
Test / test_interrupted_rebalance_ec_imm (push) Successful in 2m9s Details
Test / test_snapshot_down (push) Successful in 23s Details
Test / test_move_reappear (push) Failing after 51s Details
Test / test_snapshot_down_ec (push) Successful in 25s Details
Test / test_splitbrain (push) Successful in 24s Details
Test / test_snapshot_chain (push) Successful in 2m26s Details
Test / test_snapshot_chain_ec (push) Failing after 3m6s Details
Test / test_rebalance_verify_imm (push) Successful in 3m2s Details
Test / test_write (push) Successful in 35s Details
Test / test_rebalance_verify (push) Successful in 3m56s Details
Test / test_write_no_same (push) Successful in 12s Details
Test / test_write_xor (push) Successful in 38s Details
Test / test_rebalance_verify_ec (push) Successful in 5m2s Details
Test / test_rebalance_verify_ec_imm (push) Successful in 4m13s Details
Test / test_heal_pg_size_2 (push) Successful in 4m17s Details
Test / test_heal_ec (push) Successful in 5m2s Details
Test / test_heal_csum_32k_dmj (push) Successful in 5m43s Details
Test / test_heal_csum_32k_dj (push) Successful in 5m36s Details
Test / test_heal_csum_32k (push) Successful in 7m4s Details
Test / test_heal_csum_4k_dmj (push) Successful in 6m47s Details
Test / test_scrub (push) Successful in 1m11s Details
Test / test_scrub_zero_osd_2 (push) Successful in 59s Details
Test / test_scrub_pg_size_3 (push) Successful in 1m26s Details
Test / test_heal_csum_4k_dj (push) Successful in 6m32s Details
Test / test_heal_csum_4k (push) Successful in 6m31s Details
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 27s Details
Test / test_scrub_ec (push) Successful in 25s Details
Test / test_scrub_xor (push) Failing after 3m7s Details
2023-10-29 01:30:55 +03:00
Vitaliy Filippov b92f644e3a Fix statistics aggregation, calculate inode stats by first deriving per-OSD stats, too 2023-10-29 01:30:55 +03:00
1 changed files with 68 additions and 37 deletions

View File

@ -397,8 +397,8 @@ class Mon
this.etcd_prefix = this.etcd_prefix.replace(/\/\/+/g, '/').replace(/^\/?(.*[^\/])\/?$/, '/$1'); this.etcd_prefix = this.etcd_prefix.replace(/\/\/+/g, '/').replace(/^\/?(.*[^\/])\/?$/, '/$1');
this.etcd_start_timeout = (config.etcd_start_timeout || 5) * 1000; this.etcd_start_timeout = (config.etcd_start_timeout || 5) * 1000;
this.state = JSON.parse(JSON.stringify(this.constructor.etcd_tree)); this.state = JSON.parse(JSON.stringify(this.constructor.etcd_tree));
this.prev_stats = { osd_stats: {}, osd_diff: {} };
this.signals_set = false; this.signals_set = false;
this.stat_time = Date.now();
this.ws = null; this.ws = null;
this.ws_alive = false; this.ws_alive = false;
this.ws_keepalive_timer = null; this.ws_keepalive_timer = null;
@ -552,9 +552,9 @@ class Mon
const cur_addr = this.pick_next_etcd(); const cur_addr = this.pick_next_etcd();
const base = 'ws'+cur_addr.substr(4); const base = 'ws'+cur_addr.substr(4);
let now = Date.now(); let now = Date.now();
if (tried[base] && now-tried[base] < timeout) if (tried[base] && now-tried[base] < this.etcd_start_timeout)
{ {
await new Promise(ok => setTimeout(ok, timeout-(now-tried[base]))); await new Promise(ok => setTimeout(ok, this.etcd_start_timeout-(now-tried[base])));
now = Date.now(); now = Date.now();
} }
tried[base] = now; tried[base] = now;
@ -1459,15 +1459,15 @@ class Mon
} }
} }
derive_osd_stats(st, prev) derive_osd_stats(st, prev, prev_diff)
{ {
const zero_stats = { op: { bps: 0n, iops: 0n, lat: 0n }, subop: { iops: 0n, lat: 0n }, recovery: { bps: 0n, iops: 0n } }; const zero_stats = { op: { bps: 0n, iops: 0n, lat: 0n }, subop: { iops: 0n, lat: 0n }, recovery: { bps: 0n, iops: 0n } };
const diff = { op_stats: {}, subop_stats: {}, recovery_stats: {} }; const diff = { op_stats: {}, subop_stats: {}, recovery_stats: {}, inode_stats: {} };
if (!st || !st.time || prev && (prev.time || this.stat_time/1000) >= st.time) if (!st || !st.time || !prev || prev.time >= st.time)
{ {
return diff; return prev_diff || diff;
} }
const timediff = BigInt(st.time*1000 - (prev && prev.time*1000 || this.stat_time)); const timediff = BigInt(st.time*1000 - prev.time*1000);
for (const op in st.op_stats||{}) for (const op in st.op_stats||{})
{ {
const pr = prev && prev.op_stats && prev.op_stats[op]; const pr = prev && prev.op_stats && prev.op_stats[op];
@ -1499,25 +1499,47 @@ class Mon
if (n > 0) if (n > 0)
diff.recovery_stats[op] = { ...c, bps: b*1000n/timediff, iops: n*1000n/timediff }; diff.recovery_stats[op] = { ...c, bps: b*1000n/timediff, iops: n*1000n/timediff };
} }
for (const pool_id in st.inode_stats||{})
{
const pool_diff = diff.inode_stats[pool_id] = {};
for (const inode_num in st.inode_stats[pool_id])
{
const inode_diff = diff.inode_stats[pool_id][inode_num] = {};
for (const op of [ 'read', 'write', 'delete' ])
{
const c = st.inode_stats[pool_id][inode_num][op];
const pr = prev && prev.inode_stats && prev.inode_stats[pool_id] &&
prev.inode_stats[pool_id][inode_num] && prev.inode_stats[pool_id][inode_num][op];
const n = BigInt(c.count||0) - BigInt(pr && pr.count||0);
inode_diff[op] = {
bps: (BigInt(c.bytes||0) - BigInt(pr && pr.bytes||0))*1000n/timediff,
iops: n*1000n/timediff,
lat: (BigInt(c.usec||0) - BigInt(pr && pr.usec||0))/(n || 1n),
};
}
}
}
return diff; return diff;
} }
sum_op_stats(timestamp, prev_stats) sum_op_stats()
{ {
const sum_diff = { op_stats: {}, subop_stats: {}, recovery_stats: {} }; for (const osd in this.state.osd.stats)
if (!prev_stats || prev_stats.timestamp >= timestamp)
{ {
return sum_diff; const cur = { ...this.state.osd.stats[osd], inode_stats: this.state.osd.inodestats[osd]||{} };
this.prev_stats.osd_diff[osd] = this.derive_osd_stats(
cur, this.prev_stats.osd_stats[osd], this.prev_stats.osd_diff[osd]
);
this.prev_stats.osd_stats[osd] = cur;
} }
const tm = BigInt(timestamp - (prev_stats.timestamp || 0)); const sum_diff = { op_stats: {}, subop_stats: {}, recovery_stats: {} };
// Sum derived values instead of deriving summed // Sum derived values instead of deriving summed
for (const osd in this.state.osd.stats) for (const osd in this.state.osd.stats)
{ {
const derived = this.derive_osd_stats(this.state.osd.stats[osd], const derived = this.prev_stats.osd_diff[osd];
this.prev_stats && this.prev_stats.osd_stats && this.prev_stats.osd_stats[osd]); for (const type in sum_diff)
for (const type in derived)
{ {
for (const op in derived[type]) for (const op in derived[type]||{})
{ {
for (const k in derived[type][op]) for (const k in derived[type][op])
{ {
@ -1574,14 +1596,14 @@ class Mon
return { object_counts, object_bytes }; return { object_counts, object_bytes };
} }
sum_inode_stats(prev_stats, timestamp, prev_timestamp) sum_inode_stats()
{ {
const inode_stats = {}; const inode_stats = {};
const inode_stub = () => ({ const inode_stub = () => ({
raw_used: 0n, raw_used: 0n,
read: { count: 0n, usec: 0n, bytes: 0n }, read: { count: 0n, usec: 0n, bytes: 0n, bps: 0n, iops: 0n, lat: 0n },
write: { count: 0n, usec: 0n, bytes: 0n }, write: { count: 0n, usec: 0n, bytes: 0n, bps: 0n, iops: 0n, lat: 0n },
delete: { count: 0n, usec: 0n, bytes: 0n }, delete: { count: 0n, usec: 0n, bytes: 0n, bps: 0n, iops: 0n, lat: 0n },
}); });
const seen_pools = {}; const seen_pools = {};
for (const pool_id in this.state.config.pools) for (const pool_id in this.state.config.pools)
@ -1633,11 +1655,25 @@ class Mon
} }
} }
} }
if (prev_stats && prev_timestamp >= timestamp) for (const osd in this.prev_stats.osd_diff)
{ {
prev_stats = null; for (const pool_id in this.prev_stats.osd_diff[osd].inode_stats)
{
for (const inode_num in this.prev_stats.osd_diff[osd].inode_stats[pool_id])
{
inode_stats[pool_id][inode_num] = inode_stats[pool_id][inode_num] || inode_stub();
for (const op of [ 'read', 'write', 'delete' ])
{
const op_diff = this.prev_stats.osd_diff[osd].inode_stats[pool_id][inode_num][op] || {};
const op_st = inode_stats[pool_id][inode_num][op];
op_st.bps += op_diff.bps;
op_st.iops += op_diff.iops;
op_st.lat += op_diff.lat;
op_st.n_osd = (op_st.n_osd || 0) + 1;
}
}
}
} }
const tm = prev_stats ? BigInt(timestamp - prev_timestamp) : 0;
for (const pool_id in inode_stats) for (const pool_id in inode_stats)
{ {
for (const inode_num in inode_stats[pool_id]) for (const inode_num in inode_stats[pool_id])
@ -1646,11 +1682,12 @@ class Mon
for (const op of [ 'read', 'write', 'delete' ]) for (const op of [ 'read', 'write', 'delete' ])
{ {
const op_st = inode_stats[pool_id][inode_num][op]; const op_st = inode_stats[pool_id][inode_num][op];
const prev_st = prev_stats && prev_stats[pool_id] && prev_stats[pool_id][inode_num] && prev_stats[pool_id][inode_num][op]; if (op_st.n_osd)
op_st.bps = prev_st ? (op_st.bytes - prev_st.bytes) * 1000n / tm : 0; {
op_st.iops = prev_st ? (op_st.count - prev_st.count) * 1000n / tm : 0; op_st.lat /= BigInt(op_st.n_osd);
op_st.lat = prev_st ? (op_st.usec - prev_st.usec) / ((op_st.count - prev_st.count) || 1n) : 0; delete op_st.n_osd;
if (op_st.bps > 0 || op_st.iops > 0 || op_st.lat > 0) }
if (op_st.bps > 0 || op_st.iops > 0)
nonzero = true; nonzero = true;
} }
if (!nonzero && (!this.state.config.inode[pool_id] || !this.state.config.inode[pool_id][inode_num])) if (!nonzero && (!this.state.config.inode[pool_id] || !this.state.config.inode[pool_id][inode_num]))
@ -1683,15 +1720,9 @@ class Mon
async update_total_stats() async update_total_stats()
{ {
const txn = []; const txn = [];
const timestamp = Date.now();
const { object_counts, object_bytes } = this.sum_object_counts(); const { object_counts, object_bytes } = this.sum_object_counts();
let stats = this.sum_op_stats(timestamp, this.prev_stats); let stats = this.sum_op_stats();
let { inode_stats, seen_pools } = this.sum_inode_stats( let { inode_stats, seen_pools } = this.sum_inode_stats();
this.prev_stats ? this.prev_stats.inode_stats : null,
timestamp, this.prev_stats ? this.prev_stats.timestamp : null
);
this.prev_stats = { timestamp, inode_stats, osd_stats: { ...this.state.osd.stats } };
this.stat_time = Date.now();
stats.object_counts = object_counts; stats.object_counts = object_counts;
stats.object_bytes = object_bytes; stats.object_bytes = object_bytes;
stats = this.serialize_bigints(stats); stats = this.serialize_bigints(stats);