1 /* $OpenBSD: output-ometric.c,v 1.5 2023/06/29 14:33:35 tb 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 ometric_set_int_with_labels(metric, in->mfts_stale, 51 OKV("type", "state"), OKV("manifest", "stale"), ol); 52 53 ometric_set_int_with_labels(metric, in->roas, 54 OKV("type", "state"), OKV("roa", "valid"), ol); 55 ometric_set_int_with_labels(metric, in->roas_fail, 56 OKV("type", "state"), OKV("roa", "failed parse"), ol); 57 ometric_set_int_with_labels(metric, in->roas_invalid, 58 OKV("type", "state"), OKV("roa", "invalid"), ol); 59 60 ometric_set_int_with_labels(metric, in->aspas, 61 OKV("type", "state"), OKV("aspa", "valid"), ol); 62 ometric_set_int_with_labels(metric, in->aspas_fail, 63 OKV("type", "state"), OKV("aspa", "failed parse"), ol); 64 ometric_set_int_with_labels(metric, in->aspas_invalid, 65 OKV("type", "state"), OKV("aspa", "invalid"), ol); 66 67 ometric_set_int_with_labels(metric, in->brks, 68 OKV("type", "state"), OKV("router_key", "valid"), ol); 69 ometric_set_int_with_labels(metric, in->crls, 70 OKV("type", "state"), OKV("crl", "valid"), ol); 71 ometric_set_int_with_labels(metric, in->gbrs, 72 OKV("type", "state"), OKV("gbr", "valid"), ol); 73 ometric_set_int_with_labels(metric, in->taks, 74 OKV("type", "state"), OKV("tak", "valid"), ol); 75 76 ometric_set_int_with_labels(metric, in->vrps, 77 OKV("type", "state"), OKV("vrp", "total"), ol); 78 ometric_set_int_with_labels(metric, in->vrps_uniqs, 79 OKV("type", "state"), OKV("vrp", "unique"), ol); 80 81 ometric_set_int_with_labels(metric, in->vaps, 82 OKV("type", "state"), OKV("vap", "total"), ol); 83 ometric_set_int_with_labels(metric, in->vaps_uniqs, 84 OKV("type", "state"), OKV("vap", "unique"), ol); 85 ometric_set_int_with_labels(metric, in->vaps_pas, 86 OKV("type", "state"), OKV("vap providers", "total"), ol); 87 } 88 89 static void 90 ta_stats(int id) 91 { 92 struct olabels *ol; 93 const char *keys[2] = { "name", NULL }; 94 const char *values[2]; 95 96 values[0] = taldescs[id]; 97 values[1] = NULL; 98 99 ol = olabels_new(keys, values); 100 set_common_stats(&talstats[id], rpki_ta_obj, ol); 101 olabels_free(ol); 102 } 103 104 static void 105 repo_tal_stats(const struct repo *rp, const struct repotalstats *in, void *arg) 106 { 107 struct olabels *ol; 108 const char *keys[4] = { "name", "carepo", "notify", NULL }; 109 const char *values[4]; 110 int talid = *(int *)arg; 111 112 values[0] = taldescs[talid]; 113 repo_fetch_uris(rp, &values[1], &values[2]); 114 values[3] = NULL; 115 116 ol = olabels_new(keys, values); 117 set_common_stats(in, rpki_repo_obj, ol); 118 olabels_free(ol); 119 } 120 121 static void 122 repo_stats(const struct repo *rp, const struct repostats *in, void *arg) 123 { 124 struct olabels *ol; 125 const char *keys[3] = { "carepo", "notify", NULL }; 126 const char *values[3]; 127 128 repo_fetch_uris(rp, &values[0], &values[1]); 129 values[2] = NULL; 130 131 ol = olabels_new(keys, values); 132 ometric_set_timespec(rpki_repo_duration, &in->sync_time, ol); 133 134 ometric_set_int_with_labels(rpki_repo_obj, in->del_files, 135 OKV("type", "state"), OKV("files", "deleted"), ol); 136 ometric_set_int_with_labels(rpki_repo_obj, in->extra_files, 137 OKV("type", "state"), OKV("files", "extra"), ol); 138 ometric_set_int_with_labels(rpki_repo_obj, in->del_extra_files, 139 OKV("type", "state"), OKV("files", "deleted_extra"), ol); 140 ometric_set_int_with_labels(rpki_repo_obj, in->del_dirs, 141 OKV("type", "state"), OKV("dirs", "deleted"), ol); 142 143 ometric_set_state(rpki_repo_state, repo_states[repo_synced(rp)], ol); 144 if (repo_synced(rp)) 145 ometric_set_state(rpki_repo_proto, repo_proto(rp), ol); 146 olabels_free(ol); 147 } 148 149 int 150 output_ometric(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks, 151 struct vap_tree *vaps, struct stats *st) 152 { 153 struct olabels *ol; 154 const char *keys[4] = { "nodename", "domainname", "release", NULL }; 155 const char *values[4]; 156 char hostname[HOST_NAME_MAX + 1]; 157 char *domainname; 158 struct timespec now_time; 159 int rv, i; 160 161 rpki_info = ometric_new(OMT_INFO, "rpki_client", 162 "rpki-client information"); 163 rpki_completion_time = ometric_new(OMT_GAUGE, 164 "rpki_client_job_completion_time", 165 "end of this run as epoch timestamp"); 166 167 rpki_repo = ometric_new(OMT_GAUGE, "rpki_client_repository", 168 "total number of repositories"); 169 rpki_obj = ometric_new(OMT_GAUGE, "rpki_client_objects", 170 "total number of objects"); 171 172 rpki_duration = ometric_new(OMT_GAUGE, "rpki_client_duration", 173 "duration in seconds"); 174 175 rpki_ta_obj = ometric_new(OMT_GAUGE, "rpki_client_ta_objects", 176 "total number of objects per TAL"); 177 rpki_repo_obj = ometric_new(OMT_GAUGE, "rpki_client_repository_objects", 178 "total number of objects per repository"); 179 rpki_repo_duration = ometric_new(OMT_GAUGE, 180 "rpki_client_repository_duration", 181 "duration used to sync this repository in seconds"); 182 rpki_repo_state = ometric_new_state(repo_states, 183 sizeof(repo_states) / sizeof(repo_states[0]), 184 "rpki_client_repository_state", 185 "repository state"); 186 rpki_repo_proto = ometric_new_state(repo_protos, 187 sizeof(repo_protos) / sizeof(repo_protos[0]), 188 "rpki_client_repository_protos", 189 "used protocol to sync repository"); 190 191 /* 192 * Dump statistics 193 */ 194 if (gethostname(hostname, sizeof(hostname))) 195 err(1, "gethostname"); 196 if ((domainname = strchr(hostname, '.'))) 197 *domainname++ = '\0'; 198 199 values[0] = hostname; 200 values[1] = domainname; 201 values[2] = RPKI_VERSION; 202 values[3] = NULL; 203 204 ol = olabels_new(keys, values); 205 ometric_set_info(rpki_info, NULL, NULL, ol); 206 olabels_free(ol); 207 208 for (i = 0; i < talsz; i++) { 209 repo_tal_stats_collect(repo_tal_stats, i, &i); 210 ta_stats(i); 211 } 212 repo_stats_collect(repo_stats, NULL); 213 set_common_stats(&st->repo_tal_stats, rpki_obj, NULL); 214 215 ometric_set_int_with_labels(rpki_repo, st->rsync_repos, 216 OKV("type", "state"), OKV("rsync", "synced"), NULL); 217 ometric_set_int_with_labels(rpki_repo, st->rsync_fails, 218 OKV("type", "state"), OKV("rsync", "failed"), NULL); 219 ometric_set_int_with_labels(rpki_repo, st->http_repos, 220 OKV("type", "state"), OKV("http", "synced"), NULL); 221 ometric_set_int_with_labels(rpki_repo, st->http_fails, 222 OKV("type", "state"), OKV("http", "failed"), NULL); 223 ometric_set_int_with_labels(rpki_repo, st->rrdp_repos, 224 OKV("type", "state"), OKV("rrdp", "synced"), NULL); 225 ometric_set_int_with_labels(rpki_repo, st->rrdp_fails, 226 OKV("type", "state"), OKV("rrdp", "failed"), NULL); 227 228 ometric_set_timespec_with_labels(rpki_duration, &st->elapsed_time, 229 OKV("type"), OKV("elapsed"), NULL); 230 ometric_set_timespec_with_labels(rpki_duration, &st->user_time, 231 OKV("type"), OKV("user"), NULL); 232 ometric_set_timespec_with_labels(rpki_duration, &st->system_time, 233 OKV("type"), OKV("system"), NULL); 234 235 clock_gettime(CLOCK_REALTIME, &now_time); 236 ometric_set_timespec(rpki_completion_time, &now_time, NULL); 237 238 rv = ometric_output_all(out); 239 ometric_free_all(); 240 241 return rv; 242 } 243