]> git.immae.eu Git - github/bastienwirtz/homer.git/blob - src/components/services/Prometheus.vue
Add Prometheus custom component
[github/bastienwirtz/homer.git] / src / components / services / Prometheus.vue
1 <template>
2 <div>
3 <div
4 class="card"
5 :style="`background-color:${item.background};`"
6 :class="item.class"
7 >
8 <a :href="item.url" :target="item.target" rel="noreferrer">
9 <div class="card-content">
10 <div :class="mediaClass">
11 <slot name="icon">
12 <div v-if="item.logo" class="media-left">
13 <figure class="image is-48x48">
14 <img :src="item.logo" :alt="`${item.name} logo`" />
15 </figure>
16 </div>
17 <div v-if="item.icon" class="media-left">
18 <figure class="image is-48x48">
19 <i style="font-size: 35px" :class="['fa-fw', item.icon]"></i>
20 </figure>
21 </div>
22 </slot>
23 <div class="media-content">
24 <slot name="content">
25 <p class="title is-4">{{ item.name }}</p>
26 <p class="subtitle is-6">
27 <template v-if="item.subtitle">
28 {{ item.subtitle }}
29 </template>
30 <template v-else-if="api">
31 {{ count }} {{ level }} alerts
32 </template>
33 </p>
34 </slot>
35 </div>
36 <div v-if="api" class="status" :class="level">
37 {{ count }}
38 </div>
39 </div>
40 <div class="tag" :class="item.tagstyle" v-if="item.tag">
41 <strong class="tag-text">#{{ item.tag }}</strong>
42 </div>
43 </div>
44 </a>
45 </div>
46 </div>
47 </template>
48
49 <script>
50 export default {
51 name: "Prometheus",
52 props: {
53 item: Object,
54 },
55 data: () => ({
56 api: {
57 status: "",
58 count: 0,
59 alerts: {
60 firing: 0,
61 inactive: 0,
62 pending: 0,
63 },
64 },
65 }),
66 computed: {
67 mediaClass: function () {
68 return { media: true, "no-subtitle": !this.item.subtitle };
69 },
70 count: function () {
71 return (
72 this.countFiring() || this.countPending() || this.countInactive() || 0
73 );
74 },
75 level: function () {
76 if (this.countFiring()) {
77 return "firing";
78 } else if (this.countPending()) {
79 return "pending";
80 }
81 return "inactive";
82 },
83 },
84 created() {
85 this.fetchStatus();
86 },
87 methods: {
88 fetchStatus: async function () {
89 const url = `${this.item.url}/api/v1/alerts`;
90 this.api = await fetch(url, { method: "get" })
91 .then((response) => {
92 return response.json();
93 })
94 .catch((e) => console.log(e));
95 },
96 countFiring: function () {
97 if (this.api) {
98 return this.api.data?.alerts?.filter(
99 (alert) => alert.state === "firing"
100 ).length;
101 }
102 return 0;
103 },
104 countPending: function () {
105 if (this.api) {
106 return this.api.data?.alerts?.filter(
107 (alert) => alert.state === "pending"
108 ).length;
109 }
110 return 0;
111 },
112 countInactive: function () {
113 if (this.api) {
114 return this.api.data?.alerts?.filter(
115 (alert) => alert.state === "inactive"
116 ).length;
117 }
118 return 0;
119 },
120 },
121 };
122 </script>
123
124 <style scoped lang="scss">
125 .media-left {
126 .image {
127 display: flex;
128 align-items: center;
129 }
130
131 img {
132 max-height: 100%;
133 }
134 }
135 .status {
136 font-size: 0.8rem;
137 color: var(--text-title);
138
139 &.firing:before {
140 background-color: #d65c68;
141 border-color: #e87d88;
142 box-shadow: 0 0 5px 1px #d65c68;
143 }
144
145 &.pending:before {
146 background-color: #e8bb7d;
147 border-color: #d6a35c;
148 box-shadow: 0 0 5px 1px #e8bb7d;
149 }
150
151 &.inactive:before {
152 background-color: #8fe87d;
153 border-color: #70d65c;
154 box-shadow: 0 0 5px 1px #8fe87d;
155 }
156
157 &:before {
158 content: " ";
159 display: inline-block;
160 width: 7px;
161 height: 7px;
162 margin-right: 10px;
163 border: 1px solid #000;
164 border-radius: 7px;
165 }
166 }
167 </style>