ncteisen | 3b42f83 | 2018-03-19 13:22:35 -0700 | [diff] [blame] | 1 | /* |
| 2 | * |
| 3 | * Copyright 2017 gRPC authors. |
| 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | * |
| 17 | */ |
| 18 | |
| 19 | #include <grpc/impl/codegen/port_platform.h> |
| 20 | |
ncteisen | 3b42f83 | 2018-03-19 13:22:35 -0700 | [diff] [blame] | 21 | #include "src/core/lib/channel/channel_trace.h" |
ncteisen | 97066fd | 2018-07-13 14:05:27 -0700 | [diff] [blame] | 22 | #include "src/core/lib/channel/channelz.h" |
ncteisen | bba8840 | 2018-05-11 11:54:41 -0400 | [diff] [blame] | 23 | #include "src/core/lib/channel/channelz_registry.h" |
ncteisen | 3b42f83 | 2018-03-19 13:22:35 -0700 | [diff] [blame] | 24 | #include "src/core/lib/gpr/useful.h" |
ncteisen | 3be52f9 | 2018-05-11 12:34:02 -0400 | [diff] [blame] | 25 | #include "src/core/lib/gprpp/memory.h" |
ncteisen | 3b42f83 | 2018-03-19 13:22:35 -0700 | [diff] [blame] | 26 | |
| 27 | #include <grpc/support/alloc.h> |
| 28 | #include <grpc/support/log.h> |
ncteisen | 9a6c722 | 2018-07-13 12:09:55 -0700 | [diff] [blame] | 29 | #include <grpc/support/sync.h> |
ncteisen | 3b42f83 | 2018-03-19 13:22:35 -0700 | [diff] [blame] | 30 | |
ncteisen | aca5043 | 2018-07-10 18:50:45 -0700 | [diff] [blame] | 31 | #include <cstring> |
| 32 | |
ncteisen | 3be52f9 | 2018-05-11 12:34:02 -0400 | [diff] [blame] | 33 | namespace grpc_core { |
ncteisen | 9a6c722 | 2018-07-13 12:09:55 -0700 | [diff] [blame] | 34 | namespace channelz { |
ncteisen | 3be52f9 | 2018-05-11 12:34:02 -0400 | [diff] [blame] | 35 | namespace { |
ncteisen | 3b42f83 | 2018-03-19 13:22:35 -0700 | [diff] [blame] | 36 | |
ncteisen | 3be52f9 | 2018-05-11 12:34:02 -0400 | [diff] [blame] | 37 | // singleton instance of the registry. |
| 38 | ChannelzRegistry* g_channelz_registry = nullptr; |
| 39 | |
ncteisen | 3be52f9 | 2018-05-11 12:34:02 -0400 | [diff] [blame] | 40 | } // anonymous namespace |
| 41 | |
| 42 | void ChannelzRegistry::Init() { g_channelz_registry = New<ChannelzRegistry>(); } |
| 43 | |
| 44 | void ChannelzRegistry::Shutdown() { Delete(g_channelz_registry); } |
| 45 | |
| 46 | ChannelzRegistry* ChannelzRegistry::Default() { |
| 47 | GPR_DEBUG_ASSERT(g_channelz_registry != nullptr); |
| 48 | return g_channelz_registry; |
ncteisen | 3b42f83 | 2018-03-19 13:22:35 -0700 | [diff] [blame] | 49 | } |
| 50 | |
ncteisen | 2fe4938 | 2018-07-11 08:11:40 -0700 | [diff] [blame] | 51 | ChannelzRegistry::ChannelzRegistry() { gpr_mu_init(&mu_); } |
ncteisen | 3b42f83 | 2018-03-19 13:22:35 -0700 | [diff] [blame] | 52 | |
ncteisen | 2fe4938 | 2018-07-11 08:11:40 -0700 | [diff] [blame] | 53 | ChannelzRegistry::~ChannelzRegistry() { gpr_mu_destroy(&mu_); } |
ncteisen | 3be52f9 | 2018-05-11 12:34:02 -0400 | [diff] [blame] | 54 | |
ncteisen | 9a6c722 | 2018-07-13 12:09:55 -0700 | [diff] [blame] | 55 | intptr_t ChannelzRegistry::InternalRegisterEntry(const RegistryEntry& entry) { |
| 56 | mu_guard guard(&mu_); |
| 57 | entities_.push_back(entry); |
| 58 | intptr_t uuid = entities_.size(); |
| 59 | return uuid; |
ncteisen | 3b42f83 | 2018-03-19 13:22:35 -0700 | [diff] [blame] | 60 | } |
| 61 | |
ncteisen | 9a6c722 | 2018-07-13 12:09:55 -0700 | [diff] [blame] | 62 | void ChannelzRegistry::InternalUnregisterEntry(intptr_t uuid, EntityType type) { |
| 63 | GPR_ASSERT(uuid >= 1); |
| 64 | mu_guard guard(&mu_); |
| 65 | GPR_ASSERT(static_cast<size_t>(uuid) <= entities_.size()); |
| 66 | GPR_ASSERT(entities_[uuid - 1].type == type); |
| 67 | entities_[uuid - 1].object = nullptr; |
ncteisen | 97066fd | 2018-07-13 14:05:27 -0700 | [diff] [blame] | 68 | entities_[uuid - 1].type = EntityType::kUnset; |
ncteisen | 9a6c722 | 2018-07-13 12:09:55 -0700 | [diff] [blame] | 69 | } |
| 70 | |
| 71 | void* ChannelzRegistry::InternalGetEntry(intptr_t uuid, EntityType type) { |
| 72 | mu_guard guard(&mu_); |
| 73 | if (uuid < 1 || uuid > static_cast<intptr_t>(entities_.size())) { |
| 74 | return nullptr; |
| 75 | } |
| 76 | if (entities_[uuid - 1].type == type) { |
| 77 | return entities_[uuid - 1].object; |
| 78 | } else { |
| 79 | return nullptr; |
| 80 | } |
| 81 | } |
| 82 | |
ncteisen | 97066fd | 2018-07-13 14:05:27 -0700 | [diff] [blame] | 83 | char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) { |
| 84 | grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); |
| 85 | grpc_json* json = top_level_json; |
| 86 | grpc_json* json_iterator = nullptr; |
| 87 | InlinedVector<ChannelNode*, 10> top_level_channels; |
| 88 | // uuids index into entities one-off (idx 0 is really uuid 1, since 0 is |
ncteisen | 5d373c4 | 2018-07-17 11:57:31 -0700 | [diff] [blame] | 89 | // reserved). However, we want to support requests coming in this |
ncteisen | 97066fd | 2018-07-13 14:05:27 -0700 | [diff] [blame] | 90 | // start_channel_id=0, which signifies "give me everything." Hence this |
| 91 | // funky looking line below. |
| 92 | size_t start_idx = start_channel_id == 0 ? 0 : start_channel_id - 1; |
| 93 | for (size_t i = start_idx; i < entities_.size(); ++i) { |
| 94 | if (entities_[i].type == EntityType::kChannelNode) { |
| 95 | ChannelNode* channel_node = |
| 96 | static_cast<ChannelNode*>(entities_[i].object); |
| 97 | if (channel_node->is_top_level_channel()) { |
| 98 | top_level_channels.push_back(channel_node); |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | if (top_level_channels.size() > 0) { |
| 103 | // create list of channels |
| 104 | grpc_json* array_parent = grpc_json_create_child( |
| 105 | nullptr, json, "channel", nullptr, GRPC_JSON_ARRAY, false); |
| 106 | for (size_t i = 0; i < top_level_channels.size(); ++i) { |
| 107 | grpc_json* channel_json = top_level_channels[i]->RenderJson(); |
| 108 | json_iterator = |
| 109 | grpc_json_link_child(array_parent, channel_json, json_iterator); |
| 110 | channel_json->parent = array_parent; |
ncteisen | 97066fd | 2018-07-13 14:05:27 -0700 | [diff] [blame] | 111 | } |
| 112 | } |
| 113 | // For now we do not have any pagination rules. In the future we could |
| 114 | // pick a constant for max_channels_sent for a GetTopChannels request. |
| 115 | // Tracking: https://github.com/grpc/grpc/issues/16019. |
| 116 | json_iterator = grpc_json_create_child(nullptr, json, "end", nullptr, |
| 117 | GRPC_JSON_TRUE, false); |
| 118 | char* json_str = grpc_json_dump_to_string(top_level_json, 0); |
| 119 | grpc_json_destroy(top_level_json); |
| 120 | return json_str; |
| 121 | } |
| 122 | |
ncteisen | 9a6c722 | 2018-07-13 12:09:55 -0700 | [diff] [blame] | 123 | } // namespace channelz |
ncteisen | 3be52f9 | 2018-05-11 12:34:02 -0400 | [diff] [blame] | 124 | } // namespace grpc_core |