nitweb: introduce metrics API
[nit.git] / src / web / api_metrics.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 module api_metrics
16
17 import web_base
18 import metrics
19
20 # Group all api handlers in one router.
21 class APIMetricsRouter
22 super Router
23
24 # Model to pass to handlers.
25 var model: Model
26
27 # Mainmodule to pass to handlers.
28 var mainmodule: MModule
29
30 init do
31 use("/structural/:id", new APIStructuralMetrics(model, mainmodule))
32 end
33 end
34
35 class APIStructuralMetrics
36 super APIHandler
37
38 private fun mclasses_metrics: MetricSet do
39 var metrics = new MetricSet
40 metrics.register(new CNOA(mainmodule, view))
41 metrics.register(new CNOP(mainmodule, view))
42 metrics.register(new CNOC(mainmodule, view))
43 metrics.register(new CNOD(mainmodule, view))
44 metrics.register(new CNOAC(mainmodule, view))
45 metrics.register(new CNOAA(mainmodule, view))
46 metrics.register(new CNOAI(mainmodule, view))
47 metrics.register(new CDIT(mainmodule, view))
48 metrics.register(new CNBP(mainmodule, view))
49 metrics.register(new CNBA(mainmodule, view))
50 metrics.register(new CNBM(mainmodule, view))
51 metrics.register(new CNBI(mainmodule, view))
52 metrics.register(new CNBV(mainmodule, view))
53 metrics.register(new CNBIP(mainmodule, view))
54 metrics.register(new CNBRP(mainmodule, view))
55 metrics.register(new CNBHP(mainmodule, view))
56 metrics.register(new CNBLP(mainmodule, view))
57 return metrics
58 end
59
60 private fun mmodules_metrics: MetricSet do
61 var metrics = new MetricSet
62 metrics.register(new MNOA(mainmodule, view))
63 metrics.register(new MNOP(mainmodule, view))
64 metrics.register(new MNOC(mainmodule, view))
65 metrics.register(new MNOD(mainmodule, view))
66 metrics.register(new MDIT(mainmodule, view))
67 metrics.register(new MNBD(mainmodule, view))
68 metrics.register(new MNBI(mainmodule, view))
69 metrics.register(new MNBR(mainmodule, view))
70 metrics.register(new MNBCC(mainmodule, view))
71 metrics.register(new MNBAC(mainmodule, view))
72 metrics.register(new MNBIC(mainmodule, view))
73 return metrics
74 end
75
76 redef fun get(req, res) do
77 var mentity = mentity_from_uri(req, res)
78 if mentity == null then
79 res.error 404
80 return
81 end
82 var metrics = mentity.collect_metrics(self)
83 if metrics == null then
84 res.error 404
85 return
86 end
87 res.json metrics
88 end
89 end
90
91 redef class MEntity
92 private fun collect_metrics(h: APIStructuralMetrics): nullable JsonObject do return null
93 end
94
95 redef class MPackage
96 redef fun collect_metrics(h) do
97 var mclasses = new HashSet[MClass]
98 for mgroup in self.mgroups do
99 for mmodule in mgroup.mmodules do mclasses.add_all mmodule.intro_mclasses
100 end
101
102 var mclasses_metrics = h.mclasses_metrics
103 mclasses_metrics.collect(new HashSet[MClass].from(mclasses))
104
105 var mmodules = new HashSet[MModule]
106 for mgroup in self.mgroups do
107 mmodules.add_all mgroup.mmodules
108 end
109
110 var mmodules_metrics = h.mmodules_metrics
111 mmodules_metrics.collect(new HashSet[MModule].from(mmodules))
112
113 var metrics = new JsonObject
114 metrics["mclasses"] = mclasses_metrics
115 metrics["mmodules"] = mmodules_metrics
116 return metrics
117 end
118 end
119
120 redef class MGroup
121 redef fun collect_metrics(h) do
122 var mclasses = new HashSet[MClass]
123 for mmodule in self.mmodules do mclasses.add_all mmodule.intro_mclasses
124
125 var mclasses_metrics = h.mclasses_metrics
126 mclasses_metrics.collect(new HashSet[MClass].from(mclasses))
127
128 var mmodules_metrics = h.mmodules_metrics
129 mmodules_metrics.collect(new HashSet[MModule].from(mmodules))
130
131 var metrics = new JsonObject
132 metrics["mclasses"] = mclasses_metrics
133 metrics["mmodules"] = mmodules_metrics
134 return metrics
135 end
136 end
137
138 redef class MModule
139 redef fun collect_metrics(h) do
140 var mclasses_metrics = h.mclasses_metrics
141 mclasses_metrics.collect(new HashSet[MClass].from(intro_mclasses))
142
143 var mmodule_metrics = h.mmodules_metrics
144 mmodule_metrics.collect(new HashSet[MModule].from([self]))
145
146 var metrics = new JsonObject
147 metrics["mclasses"] = mclasses_metrics
148 metrics["mmodule"] = mmodule_metrics
149 return metrics
150 end
151 end
152
153 redef class MClass
154 redef fun collect_metrics(h) do
155 var mclass_metrics = h.mclasses_metrics
156 mclass_metrics.collect(new HashSet[MClass].from([self]))
157
158 var metrics = new JsonObject
159 metrics["mclass"] = mclass_metrics
160 return metrics
161 end
162 end
163
164 redef class MetricSet
165 super Jsonable
166
167 fun json: JsonObject do
168 var obj = new JsonObject
169 for metric in metrics do
170 obj[metric.name] = metric
171 end
172 return obj
173 end
174
175 redef fun to_json do return json.to_json
176 end
177
178 redef class Metric
179 super Jsonable
180
181 fun json: JsonObject do
182 var obj = new JsonObject
183 obj["name"] = name
184 obj["desc"] = desc
185 obj["empty"] = values.is_empty
186 if values.not_empty then obj["avg"] = avg
187 if values.not_empty then obj["std_dev"] = std_dev
188 if values.not_empty then obj["threshold"] = threshold
189 return obj
190 end
191
192 redef fun to_json do return json.to_json
193 end
194
195 redef class IntMetric
196 redef fun json do
197 var obj = super
198 if values.not_empty then obj["sum"] = sum
199 return obj
200 end
201 end
202
203 redef class FloatMetric
204 redef fun json do
205 var obj = super
206 if values.not_empty then obj["sum"] = sum
207 return obj
208 end
209 end
210
211 redef class MModuleMetric
212 redef fun json do
213 var obj = super
214 if values.not_empty then obj["min"] = min
215 if values.not_empty then obj["max"] = max
216 var values = new JsonObject
217 for value in sort do
218 var v = self[value]
219 var vobj = new JsonObject
220 vobj["mentity"] = value
221 vobj["value"] = if v isa Jsonable then v else v.to_s
222 values[value.full_name] = vobj
223 end
224 obj["values"] = values
225 return obj
226 end
227 end
228
229 redef class MClassMetric
230 redef fun json do
231 var obj = super
232 if values.not_empty then obj["min"] = min
233 if values.not_empty then obj["max"] = max
234 var values = new JsonObject
235 for value in sort do
236 var v = self[value]
237 var vobj = new JsonObject
238 vobj["mentity"] = value
239 vobj["value"] = if v isa Jsonable then v else v.to_s
240 values[value.full_name] = vobj
241 end
242 obj["values"] = values
243 return obj
244 end
245 end