1 | package eu.clarin.sru.fcs.aggregator.scan; |
---|
2 | |
---|
3 | import com.fasterxml.jackson.annotation.JsonProperty; |
---|
4 | import java.util.ArrayList; |
---|
5 | import java.util.Collections; |
---|
6 | import java.util.Date; |
---|
7 | import java.util.HashMap; |
---|
8 | import java.util.List; |
---|
9 | import java.util.Map; |
---|
10 | |
---|
11 | /** |
---|
12 | * |
---|
13 | * @author edima |
---|
14 | * @author ljo |
---|
15 | * |
---|
16 | * Stores statistics information about scans or searches. The info is then sent |
---|
17 | * to the JS client and displayed in the /Aggregator/stats page. |
---|
18 | */ |
---|
19 | public class Statistics { |
---|
20 | |
---|
21 | public static class EndpointStats { |
---|
22 | |
---|
23 | private final Object lock = new Object(); |
---|
24 | |
---|
25 | @JsonProperty |
---|
26 | FCSProtocolVersion version = FCSProtocolVersion.LEGACY; |
---|
27 | |
---|
28 | @JsonProperty |
---|
29 | List<String> rootCollections = new ArrayList<String>(); |
---|
30 | |
---|
31 | List<Long> queueTimes = Collections.synchronizedList(new ArrayList<Long>()); |
---|
32 | List<Long> executionTimes = Collections.synchronizedList(new ArrayList<Long>()); |
---|
33 | |
---|
34 | @JsonProperty |
---|
35 | int maxConcurrentRequests; |
---|
36 | |
---|
37 | public static class DiagPair { |
---|
38 | |
---|
39 | public DiagPair(Diagnostic diagnostic, String context, int counter) { |
---|
40 | this.diagnostic = diagnostic; |
---|
41 | this.context = context; |
---|
42 | this.counter = counter; |
---|
43 | } |
---|
44 | |
---|
45 | @JsonProperty |
---|
46 | public Diagnostic diagnostic; |
---|
47 | @JsonProperty |
---|
48 | String context; |
---|
49 | @JsonProperty |
---|
50 | public int counter; |
---|
51 | } |
---|
52 | |
---|
53 | @JsonProperty |
---|
54 | Map<String, DiagPair> diagnostics = Collections.synchronizedMap(new HashMap<String, DiagPair>()); |
---|
55 | |
---|
56 | public static class ExcPair { |
---|
57 | |
---|
58 | public ExcPair(JsonException exception, String context, int counter) { |
---|
59 | this.exception = exception; |
---|
60 | this.context = context; |
---|
61 | this.counter = counter; |
---|
62 | } |
---|
63 | |
---|
64 | @JsonProperty |
---|
65 | public JsonException exception; |
---|
66 | @JsonProperty |
---|
67 | String context; |
---|
68 | @JsonProperty |
---|
69 | public int counter; |
---|
70 | } |
---|
71 | |
---|
72 | @JsonProperty |
---|
73 | Map<String, ExcPair> errors = Collections.synchronizedMap(new HashMap<String, ExcPair>()); |
---|
74 | |
---|
75 | double avg(List<Long> q) { |
---|
76 | double sum = 0; |
---|
77 | for (long l : q) { |
---|
78 | sum += l; |
---|
79 | } |
---|
80 | return sum / q.size(); |
---|
81 | } |
---|
82 | |
---|
83 | double max(List<Long> q) { |
---|
84 | double max = 0; |
---|
85 | for (long l : q) { |
---|
86 | max = max > l ? max : l; |
---|
87 | } |
---|
88 | return max; |
---|
89 | } |
---|
90 | |
---|
91 | @JsonProperty |
---|
92 | public double getAvgQueueTime() { |
---|
93 | return avg(queueTimes) / 1000.0; |
---|
94 | } |
---|
95 | |
---|
96 | @JsonProperty |
---|
97 | public double getMaxQueueTime() { |
---|
98 | return max(queueTimes) / 1000.0; |
---|
99 | } |
---|
100 | |
---|
101 | @JsonProperty |
---|
102 | public double getAvgExecutionTime() { |
---|
103 | return avg(executionTimes) / 1000.0; |
---|
104 | } |
---|
105 | |
---|
106 | @JsonProperty |
---|
107 | public double getMaxExecutionTime() { |
---|
108 | return max(executionTimes) / 1000.0; |
---|
109 | } |
---|
110 | |
---|
111 | @JsonProperty |
---|
112 | public int getNumberOfRequests() { |
---|
113 | return executionTimes.size(); |
---|
114 | } |
---|
115 | }; |
---|
116 | |
---|
117 | private final Object lock = new Object(); |
---|
118 | |
---|
119 | Date date = new Date(); |
---|
120 | |
---|
121 | public Date getDate() { |
---|
122 | return date; |
---|
123 | } |
---|
124 | |
---|
125 | // institution to endpoint to statistics_per_endpoint map |
---|
126 | Map<String, Map<String, EndpointStats>> institutions |
---|
127 | = Collections.synchronizedMap(new HashMap<String, Map<String, EndpointStats>>()); |
---|
128 | |
---|
129 | public Map<String, Map<String, EndpointStats>> getInstitutions() { |
---|
130 | return institutions; |
---|
131 | } |
---|
132 | |
---|
133 | public void initEndpoint(Institution institution, Endpoint endpoint, int maxConcurrentRequests) { |
---|
134 | EndpointStats stats = getEndpointStats(institution, endpoint); |
---|
135 | synchronized (stats.lock) { |
---|
136 | stats.maxConcurrentRequests = maxConcurrentRequests; |
---|
137 | } |
---|
138 | } |
---|
139 | |
---|
140 | public void addEndpointDatapoint(Institution institution, Endpoint endpoint, long enqueuedTime, long executionTime) { |
---|
141 | EndpointStats stats = getEndpointStats(institution, endpoint); |
---|
142 | synchronized (stats.lock) { |
---|
143 | stats.queueTimes.add(enqueuedTime); |
---|
144 | stats.executionTimes.add(executionTime); |
---|
145 | } |
---|
146 | } |
---|
147 | |
---|
148 | public void addEndpointDiagnostic(Institution institution, Endpoint endpoint, Diagnostic diag, String context) { |
---|
149 | EndpointStats stats = getEndpointStats(institution, endpoint); |
---|
150 | synchronized (stats.lock) { |
---|
151 | if (!stats.diagnostics.containsKey(diag.uri)) { |
---|
152 | stats.diagnostics.put(diag.uri, new EndpointStats.DiagPair(diag, context, 1)); |
---|
153 | } else { |
---|
154 | stats.diagnostics.get(diag.uri).counter++; |
---|
155 | } |
---|
156 | } |
---|
157 | } |
---|
158 | |
---|
159 | public void addErrorDatapoint(Institution institution, Endpoint endpoint, Exception error, String context) { |
---|
160 | EndpointStats stats = getEndpointStats(institution, endpoint); |
---|
161 | JsonException jxc = new JsonException(error); |
---|
162 | synchronized (stats.lock) { |
---|
163 | if (!stats.errors.containsKey(jxc.message)) { |
---|
164 | stats.errors.put(jxc.message, new EndpointStats.ExcPair(jxc, context, 1)); |
---|
165 | } else { |
---|
166 | stats.errors.get(jxc.message).counter++; |
---|
167 | } |
---|
168 | } |
---|
169 | } |
---|
170 | |
---|
171 | public void upgradeProtocolVersion(Institution institution, Endpoint endpoint) { |
---|
172 | EndpointStats stats = getEndpointStats(institution, endpoint); |
---|
173 | synchronized (stats.lock) { |
---|
174 | stats.version = endpoint.getProtocol().equals(FCSProtocolVersion.VERSION_2) ? FCSProtocolVersion.VERSION_2 : FCSProtocolVersion.VERSION_1; |
---|
175 | } |
---|
176 | } |
---|
177 | |
---|
178 | public void addEndpointCollection(Institution institution, Endpoint endpoint, String collectionName) { |
---|
179 | EndpointStats stats = getEndpointStats(institution, endpoint); |
---|
180 | synchronized (stats.lock) { |
---|
181 | stats.rootCollections.add(collectionName); |
---|
182 | } |
---|
183 | } |
---|
184 | |
---|
185 | public void addEndpointCollections(Institution institution, Endpoint endpoint, List<String> collections) { |
---|
186 | EndpointStats stats = getEndpointStats(institution, endpoint); |
---|
187 | synchronized (stats.lock) { |
---|
188 | stats.rootCollections.addAll(collections); |
---|
189 | } |
---|
190 | } |
---|
191 | |
---|
192 | private EndpointStats getEndpointStats(Institution institution, Endpoint endpoint) { |
---|
193 | EndpointStats stats; |
---|
194 | synchronized (lock) { |
---|
195 | if (!institutions.containsKey(institution.getName())) { |
---|
196 | institutions.put(institution.getName(), |
---|
197 | Collections.synchronizedMap(new HashMap<String, EndpointStats>())); |
---|
198 | } |
---|
199 | Map<String, EndpointStats> esmap = institutions.get(institution.getName()); |
---|
200 | if (!esmap.containsKey(endpoint.getUrl())) { |
---|
201 | EndpointStats es = new EndpointStats(); |
---|
202 | es.version = endpoint.getProtocol(); |
---|
203 | esmap.put(endpoint.getUrl(), es); |
---|
204 | } |
---|
205 | stats = esmap.get(endpoint.getUrl()); |
---|
206 | } |
---|
207 | return stats; |
---|
208 | } |
---|
209 | |
---|
210 | } |
---|