aboutsummaryrefslogtreecommitdiff
path: root/src/channelz.rs
blob: 65180bc92e2bb90c57a6fe28bbe756bca51228a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0.

//! Channelz provides channel level debug information. In short, There are four types of
//! top level entities: channel, subchannel, socket and server. All entities are
//! identified by an positive unique integer, which is allocated in order. For more
//! explanation, see https://github.com/grpc/proposal/blob/master/A14-channelz.md.
//!
//! A full support requires a service that allow remote querying. But for now it's
//! too complicated to add full support. Because gRPC C core exposes the information
//! using JSON format, and there is no protobuf library that supports parsing json
//! format in Rust. So this module only provides safe APIs to access the informations.

use std::ffi::CStr;
use std::{cmp, str};

macro_rules! visit {
    ($ptr:expr, $visitor:ident) => {{
        let s_ptr = $ptr;
        let res;
        if !s_ptr.is_null() {
            let c_s = CStr::from_ptr(s_ptr);
            // It's json string, so it must be utf8 compatible.
            let s = str::from_utf8_unchecked(c_s.to_bytes());
            res = $visitor(s);
            grpcio_sys::gpr_free(s_ptr as _);
        } else {
            res = $visitor("");
        }
        res
    }};
}

/// Gets all root channels (i.e. channels the application has directly created). This
/// does not include subchannels nor non-top level channels.
pub fn get_top_channels<V, R>(start_channel_id: u64, visitor: V) -> R
where
    V: FnOnce(&str) -> R,
{
    unsafe {
        visit!(
            grpcio_sys::grpc_channelz_get_top_channels(start_channel_id as _),
            visitor
        )
    }
}

/// Gets all servers that exist in the process.
pub fn get_servers<V, R>(start_server_id: u64, visitor: V) -> R
where
    V: FnOnce(&str) -> R,
{
    unsafe {
        visit!(
            grpcio_sys::grpc_channelz_get_servers(start_server_id as _),
            visitor
        )
    }
}

/// Returns a single Server, or else an empty string.
pub fn get_server<V, R>(server_id: u64, visitor: V) -> R
where
    V: FnOnce(&str) -> R,
{
    unsafe {
        visit!(
            grpcio_sys::grpc_channelz_get_server(server_id as _),
            visitor
        )
    }
}

/// Gets all server sockets that exist in the server.
pub fn get_server_sockets<V, R>(
    server_id: u64,
    start_socket_id: u64,
    max_results: usize,
    visitor: V,
) -> R
where
    V: FnOnce(&str) -> R,
{
    let max_results = cmp::min(isize::MAX as usize, max_results) as isize;
    unsafe {
        visit!(
            grpcio_sys::grpc_channelz_get_server_sockets(
                server_id as _,
                start_socket_id as _,
                max_results
            ),
            visitor
        )
    }
}

/// Returns a single Channel, or else an empty string.
pub fn get_channel<V, R>(channel_id: u64, visitor: V) -> R
where
    V: FnOnce(&str) -> R,
{
    unsafe {
        visit!(
            grpcio_sys::grpc_channelz_get_channel(channel_id as _),
            visitor
        )
    }
}

/// Returns a single Subchannel, or else an empty string.
pub fn get_subchannel<V, R>(subchannel_id: u64, visitor: V) -> R
where
    V: FnOnce(&str) -> R,
{
    unsafe {
        visit!(
            grpcio_sys::grpc_channelz_get_subchannel(subchannel_id as _),
            visitor
        )
    }
}

/// Returns a single Socket, or else an empty string.
pub fn get_socket<V, R>(socket_id: u64, visitor: V) -> R
where
    V: FnOnce(&str) -> R,
{
    unsafe {
        visit!(
            grpcio_sys::grpc_channelz_get_socket(socket_id as _),
            visitor
        )
    }
}