]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/dnssd_analytics.c
mDNSResponder-1310.40.42.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / dnssd_analytics.c
1 /*
2 * Copyright (c) 2019-2020 Apple Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "dnssd_analytics.h"
18 #include "mDNSMacOSX.h"
19 #include "uds_daemon.h"
20
21 #if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS)
22
23 #include <xpc/xpc.h>
24 #include <CoreAnalytics/CoreAnalytics.h>
25 typedef xpc_object_t COREANALYTICS_RETURNS_RETAINED
26 (^event_create_block_t)(void);
27
28 #define UNSET_STR "unset"
29
30 #endif // ANALYTICS
31
32 #if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
33
34 // Local aggregate counters to track request counts
35
36 mDNSlocal uint64_t sCacheUsage_UnicastHitCount = 0;
37 mDNSlocal uint64_t sCacheUsage_UnicastMissCount = 0;
38 mDNSlocal uint64_t sCacheUsage_MulticastHitCount = 0;
39 mDNSlocal uint64_t sCacheUsage_MulticastMissCount = 0;
40
41 mDNSlocal uint64_t sCacheRequest_UnicastHitCount = 0;
42 mDNSlocal uint64_t sCacheRequest_UnicastMissCount = 0;
43 mDNSlocal uint64_t sCacheRequest_MulticastHitCount = 0;
44 mDNSlocal uint64_t sCacheRequest_MulticastMissCount = 0;
45
46 #if COMPILER_LIKES_PRAGMA_MARK
47 #pragma mark -
48 #pragma mark - Private CacheUsage Functions
49 #endif
50
51 mDNSlocal void
52 dnssd_analytics_post_cache_request_count(CacheRequestType inType, CacheState inState, uint64_t inRequestCount)
53 {
54 event_create_block_t create_event;
55 bool posted;
56
57 create_event = ^{
58 xpc_object_t dict;
59 dict = xpc_dictionary_create(NULL, NULL, 0);
60 xpc_dictionary_set_string(dict, "requestType", inType == CacheRequestType_multicast ? "multicast" : "unicast");
61 xpc_dictionary_set_string(dict, "cacheState", inState == CacheState_hit ? "hit" : "miss");
62 xpc_dictionary_set_uint64(dict, "requestCount", inRequestCount);
63 return (dict);
64 };
65 posted = analytics_send_event_lazy("com.apple.mDNSResponder.CacheUsage.request", create_event);
66 if (!posted) {
67 LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "com.apple.mDNSResponder.CacheUsage.request: Failed to post");
68 }
69 }
70
71 mDNSlocal void
72 dnssd_analytics_post_cache_request_counts()
73 {
74 if (sCacheRequest_UnicastHitCount > 0) {
75 dnssd_analytics_post_cache_request_count(CacheRequestType_unicast, CacheState_hit, sCacheRequest_UnicastHitCount);
76 sCacheRequest_UnicastHitCount = 0;
77 }
78 if (sCacheRequest_UnicastMissCount > 0) {
79 dnssd_analytics_post_cache_request_count(CacheRequestType_unicast, CacheState_miss, sCacheRequest_UnicastMissCount);
80 sCacheRequest_UnicastMissCount = 0;
81 }
82 if (sCacheRequest_MulticastHitCount > 0) {
83 dnssd_analytics_post_cache_request_count(CacheRequestType_multicast, CacheState_hit, sCacheRequest_MulticastHitCount);
84 sCacheRequest_MulticastHitCount = 0;
85 }
86 if (sCacheRequest_MulticastMissCount > 0) {
87 dnssd_analytics_post_cache_request_count(CacheRequestType_multicast, CacheState_miss, sCacheRequest_MulticastMissCount);
88 sCacheRequest_MulticastMissCount = 0;
89 }
90 }
91
92 mDNSlocal void
93 dnssd_analytics_post_cache_usage_counts_for_type(CacheRequestType inType, uint64_t inHitCount, uint64_t inMissCount)
94 {
95 event_create_block_t create_event;
96 bool posted;
97
98 create_event = ^{
99 xpc_object_t dict;
100 dict = xpc_dictionary_create(NULL, NULL, 0);
101 xpc_dictionary_set_string(dict, "requestType", inType == CacheRequestType_multicast ? "multicast" : "unicast");
102 xpc_dictionary_set_uint64(dict, "hitCount", inHitCount);
103 xpc_dictionary_set_uint64(dict, "missCount", inMissCount);
104 return (dict);
105 };
106 posted = analytics_send_event_lazy("com.apple.mDNSResponder.CacheUsage.entries", create_event);
107 if (!posted) {
108 LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "com.apple.mDNSResponder.CacheUsage.entries: Failed to post");
109 }
110 }
111
112 mDNSlocal void
113 dnssd_analytics_post_cache_usage_counts()
114 {
115 if (sCacheUsage_MulticastHitCount || sCacheUsage_MulticastMissCount) {
116 dnssd_analytics_post_cache_usage_counts_for_type(CacheRequestType_multicast, sCacheUsage_MulticastHitCount, sCacheUsage_MulticastMissCount);
117 sCacheUsage_MulticastHitCount = 0;
118 sCacheUsage_MulticastMissCount = 0;
119 }
120 if (sCacheUsage_UnicastHitCount || sCacheUsage_UnicastMissCount) {
121 dnssd_analytics_post_cache_usage_counts_for_type(CacheRequestType_unicast, sCacheUsage_UnicastHitCount, sCacheUsage_UnicastMissCount);
122 sCacheUsage_UnicastHitCount = 0;
123 sCacheUsage_UnicastMissCount = 0;
124 }
125 }
126
127 #if COMPILER_LIKES_PRAGMA_MARK
128 #pragma mark -
129 #pragma mark - Exported CacheUsage Functions
130 #endif
131
132 mDNSexport void
133 dnssd_analytics_update_cache_request(CacheRequestType inType, CacheState inState)
134 {
135 if (inType == CacheRequestType_unicast) {
136 if (inState == CacheState_hit) {
137 sCacheRequest_UnicastHitCount++;
138 } else if (inState == CacheState_miss) {
139 sCacheRequest_UnicastMissCount++;
140 } else {
141 LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "dnssd_analytics_update_cache_request: unknown CacheState %d for unicast", inState);
142 }
143 } else if (inType == CacheRequestType_multicast) {
144 if (inState == CacheState_hit) {
145 sCacheRequest_MulticastHitCount++;
146 } else if (inState == CacheState_miss) {
147 sCacheRequest_MulticastMissCount++;
148 } else {
149 LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "dnssd_analytics_update_cache_request: unknown CacheState %d for multicast", inState);
150 }
151 } else {
152 LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "dnssd_analytics_update_cache_request: unknown CacheRequestType %d", inType);
153 }
154 }
155
156 mDNSexport void
157 dnssd_analytics_update_cache_usage_counts(uint32_t inHitMulticastCount, uint32_t inMissMulticastCount, uint32_t inHitUnicastCount, uint32_t inMissUnicastCount)
158 {
159 sCacheUsage_MulticastHitCount += inHitMulticastCount;
160 sCacheUsage_MulticastMissCount += inMissMulticastCount;
161 sCacheUsage_UnicastHitCount += inHitUnicastCount;
162 sCacheUsage_UnicastMissCount += inMissUnicastCount;
163 }
164
165 #endif // CACHE_ANALYTICS
166
167 #if MDNSRESPONDER_SUPPORTS(APPLE, WAB_ANALYTICS)
168
169 #if COMPILER_LIKES_PRAGMA_MARK
170 #pragma mark -
171 #pragma mark - Exported WABUsage Functions
172 #endif
173
174 mDNSexport void
175 dnssd_analytics_post_WAB_usage_event_count(WABUsageKind inKind, WABUsageType inType, WABUsageEvent inEvent, uint64_t inEventCount)
176 {
177 event_create_block_t create_event;
178 bool posted;
179 char * kind = UNSET_STR;
180 char * type = UNSET_STR;
181 char * event = UNSET_STR;
182
183 if (analytics_send_event_lazy) {
184 switch (inKind) {
185 case WABUsageKind_results: {
186 kind = "results";
187 break;
188 }
189 case WABUsageKind_session: {
190 kind = "session";
191 break;
192 }
193 case WABUsageKind_operation: {
194 kind = "operation";
195 break;
196 }
197 }
198
199 switch (inType) {
200 case WABUsageType_enumeration: {
201 type = "enumeration";
202 break;
203 }
204 case WABUsageType_query: {
205 type = "query";
206 break;
207 }
208 case WABUsageType_push: {
209 type = "push";
210 break;
211 }
212 case WABUsageType_llq: {
213 type = "llq";
214 break;
215 }
216 }
217
218 switch (inEvent) {
219 case WABUsageEvent_positive: {
220 event = "positive";
221 break;
222 }
223 case WABUsageEvent_negative: {
224 event = "negative";
225 break;
226 }
227 case WABUsageEvent_null: {
228 event = "null";
229 break;
230 }
231 case WABUsageEvent_error: {
232 event = "error";
233 break;
234 }
235
236 case WABUsageEvent_connected: {
237 event = "connected";
238 break;
239 }
240 case WABUsageEvent_session: {
241 event = "session";
242 break;
243 }
244 case WABUsageEvent_reset: {
245 event = "reset";
246 break;
247 }
248 case WABUsageEvent_idledOut: {
249 event = "idledOut";
250 break;
251 }
252 case WABUsageEvent_goAway: {
253 event = "goAway";
254 break;
255 }
256 case WABUsageEvent_resumedGood: {
257 event = "resumedGood";
258 break;
259 }
260 case WABUsageEvent_resumedBad: {
261 event = "resumedBad";
262 break;
263 }
264
265 case WABUsageEvent_succeeded: {
266 event = "succeeded";
267 break;
268 }
269 case WABUsageEvent_rejected: {
270 event = "rejected";
271 break;
272 }
273 case WABUsageEvent_dsoni: {
274 event = "dsoni";
275 break;
276 }
277 case WABUsageEvent_answered: {
278 event = "answered";
279 break;
280 }
281 }
282
283 create_event = ^{
284 xpc_object_t dict;
285 dict = xpc_dictionary_create(NULL, NULL, 0);
286 xpc_dictionary_set_string(dict, "kind", kind);
287 xpc_dictionary_set_string(dict, "type", type);
288 xpc_dictionary_set_string(dict, "event", event);
289 xpc_dictionary_set_uint64(dict, "eventCount", inEventCount);
290 return (dict);
291 };
292 posted = analytics_send_event_lazy("com.apple.mDNSResponder.CacheUsage.entries", create_event);
293 if (!posted) {
294 LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "com.apple.mDNSResponder.CacheUsage.entries: Failed to post");
295 }
296 }
297 }
298
299 #endif // WAB_ANALYTICS
300
301 #if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS)
302 #if COMPILER_LIKES_PRAGMA_MARK
303 #pragma mark -
304 #pragma mark - Exported Analytics Functions
305 #endif
306
307 mDNSexport void
308 dnssd_analytics_init()
309 {
310 static dispatch_once_t sInitAnalyticsOnce = 0;
311 static dispatch_queue_t sAnalyticsQueue = NULL;
312 dispatch_once(&sInitAnalyticsOnce, ^{
313 sAnalyticsQueue = dispatch_queue_create("com.apple.mDNSResponder.analytics-reporting-queue", DISPATCH_QUEUE_SERIAL);
314 xpc_object_t criteria = xpc_dictionary_create(NULL, NULL, 0);
315 xpc_dictionary_set_bool(criteria, XPC_ACTIVITY_REPEATING, true);
316 xpc_dictionary_set_bool(criteria, XPC_ACTIVITY_ALLOW_BATTERY, true);
317 xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_DELAY, XPC_ACTIVITY_INTERVAL_1_DAY);
318 xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_GRACE_PERIOD, XPC_ACTIVITY_INTERVAL_5_MIN);
319 xpc_dictionary_set_string(criteria, XPC_ACTIVITY_PRIORITY, XPC_ACTIVITY_PRIORITY_MAINTENANCE);
320
321 xpc_activity_register("com.apple.mDNSResponder.analytics.daily", criteria, ^(xpc_activity_t activity) {
322 if (xpc_activity_should_defer(activity)) {
323 if (xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_DEFER)) {
324 LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_INFO, "com.apple.mDNSResponder.analytics.daily: Asked to defer");
325 } else {
326 LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_ERROR, "com.apple.mDNSResponder.analytics.daily: Asked to defer but failed to set state");
327 }
328 } else {
329 dispatch_async(sAnalyticsQueue, ^{
330 #if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS)
331 KQueueLock();
332 mDNS_Lock(&mDNSStorage);
333 #if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
334 dnssd_analytics_post_cache_request_counts();
335 dnssd_analytics_post_cache_usage_counts();
336 #endif // CACHE_ANALYTICS
337 LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_INFO, "Analytics Posted");
338 mDNS_Unlock(&mDNSStorage);
339 KQueueUnlock("Analytics Update");
340 #endif // ANALYTICS
341 });
342 if (!xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_DONE)) {
343 LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_ERROR, "com.apple.mDNSResponder.analytics.daily: Analytics XPC_ACTIVITY_STATE_DONE failed");
344 }
345 }
346 });
347 xpc_release(criteria);
348 });
349 }
350
351 #endif // ANALYTICS