1 /* $OpenBSD: output-ometric.c,v 1.7 2024/02/13 20:41:22 job Exp $ */ 2 /* 3 * Copyright (c) 2022 Claudio Jeker <claudio@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <err.h> 19 #include <limits.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <unistd.h> 24 25 #include "extern.h" 26 #include "ometric.h" 27 #include "version.h" 28 29 static struct ometric *rpki_info, *rpki_completion_time, *rpki_duration; 30 static struct ometric *rpki_repo, *rpki_obj, *rpki_ta_obj; 31 static struct ometric *rpki_repo_obj, *rpki_repo_duration; 32 static struct ometric *rpki_repo_state, *rpki_repo_proto; 33 34 static const char * const repo_states[2] = { "failed", "synced" }; 35 static const char * const repo_protos[3] = { "rrdp", "rsync", "https" }; 36 37 static void 38 set_common_stats(const struct repotalstats *in, struct ometric *metric, 39 struct olabels *ol) 40 { 41 ometric_set_int_with_labels(metric, in->certs, 42 OKV("type", "state"), OKV("cert", "valid"), ol); 43 ometric_set_int_with_labels(metric, in->certs_fail, 44 OKV("type", "state"), OKV("cert", "failed parse"), ol); 45 46 ometric_set_int_with_labels(metric, in->mfts, 47 OKV("type", "state"), OKV("manifest", "valid"), ol); 48 ometric_set_int_with_labels(metric, in->mfts_fail, 49 OKV("type", "state"), OKV("manifest", "failed parse"), ol); 50 51 ometric_set_int_with_labels(metric, in->roas, 52 OKV("type", "state"), OKV("roa", "valid"), ol); 53 ometric_set_int_with_labels(metric, in->roas_fail, 54 OKV("type", "state"), OKV("roa", "failed parse"), ol); 55 ometric_set_int_with_labels(metric, in->roas_invalid, 56 OKV("type", "state"), OKV("roa", "invalid"), ol); 57 58 ometric_set_int_with_labels(metric, in->aspas, 59 OKV("type", "state"), OKV("aspa", "valid"), ol); 60 ometric_set_int_with_labels(metric, in->aspas_fail, 61 OKV("type", "state"), OKV("aspa", "failed parse"), ol); 62 ometric_set_int_with_labels(metric, in->aspas_invalid, 63 OKV("type", "state"), OKV("aspa", "invalid"), ol); 64 65 ometric_set_int_with_labels(metric, in->brks, 66 OKV("type", "state"), OKV("router_key", "valid"), ol); 67 ometric_set_int_with_labels(metric, in->crls, 68 OKV("type", "state"), OKV("crl", "valid"), ol); 69 ometric_set_int_with_labels(metric, in->gbrs, 70 OKV("type", "state"), OKV("gbr", "valid"), ol); 71 ometric_set_int_with_labels(metric, in->taks, 72 OKV("type", "state"), OKV("tak", "valid"), ol); 73 74 ometric_set_int_with_labels(metric, in->vrps, 75 OKV("type", "state"), OKV("vrp", "total"), ol); 76 ometric_set_int_with_labels(metric, in->vrps_uniqs, 77 OKV("type", "state"), OKV("vrp", "unique"), ol); 78 79 ometric_set_int_with_labels(metric, in->vaps, 80 OKV("type", "state"), OKV("vap", "total"), ol); 81 ometric_set_int_with_labels(metric, in->vaps_uniqs, 82 OKV("type", "state"), OKV("vap", "unique"), ol); 83 ometric_set_int_with_labels(metric, in->vaps_pas, 84 OKV("type", "state"), OKV("vap providers", "total"), ol); 85 } 86 87 static void 88 ta_stats(int id) 89 { 90 struct olabels *ol; 91 const char *keys[2] = { "name", NULL }; 92 const char *values[2]; 93 94 values[0] = taldescs[id]; 95 values[1] = NULL; 96 97 ol = olabels_new(keys, values); 98 set_common_stats(&talstats[id], rpki_ta_obj, ol); 99 olabels_free(ol); 100 } 101 102 static void 103 repo_tal_stats(const struct repo *rp, const struct repotalstats *in, void *arg) 104 { 105 struct olabels *ol; 106 const char *keys[4] = { "name", "carepo", "notify", NULL }; 107 const char *values[4]; 108 int talid = *(int *)arg; 109 110 values[0] = taldescs[talid]; 111 repo_fetch_uris(rp, &values[1], &values[2]); 112 values[3] = NULL; 113 114 ol = olabels_new(keys, values); 115 set_common_stats(in, rpki_repo_obj, ol); 116 olabels_free(ol); 117 } 118 119 static void 120 repo_stats(const struct repo *rp, const struct repostats *in, void *arg) 121 { 122 struct olabels *ol; 123 const char *keys[3] = { "carepo", "notify", NULL }; 124 const char *values[3]; 125 126 repo_fetch_uris(rp, &values[0], &values[1]); 127 values[2] = NULL; 128 129 ol = olabels_new(keys, values); 130 ometric_set_timespec(rpki_repo_duration, &in->sync_time, ol); 131 132 ometric_set_int_with_labels(rpki_repo_obj, in->del_files, 133 OKV("type", "state"), OKV("files", "deleted"), ol); 134 ometric_set_int_with_labels(rpki_repo_obj, in->extra_files, 135 OKV("type", "state"), OKV("files", "extra"), ol); 136 ometric_set_int_with_labels(rpki_repo_obj, in->del_extra_files, 137 OKV("type", "state"), OKV("files", "deleted_extra"), ol); 138 ometric_set_int_with_labels(rpki_repo_obj, in->del_dirs, 139 OKV("type", "state"), OKV("dirs", "deleted"), ol); 140 141 ometric_set_state(rpki_repo_state, repo_states[repo_synced(rp)], ol); 142 if (repo_synced(rp)) 143 ometric_set_state(rpki_repo_proto, repo_proto(rp), ol); 144 olabels_free(ol); 145 } 146 147 int 148 output_ometric(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks, 149 struct vap_tree *vaps, struct stats *st) 150 { 151 struct olabels *ol; 152 const char *keys[4] = { "nodename", "domainname", "release", NULL }; 153 const char *values[4]; 154 char hostname[HOST_NAME_MAX + 1]; 155 char *domainname; 156 struct timespec now_time; 157 int rv, i; 158 159 rpki_info = ometric_new(OMT_INFO, "rpki_client", 160 "rpki-client information"); 161 rpki_completion_time = ometric_new(OMT_GAUGE, 162 "rpki_client_job_completion_time", 163 "end of this run as epoch timestamp"); 164 165 rpki_repo = ometric_new(OMT_GAUGE, "rpki_client_repository", 166 "total number of repositories"); 167 rpki_obj = ometric_new(OMT_GAUGE, "rpki_client_objects", 168 "total number of objects"); 169 170 rpki_duration = ometric_new(OMT_GAUGE, "rpki_client_duration", 171 "duration in seconds"); 172 173 rpki_ta_obj = ometric_new(OMT_GAUGE, "rpki_client_ta_objects", 174 "total number of objects per TAL"); 175 rpki_repo_obj = ometric_new(OMT_GAUGE, "rpki_client_repository_objects", 176 "total number of objects per repository"); 177 rpki_repo_duration = ometric_new(OMT_GAUGE, 178 "rpki_client_repository_duration", 179 "duration used to sync this repository in seconds"); 180 rpki_repo_state = ometric_new_state(repo_states, 181 sizeof(repo_states) / sizeof(repo_states[0]), 182 "rpki_client_repository_state", 183 "repository state"); 184 rpki_repo_proto = ometric_new_state(repo_protos, 185 sizeof(repo_protos) / sizeof(repo_protos[0]), 186 "rpki_client_repository_protos", 187 "used protocol to sync repository"); 188 189 /* 190 * Dump statistics 191 */ 192 if (gethostname(hostname, sizeof(hostname))) 193 err(1, "gethostname"); 194 if ((domainname = strchr(hostname, '.'))) 195 *domainname++ = '\0'; 196 197 values[0] = hostname; 198 values[1] = domainname; 199 values[2] = RPKI_VERSION; 200 values[3] = NULL; 201 202 ol = olabels_new(keys, values); 203 ometric_set_info(rpki_info, NULL, NULL, ol); 204 olabels_free(ol); 205 206 for (i = 0; i < talsz; i++) { 207 repo_tal_stats_collect(repo_tal_stats, i, &i); 208 ta_stats(i); 209 } 210 repo_stats_collect(repo_stats, NULL); 211 set_common_stats(&st->repo_tal_stats, rpki_obj, NULL); 212 213 ometric_set_int_with_labels(rpki_repo, st->rsync_repos, 214 OKV("type", "state"), OKV("rsync", "synced"), NULL); 215 ometric_set_int_with_labels(rpki_repo, st->rsync_fails, 216 OKV("type", "state"), OKV("rsync", "failed"), NULL); 217 ometric_set_int_with_labels(rpki_repo, st->http_repos, 218 OKV("type", "state"), OKV("http", "synced"), NULL); 219 ometric_set_int_with_labels(rpki_repo, st->http_fails, 220 OKV("type", "state"), OKV("http", "failed"), NULL); 221 ometric_set_int_with_labels(rpki_repo, st->rrdp_repos, 222 OKV("type", "state"), OKV("rrdp", "synced"), NULL); 223 ometric_set_int_with_labels(rpki_repo, st->rrdp_fails, 224 OKV("type", "state"), OKV("rrdp", "failed"), NULL); 225 226 ometric_set_timespec_with_labels(rpki_duration, &st->elapsed_time, 227 OKV("type"), OKV("elapsed"), NULL); 228 ometric_set_timespec_with_labels(rpki_duration, &st->user_time, 229 OKV("type"), OKV("user"), NULL); 230 ometric_set_timespec_with_labels(rpki_duration, &st->system_time, 231 OKV("type"), OKV("system"), NULL); 232 233 clock_gettime(CLOCK_REALTIME, &now_time); 234 ometric_set_timespec(rpki_completion_time, &now_time, NULL); 235 236 rv = ometric_output_all(out); 237 ometric_free_all(); 238 239 return rv; 240 } 241