1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: jan@swi-prolog.org 5 WWW: http://www.swi-prolog.org 6 Copyright (C): 2024 SWI-Prolog Solutions b.v. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2 11 of the License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public 19 License along with this library; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 22 As a special exception, if you link this library with other files, 23 compiled with a Free Software compiler, to produce an executable, this 24 library does not by itself cause the resulting executable to be covered 25 by the GNU General Public License. This exception does not however 26 invalidate any other reasons why the executable file might be covered by 27 the GNU General Public License. 28*/ 29 30:- module(http_server_health, 31 [ server_health/1 % +Request 32 ]). 33:- autoload(library(lists), [member/2]). 34:- autoload(library(aggregate), [aggregate_all/3, aggregate_all/4]). 35:- autoload(library(apply), [maplist/3]). 36:- autoload(library(option), [option/2]). 37:- autoload(library(http/http_dispatch), [http_handler/3]). 38:- autoload(library(http/http_json), [reply_json/1]). 39:- autoload(library(http/http_parameters), [http_parameters/2]). 40:- autoload(library(http/thread_httpd), [http_server_property/2, http_workers/2]). 41:- autoload(library(http/http_stream), [cgi_statistics/1]). 42:- use_module(library(http/http_cors), [cors_enable/2, cors_enable/0]). 43 44:- http_handler(root(health), server_health, [id(server_health), priority(-10)]).
Processes an optional parameter fields
to specify the fields that
should be returned. The fields content is "," or white space
delimited.
66server_health(Request) :- 67 option(method(options), Request), !, 68 cors_enable(Request, 69 [ methods([get]) 70 ]), 71 format('~n'). 72server_health(Request) :- 73 http_parameters(Request, 74 [ fields(FieldSpec, [ optional(true) ]) 75 ]), 76 cors_enable, 77 ( var(FieldSpec) 78 -> true 79 ; split_string(FieldSpec, ", \t\r\n", " \t\r\n", Strings), 80 maplist(atom_string, Fields, Strings) 81 ), 82 get_server_health(Health, Fields), 83 reply_json(Health). 84 85get_server_health(Health, Fields) :- 86 var(Fields), 87 !, 88 findall(Key-Value, health(Key, Value), Pairs), 89 dict_pairs(Health, health, Pairs). 90get_server_health(Health, Fields) :- 91 findall(Key-Value, (member(Key,Fields),health(Key, Value)), Pairs), 92 dict_pairs(Health, health, Pairs).
true
./proc/self/fd
. Otherwise we use
stream_property/2 with the file_no(Fd)
property./proc/loadavg
inuse
, but including the TCMalloc overhead and
(thus) memory that has been freed and is not (yet) reused.135:- multifile health/2. 136 137term_expansion((health(Key,Value) :- Body), 138 (health(Key,Value) :- \+ hide(Key), Body)). 139 140health(up, true) :- 141 true. 142health(epoch, Epoch) :- 143 http_server_property(_, start_time(Epoch)). 144health(cpu_time, Time) :- 145 statistics(process_cputime, Time). 146health(threads, Count) :- 147 statistics(threads, Count). 148health(workers, Count) :- 149 aggregate_all(sum(N), http_workers(_,N), Count). 150health(requests, RequestCount) :- 151 cgi_statistics(requests(RequestCount)). 152health(bytes_sent, BytesSent) :- 153 cgi_statistics(bytes_sent(BytesSent)). 154:- if(exists_directory('/proc/self/fd')). 155health(open_files, Streams) :- 156 directory_files('/proc/self/fd', FDs), 157 length(FDs, Files), 158 Streams is Files - 2. % Ignore . and .. 159:- else. 160health(open_files, Streams) :- 161 findall(N, stream_property(_, file_no(N)), FDs), 162 sort(FDs, Unique), 163 length(Unique, Streams). 164:- endif. 165health(loadavg, LoadAVG) :- 166 access_file('/proc/loadavg', exist), 167 catch(setup_call_cleanup( 168 open('/proc/loadavg', read, In), 169 read_string(In, _, String), 170 close(In)), 171 _, fail), 172 split_string(String, " ", " ", [One,Five,Fifteen|_]), 173 maplist(number_string, LoadAVG, [One,Five,Fifteen]). 174:- if(current_predicate(malloc_property/1)). 175health(heap, json{inuse:InUse, size:Size}) :- 176 malloc_property('generic.current_allocated_bytes'(InUse)), 177 malloc_property('generic.heap_size'(Size)). 178:- endif.
186:- multifile hide/1.
HTTP Server health statistics
This module defines an HTTP handler for
/health
. The handler returns a JSON document with elementary health statistics on the running instance. The location can be changed using http_handler/3. Keys may be added using additional clauses for health/2 or hidden using hide/1.This library defines an HTTP handler and defines two multifile predicates (health/2 and hide/1) to control the information presented. */