taler-exchange-httpd_aml-statistics-get.c (5079B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file taler-exchange-httpd_aml-statistics-get.c 18 * @brief Return summary information about KYC statistics 19 * @author Christian Grothoff 20 */ 21 #include "taler/platform.h" 22 #include <gnunet/gnunet_util_lib.h> 23 #include <jansson.h> 24 #include <microhttpd.h> 25 #include <pthread.h> 26 #include "taler/taler_json_lib.h" 27 #include "taler/taler_mhd_lib.h" 28 #include "taler/taler_signatures.h" 29 #include "taler-exchange-httpd.h" 30 #include "taler/taler_exchangedb_plugin.h" 31 #include "taler-exchange-httpd_aml-statistics-get.h" 32 #include "taler-exchange-httpd_metrics.h" 33 34 /** 35 * Maximum number of statistics that can be requested in one go. 36 */ 37 #define MAX_STATS 64 38 39 40 /** 41 * Function called with AML statistics (counters). 42 * 43 * @param cls JSON array to build 44 * @param name name of the counter 45 * @param cnt number of events for @a name in the query range 46 */ 47 static void 48 add_stat ( 49 void *cls, 50 const char *name, 51 uint64_t cnt) 52 { 53 json_t *stats = cls; 54 55 GNUNET_assert ( 56 0 == 57 json_array_append_new ( 58 stats, 59 GNUNET_JSON_PACK ( 60 GNUNET_JSON_pack_string ("event", 61 name), 62 GNUNET_JSON_pack_uint64 ("counter", 63 cnt)))); 64 } 65 66 67 MHD_RESULT 68 TEH_handler_aml_kyc_statistics_get ( 69 struct TEH_RequestContext *rc, 70 const struct TALER_AmlOfficerPublicKeyP *officer_pub, 71 const char *const args[]) 72 { 73 struct GNUNET_TIME_Timestamp start_date = GNUNET_TIME_UNIT_ZERO_TS; 74 struct GNUNET_TIME_Timestamp end_date = GNUNET_TIME_UNIT_FOREVER_TS; 75 const char *all_names = args[0]; 76 json_t *stats; 77 size_t max_names; 78 79 if ( (NULL == args[0]) || 80 (NULL != args[1]) ) 81 { 82 GNUNET_break_op (0); 83 return TALER_MHD_reply_with_error ( 84 rc->connection, 85 MHD_HTTP_NOT_FOUND, 86 TALER_EC_GENERIC_ENDPOINT_UNKNOWN, 87 rc->url); 88 } 89 TALER_MHD_parse_request_timestamp (rc->connection, 90 "start_date", 91 &start_date); 92 TALER_MHD_parse_request_timestamp (rc->connection, 93 "end_date", 94 &end_date); 95 if (GNUNET_TIME_absolute_is_never (end_date.abs_time)) 96 end_date = GNUNET_TIME_absolute_to_timestamp ( 97 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_SECONDS)); 98 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 99 "Looking for stats on %s from [%llu,%llu)\n", 100 all_names, 101 (unsigned long long) start_date.abs_time.abs_value_us, 102 (unsigned long long) end_date.abs_time.abs_value_us); 103 /* Estimate number of names in 'all_names' */ 104 max_names = 1; 105 for (size_t i = 0; '\0' != all_names[i]; i++) 106 if (' ' == all_names[i]) 107 max_names++; 108 if (max_names > MAX_STATS) 109 { 110 GNUNET_break_op (0); 111 return TALER_MHD_reply_with_error ( 112 rc->connection, 113 MHD_HTTP_URI_TOO_LONG, 114 TALER_EC_GENERIC_URI_TOO_LONG, 115 rc->url); 116 } 117 stats = json_array (); 118 GNUNET_assert (NULL != stats); 119 { 120 char *buf; 121 const char *names[GNUNET_NZL (max_names)]; 122 enum GNUNET_DB_QueryStatus qs; 123 size_t num_names = 0; 124 125 buf = GNUNET_strdup (all_names); 126 for (const char *tok = strtok (buf, 127 " "); 128 NULL != tok; 129 tok = strtok (NULL, 130 " ")) 131 { 132 GNUNET_assert (num_names < max_names); 133 names[num_names++] = tok; 134 } 135 qs = TEH_plugin->select_aml_statistics ( 136 TEH_plugin->cls, 137 num_names, 138 names, 139 start_date, 140 end_date, 141 &add_stat, 142 stats); 143 GNUNET_free (buf); 144 switch (qs) 145 { 146 case GNUNET_DB_STATUS_HARD_ERROR: 147 case GNUNET_DB_STATUS_SOFT_ERROR: 148 GNUNET_break (0); 149 return TALER_MHD_reply_with_error ( 150 rc->connection, 151 MHD_HTTP_INTERNAL_SERVER_ERROR, 152 TALER_EC_GENERIC_DB_FETCH_FAILED, 153 "select_aml_statistics"); 154 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 155 return TALER_MHD_reply_static ( 156 rc->connection, 157 MHD_HTTP_NO_CONTENT, 158 NULL, 159 NULL, 160 0); 161 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 162 break; 163 } 164 return TALER_MHD_REPLY_JSON_PACK ( 165 rc->connection, 166 MHD_HTTP_OK, 167 GNUNET_JSON_pack_array_steal ("statistics", 168 stats)); 169 } 170 } 171 172 173 /* end of taler-exchange-httpd_aml-statistics_get.c */