rpc: Add thread_get_stats RPC method
SPDK threads collect busy and idle time statistics. This commit adds thread_get_stats RPC method to retrieve these values. Signed-off-by: Evgeniy Kochetov <evgeniik@mellanox.com> Change-Id: I8ed8041c6164eb0c0a9336f4e50b5f26a3f20190 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/445285 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Seth Howell <seth.howell5141@gmail.com> Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Paul Luse <paul.e.luse@intel.com>
This commit is contained in:
parent
750a4213ef
commit
7535cdbd62
@ -95,6 +95,10 @@ sock groups. This API is intended to provide the user with that information.
|
|||||||
spdk_sock_group_get_ctx() was added to return the context of the spdk_sock_group.
|
spdk_sock_group_get_ctx() was added to return the context of the spdk_sock_group.
|
||||||
spdk_sock_group_create() is updated to allow input the user provided ctx.
|
spdk_sock_group_create() is updated to allow input the user provided ctx.
|
||||||
|
|
||||||
|
### rpc
|
||||||
|
|
||||||
|
Added thread_get_stats RPC method to retrieve existing statistics.
|
||||||
|
|
||||||
## v19.04:
|
## v19.04:
|
||||||
|
|
||||||
### nvme
|
### nvme
|
||||||
|
@ -484,6 +484,47 @@ Example response:
|
|||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
## thread_get_stats {#rpc_thread_get_stats}
|
||||||
|
|
||||||
|
Retrieve current statistics of all the threads.
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
This method has no parameters.
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
The response is an array of objects containing threads statistics.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
Example request:
|
||||||
|
~~~
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "thread_get_stats",
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Example response:
|
||||||
|
~~~
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": 1,
|
||||||
|
"result": {
|
||||||
|
"tick_rate": 2400000000,
|
||||||
|
"threads": [
|
||||||
|
{
|
||||||
|
"name": "reactor_0",
|
||||||
|
"busy": 139223208,
|
||||||
|
"idle": 8641080608
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~~~
|
||||||
|
|
||||||
# Block Device Abstraction Layer {#jsonrpc_components_bdev}
|
# Block Device Abstraction Layer {#jsonrpc_components_bdev}
|
||||||
|
|
||||||
## set_bdev_options {#rpc_set_bdev_options}
|
## set_bdev_options {#rpc_set_bdev_options}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/*-
|
/*-
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
*
|
*
|
||||||
* Copyright (c) Intel Corporation.
|
* Copyright (c) Intel Corporation. All rights reserved.
|
||||||
* All rights reserved.
|
* Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -37,6 +37,8 @@
|
|||||||
#include "spdk/rpc.h"
|
#include "spdk/rpc.h"
|
||||||
#include "spdk/string.h"
|
#include "spdk/string.h"
|
||||||
#include "spdk/util.h"
|
#include "spdk/util.h"
|
||||||
|
#include "spdk/env.h"
|
||||||
|
#include "spdk/thread.h"
|
||||||
|
|
||||||
#include "spdk_internal/log.h"
|
#include "spdk_internal/log.h"
|
||||||
|
|
||||||
@ -153,3 +155,69 @@ spdk_rpc_context_switch_monitor(struct spdk_jsonrpc_request *request,
|
|||||||
}
|
}
|
||||||
|
|
||||||
SPDK_RPC_REGISTER("context_switch_monitor", spdk_rpc_context_switch_monitor, SPDK_RPC_RUNTIME)
|
SPDK_RPC_REGISTER("context_switch_monitor", spdk_rpc_context_switch_monitor, SPDK_RPC_RUNTIME)
|
||||||
|
|
||||||
|
struct rpc_thread_get_stats_ctx {
|
||||||
|
struct spdk_jsonrpc_request *request;
|
||||||
|
struct spdk_json_write_ctx *w;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
rpc_thread_get_stats_done(void *arg)
|
||||||
|
{
|
||||||
|
struct rpc_thread_get_stats_ctx *ctx = arg;
|
||||||
|
|
||||||
|
spdk_json_write_array_end(ctx->w);
|
||||||
|
spdk_json_write_object_end(ctx->w);
|
||||||
|
spdk_jsonrpc_end_result(ctx->request, ctx->w);
|
||||||
|
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rpc_thread_get_stats(void *arg)
|
||||||
|
{
|
||||||
|
struct rpc_thread_get_stats_ctx *ctx = arg;
|
||||||
|
struct spdk_thread_stats stats;
|
||||||
|
|
||||||
|
if (0 == spdk_thread_get_stats(&stats)) {
|
||||||
|
spdk_json_write_object_begin(ctx->w);
|
||||||
|
spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(spdk_get_thread()));
|
||||||
|
spdk_json_write_named_uint64(ctx->w, "busy", stats.busy_tsc);
|
||||||
|
spdk_json_write_named_uint64(ctx->w, "idle", stats.idle_tsc);
|
||||||
|
spdk_json_write_object_end(ctx->w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
spdk_rpc_thread_get_stats(struct spdk_jsonrpc_request *request,
|
||||||
|
const struct spdk_json_val *params)
|
||||||
|
{
|
||||||
|
struct rpc_thread_get_stats_ctx *ctx;
|
||||||
|
|
||||||
|
if (params) {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||||
|
"'thread_get_stats' requires no arguments");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
|
if (!ctx) {
|
||||||
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||||
|
"Memory allocation error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx->request = request;
|
||||||
|
|
||||||
|
ctx->w = spdk_jsonrpc_begin_result(ctx->request);
|
||||||
|
if (NULL == ctx->w) {
|
||||||
|
free(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spdk_json_write_object_begin(ctx->w);
|
||||||
|
spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
|
||||||
|
spdk_json_write_named_array_begin(ctx->w, "threads");
|
||||||
|
|
||||||
|
spdk_for_each_thread(rpc_thread_get_stats, ctx, rpc_thread_get_stats_done);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPDK_RPC_REGISTER("thread_get_stats", spdk_rpc_thread_get_stats, SPDK_RPC_RUNTIME)
|
||||||
|
@ -1813,6 +1813,13 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
|||||||
p.add_argument('-n', '--max', help="""Maximum number of notifications to return in response""", type=int)
|
p.add_argument('-n', '--max', help="""Maximum number of notifications to return in response""", type=int)
|
||||||
p.set_defaults(func=get_notifications)
|
p.set_defaults(func=get_notifications)
|
||||||
|
|
||||||
|
def thread_get_stats(args):
|
||||||
|
print_dict(rpc.app.thread_get_stats(args.client))
|
||||||
|
|
||||||
|
p = subparsers.add_parser(
|
||||||
|
'thread_get_stats', help='Display current statistics of all the threads')
|
||||||
|
p.set_defaults(func=thread_get_stats)
|
||||||
|
|
||||||
def check_called_name(name):
|
def check_called_name(name):
|
||||||
if name in deprecated_aliases:
|
if name in deprecated_aliases:
|
||||||
print("{} is deprecated, use {} instead.".format(name, deprecated_aliases[name]), file=sys.stderr)
|
print("{} is deprecated, use {} instead.".format(name, deprecated_aliases[name]), file=sys.stderr)
|
||||||
|
@ -21,3 +21,12 @@ def context_switch_monitor(client, enabled=None):
|
|||||||
if enabled is not None:
|
if enabled is not None:
|
||||||
params['enabled'] = enabled
|
params['enabled'] = enabled
|
||||||
return client.call('context_switch_monitor', params)
|
return client.call('context_switch_monitor', params)
|
||||||
|
|
||||||
|
|
||||||
|
def thread_get_stats(client):
|
||||||
|
"""Query threads statistics.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Current threads statistics.
|
||||||
|
"""
|
||||||
|
return client.call('thread_get_stats')
|
||||||
|
Loading…
Reference in New Issue
Block a user