1
#include "source/server/admin/server_info_handler.h"
2

            
3
#include "envoy/admin/v3/memory.pb.h"
4

            
5
#include "source/common/http/headers.h"
6
#include "source/common/memory/stats.h"
7
#include "source/common/version/version.h"
8
#include "source/server/utils.h"
9

            
10
namespace Envoy {
11
namespace Server {
12

            
13
10735
ServerInfoHandler::ServerInfoHandler(Server::Instance& server) : HandlerContextBase(server) {}
14

            
15
Http::Code ServerInfoHandler::handlerCerts(Http::ResponseHeaderMap& response_headers,
16
5
                                           Buffer::Instance& response, AdminStream&) {
17
  // This set is used to track distinct certificates. We may have multiple listeners, upstreams, etc
18
  // using the same cert.
19
5
  response_headers.setReferenceContentType(Http::Headers::get().ContentTypeValues.Json);
20
5
  envoy::admin::v3::Certificates certificates;
21
5
  server_.sslContextManager().iterateContexts([&](const Ssl::Context& context) -> void {
22
2
    envoy::admin::v3::Certificate& certificate = *certificates.add_certificates();
23
2
    if (context.getCaCertInformation() != nullptr) {
24
1
      envoy::admin::v3::CertificateDetails* ca_certificate = certificate.add_ca_cert();
25
1
      *ca_certificate = *context.getCaCertInformation();
26
1
    }
27
2
    for (const auto& cert_details : context.getCertChainInformation()) {
28
1
      envoy::admin::v3::CertificateDetails* cert_chain = certificate.add_cert_chain();
29
1
      *cert_chain = *cert_details;
30
1
    }
31
2
  });
32
5
  response.add(MessageUtil::getJsonStringFromMessageOrError(certificates, true, true));
33
5
  return Http::Code::OK;
34
5
}
35

            
36
Http::Code ServerInfoHandler::handlerHotRestartVersion(Http::ResponseHeaderMap&,
37
3
                                                       Buffer::Instance& response, AdminStream&) {
38
3
  response.add(server_.hotRestart().version());
39
3
  return Http::Code::OK;
40
3
}
41

            
42
// TODO(ambuc): Add more tcmalloc stats, export proto details based on allocator.
43
Http::Code ServerInfoHandler::handlerMemory(Http::ResponseHeaderMap& response_headers,
44
1
                                            Buffer::Instance& response, AdminStream&) {
45
1
  response_headers.setReferenceContentType(Http::Headers::get().ContentTypeValues.Json);
46
1
  envoy::admin::v3::Memory memory;
47
1
  memory.set_allocated(Memory::Stats::totalCurrentlyAllocated());
48
1
  memory.set_heap_size(Memory::Stats::totalCurrentlyReserved());
49
1
  memory.set_total_thread_cache(Memory::Stats::totalThreadCacheBytes());
50
1
  memory.set_pageheap_unmapped(Memory::Stats::totalPageHeapUnmapped());
51
1
  memory.set_pageheap_free(Memory::Stats::totalPageHeapFree());
52
1
  memory.set_total_physical_bytes(Memory::Stats::totalPhysicalBytes());
53
1
  response.add(MessageUtil::getJsonStringFromMessageOrError(memory, true, true)); // pretty-print
54
1
  return Http::Code::OK;
55
1
}
56

            
57
Http::Code ServerInfoHandler::handleMemoryTcmallocStats(Http::ResponseHeaderMap& response_headers,
58
1
                                                        Buffer::Instance& response, AdminStream&) {
59
1
  response_headers.setReferenceContentType(Http::Headers::get().ContentTypeValues.Text);
60
1
  auto stats = Memory::Stats::dumpStats();
61

            
62
1
  if (stats.has_value()) {
63
1
    response.add(stats.value());
64
1
    return Http::Code::OK;
65
1
  }
66

            
67
  response.add("Envoy was not built with tcmalloc.\n");
68
  return Http::Code::NotImplemented;
69
1
}
70

            
71
Http::Code ServerInfoHandler::handlerReady(Http::ResponseHeaderMap&, Buffer::Instance& response,
72
6
                                           AdminStream&) {
73
6
  const envoy::admin::v3::ServerInfo::State state =
74
6
      Utility::serverState(server_.initManager().state(), server_.healthCheckFailed());
75

            
76
6
  response.add(envoy::admin::v3::ServerInfo::State_Name(state) + "\n");
77
6
  Http::Code code =
78
6
      state == envoy::admin::v3::ServerInfo::LIVE ? Http::Code::OK : Http::Code::ServiceUnavailable;
79
6
  return code;
80
6
}
81

            
82
Http::Code ServerInfoHandler::handlerServerInfo(Http::ResponseHeaderMap& headers,
83
8
                                                Buffer::Instance& response, AdminStream&) {
84
8
  const std::time_t current_time =
85
8
      std::chrono::system_clock::to_time_t(server_.timeSource().systemTime());
86
8
  const std::time_t uptime_current_epoch = current_time - server_.startTimeCurrentEpoch();
87
8
  const std::time_t uptime_all_epochs = current_time - server_.startTimeFirstEpoch();
88

            
89
8
  ASSERT(uptime_current_epoch >= 0);
90
8
  ASSERT(uptime_all_epochs >= 0);
91

            
92
8
  envoy::admin::v3::ServerInfo server_info;
93
8
  server_info.set_version(VersionInfo::version());
94
8
  server_info.set_hot_restart_version(server_.hotRestart().version());
95
8
  server_info.set_state(
96
8
      Utility::serverState(server_.initManager().state(), server_.healthCheckFailed()));
97
8
  server_info.set_hot_restart_initializing(server_.hotRestart().isInitializing());
98

            
99
8
  server_info.mutable_uptime_current_epoch()->set_seconds(uptime_current_epoch);
100
8
  server_info.mutable_uptime_all_epochs()->set_seconds(uptime_all_epochs);
101
8
  envoy::admin::v3::CommandLineOptions* command_line_options =
102
8
      server_info.mutable_command_line_options();
103
8
  Server::CommandLineOptionsPtr options = server_.options().toCommandLineOptions();
104
8
  if (options) {
105
5
    *command_line_options = *options;
106
5
  }
107
8
  server_info.mutable_node()->MergeFrom(server_.localInfo().node());
108
8
  response.add(MessageUtil::getJsonStringFromMessageOrError(server_info, true, true));
109
8
  headers.setReferenceContentType(Http::Headers::get().ContentTypeValues.Json);
110
8
  return Http::Code::OK;
111
8
}
112

            
113
} // namespace Server
114
} // namespace Envoy