| /* |
| * Copyright (c) 2019-2024 Apple Inc. All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "dnssd_analytics.h" |
| #include "mDNSMacOSX.h" |
| #include "uds_daemon.h" |
| |
| #if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS) |
| |
| #include <xpc/xpc.h> |
| #include <CoreAnalytics/CoreAnalytics.h> |
| #include <CoreUtils/DebugServices.h> |
| #include "mdns_strict.h" |
| |
| #endif // ANALYTICS |
| |
| #if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS) |
| |
| // MARK: - Private Types |
| |
| enum : uint8_t { |
| e_index_standard_noncell = 0, |
| e_index_standard_cell, |
| e_index_encrypted_noncell, |
| e_index_encrypted_cell, |
| e_index_count, |
| e_index_invalid = -1 |
| }; |
| |
| typedef struct { |
| uint64_t queries; |
| uint64_t reply_pos; |
| uint64_t reply_neg; |
| } qtype_count_t; |
| |
| typedef struct { |
| uint64_t latency_count; // For calulating average |
| uint64_t latency_total; // For calulating average |
| uint64_t query_bytes; |
| uint64_t reply_bytes; |
| qtype_count_t v4; |
| qtype_count_t v6; |
| qtype_count_t https; |
| } dns_analytic_t; |
| static dns_analytic_t s_dns_analytics[e_index_count] = {0}; |
| |
| // MARK: - Private Functions |
| |
| static inline const char * |
| _index_to_transport_string(uint8_t index) |
| { |
| switch (index) { |
| case e_index_standard_noncell: |
| case e_index_standard_cell: |
| return "standard"; |
| case e_index_encrypted_noncell: |
| case e_index_encrypted_cell: |
| return "encrypted"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static inline const char * |
| _index_to_network_string(uint8_t index) |
| { |
| switch (index) { |
| case e_index_standard_noncell: |
| case e_index_encrypted_noncell: |
| return "non-cell"; |
| case e_index_standard_cell: |
| case e_index_encrypted_cell: |
| return "cellular"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static void |
| _post_dns_analytic(dns_analytic_t * const _Nonnull analytic, const char * _Nonnull network, const char * _Nonnull transport) |
| { |
| bool posted; |
| posted = analytics_send_event_lazy("com.apple.mDNSResponder.dnsqueryinfo", ^{ |
| xpc_object_t dict; |
| dict = xpc_dictionary_create(NULL, NULL, 0); |
| xpc_dictionary_set_string(dict, "network", network); |
| xpc_dictionary_set_string(dict, "transport", transport); |
| xpc_dictionary_set_uint64(dict, "latency_ms", analytic->latency_total / analytic->latency_count); |
| xpc_dictionary_set_uint64(dict, "query_bytes", analytic->query_bytes); |
| xpc_dictionary_set_uint64(dict, "reply_bytes", analytic->reply_bytes); |
| xpc_dictionary_set_uint64(dict, "v4_queries", analytic->v4.queries); |
| xpc_dictionary_set_uint64(dict, "v4_reply_pos", analytic->v4.reply_pos); |
| xpc_dictionary_set_uint64(dict, "v4_reply_neg", analytic->v4.reply_neg); |
| xpc_dictionary_set_uint64(dict, "v6_queries", analytic->v6.queries); |
| xpc_dictionary_set_uint64(dict, "v6_reply_pos", analytic->v6.reply_pos); |
| xpc_dictionary_set_uint64(dict, "v6_reply_neg", analytic->v6.reply_neg); |
| xpc_dictionary_set_uint64(dict, "https_queries", analytic->https.queries); |
| xpc_dictionary_set_uint64(dict, "https_reply_pos", analytic->https.reply_pos); |
| xpc_dictionary_set_uint64(dict, "https_reply_neg", analytic->https.reply_neg); |
| return (dict); |
| }); |
| if (!posted) { |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "com.apple.mDNSResponder.dnsqueryinfo: Analytic not posted"); |
| } |
| } |
| |
| static void |
| _post_dns_query_info(void) |
| { |
| for (uint8_t i = 0 ; i < e_index_count ; i++ ) { |
| if (s_dns_analytics[i].latency_count > 0) { |
| _post_dns_analytic(&s_dns_analytics[i], _index_to_network_string(i), _index_to_transport_string(i)); |
| } |
| } |
| memset(&s_dns_analytics, 0, sizeof(s_dns_analytics)); |
| } |
| |
| static qtype_count_t* |
| _qtype_count_for_analytic(dns_analytic_t * const _Nonnull analytic, uint16_t qtype) |
| { |
| qtype_count_t *qtype_ptr = NULL; |
| switch (qtype) { |
| case kDNSType_A: |
| qtype_ptr = &analytic->v4; |
| break; |
| |
| case kDNSType_AAAA: |
| qtype_ptr = &analytic->v6; |
| break; |
| |
| case kDNSType_HTTPS: |
| qtype_ptr = &analytic->https; |
| break; |
| |
| default: |
| break; |
| } |
| return qtype_ptr; |
| } |
| |
| static dns_analytic_t* |
| _analytic_for_event(bool is_cellular, dns_transport_t transport) |
| { |
| dns_analytic_t *analytic = NULL; |
| uint8_t index = e_index_invalid; |
| require_quiet(transport != dns_transport_Undefined, exit); |
| |
| if (is_cellular) { |
| if (transport == dns_transport_Do53) { |
| index = e_index_standard_cell; |
| } else { |
| index = e_index_encrypted_cell; |
| } |
| } else { |
| if (transport == dns_transport_Do53) { |
| index = e_index_standard_noncell; |
| } else { |
| index = e_index_encrypted_noncell; |
| } |
| } |
| require_quiet(index != e_index_invalid && index < e_index_count, exit); |
| analytic = &s_dns_analytics[index]; |
| exit: |
| return analytic; |
| } |
| |
| // MARK: - Public Functions |
| |
| void |
| dnssd_analytics_update_dns_query_info(bool is_cellular, dns_transport_t transport, uint16_t qtype, uint32_t num_queries, |
| uint32_t latency_ms, bool is_positive_answer) |
| { |
| require_quiet(num_queries > 0, exit); |
| |
| dns_analytic_t *analytic = _analytic_for_event(is_cellular, transport); |
| require_quiet(analytic, exit); |
| |
| qtype_count_t *qtype_count = _qtype_count_for_analytic(analytic, qtype); |
| require_quiet(qtype_count, exit); |
| |
| analytic->latency_count++; |
| analytic->latency_total += latency_ms; |
| |
| qtype_count->queries += num_queries; |
| if (is_positive_answer) { |
| qtype_count->reply_pos++; |
| } else { |
| qtype_count->reply_neg++; |
| } |
| |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_DEBUG, "dnssd_analytics_update_dns_query_info cell %d qtype %d queries %u latency %d pos %d", |
| is_cellular, qtype, num_queries, latency_ms, is_positive_answer); |
| exit: |
| return; |
| } |
| |
| void |
| dnssd_analytics_update_dns_query_size(bool is_cellular, dns_transport_t transport, uint32_t send_bytes) |
| { |
| dns_analytic_t *analytic = _analytic_for_event(is_cellular, transport); |
| require_quiet(analytic, exit); |
| |
| analytic->query_bytes += send_bytes; |
| |
| exit: |
| return; |
| } |
| |
| void |
| dnssd_analytics_update_dns_reply_size(bool is_cellular, dns_transport_t transport, uint32_t recv_bytes) |
| { |
| dns_analytic_t *analytic = _analytic_for_event(is_cellular, transport); |
| require_quiet(analytic, exit); |
| |
| analytic->reply_bytes += recv_bytes; |
| |
| exit: |
| return; |
| } |
| |
| #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER) |
| |
| dns_transport_t |
| dnssd_analytics_dns_transport_for_resolver_type(mdns_resolver_type_t type) |
| { |
| dns_transport_t transport; |
| mdns_clang_ignore_warning_begin(-Wswitch-default); |
| switch (type) { |
| case mdns_resolver_type_https: |
| transport = dns_transport_DoH; |
| break; |
| |
| case mdns_resolver_type_tls: |
| transport = dns_transport_DoT; |
| break; |
| |
| case mdns_resolver_type_normal: |
| case mdns_resolver_type_tcp: |
| transport = dns_transport_Do53; |
| break; |
| |
| case mdns_resolver_type_null: |
| transport = dns_transport_Undefined; |
| break; |
| } |
| mdns_clang_ignore_warning_end(); |
| return transport; |
| } |
| |
| #endif // QUERIER |
| |
| #endif // DNS_ANALYTICS |
| |
| #if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS) |
| |
| // Local aggregate counters to track request counts |
| |
| static uint64_t sCacheUsage_UnicastHitCount = 0; |
| static uint64_t sCacheUsage_UnicastMissCount = 0; |
| static uint64_t sCacheUsage_MulticastHitCount = 0; |
| static uint64_t sCacheUsage_MulticastMissCount = 0; |
| |
| static uint64_t sCacheRequest_UnicastHitCount = 0; |
| static uint64_t sCacheRequest_UnicastMissCount = 0; |
| static uint64_t sCacheRequest_MulticastHitCount = 0; |
| static uint64_t sCacheRequest_MulticastMissCount = 0; |
| |
| // MARK: - Private CacheUsage Functions |
| |
| static void |
| _post_cache_request_count(CacheRequestType inType, CacheState inState, uint64_t inRequestCount) |
| { |
| bool posted; |
| posted = analytics_send_event_lazy("com.apple.mDNSResponder.CacheUsage.request", ^{ |
| xpc_object_t dict; |
| dict = xpc_dictionary_create(NULL, NULL, 0); |
| xpc_dictionary_set_string(dict, "requestType", inType == CacheRequestType_multicast ? "multicast" : "unicast"); |
| xpc_dictionary_set_string(dict, "cacheState", inState == CacheState_hit ? "hit" : "miss"); |
| xpc_dictionary_set_uint64(dict, "requestCount", inRequestCount); |
| return (dict); |
| }); |
| if (!posted) { |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "com.apple.mDNSResponder.CacheUsage.request: Analytic not posted"); |
| } |
| } |
| |
| static void |
| _post_cache_request_counts(void) |
| { |
| if (sCacheRequest_UnicastHitCount > 0) { |
| _post_cache_request_count(CacheRequestType_unicast, CacheState_hit, sCacheRequest_UnicastHitCount); |
| sCacheRequest_UnicastHitCount = 0; |
| } |
| if (sCacheRequest_UnicastMissCount > 0) { |
| _post_cache_request_count(CacheRequestType_unicast, CacheState_miss, sCacheRequest_UnicastMissCount); |
| sCacheRequest_UnicastMissCount = 0; |
| } |
| if (sCacheRequest_MulticastHitCount > 0) { |
| _post_cache_request_count(CacheRequestType_multicast, CacheState_hit, sCacheRequest_MulticastHitCount); |
| sCacheRequest_MulticastHitCount = 0; |
| } |
| if (sCacheRequest_MulticastMissCount > 0) { |
| _post_cache_request_count(CacheRequestType_multicast, CacheState_miss, sCacheRequest_MulticastMissCount); |
| sCacheRequest_MulticastMissCount = 0; |
| } |
| } |
| |
| static void |
| _post_cache_usage_counts_for_type(CacheRequestType inType, uint64_t inHitCount, uint64_t inMissCount) |
| { |
| bool posted; |
| posted = analytics_send_event_lazy("com.apple.mDNSResponder.CacheUsage.entries", ^{ |
| xpc_object_t dict; |
| dict = xpc_dictionary_create(NULL, NULL, 0); |
| xpc_dictionary_set_string(dict, "requestType", inType == CacheRequestType_multicast ? "multicast" : "unicast"); |
| xpc_dictionary_set_uint64(dict, "hitCount", inHitCount); |
| xpc_dictionary_set_uint64(dict, "missCount", inMissCount); |
| return (dict); |
| }); |
| if (!posted) { |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "com.apple.mDNSResponder.CacheUsage.entries: Analytic not posted"); |
| } |
| } |
| |
| static void |
| _post_cache_usage_counts(void) |
| { |
| if (sCacheUsage_MulticastHitCount || sCacheUsage_MulticastMissCount) { |
| _post_cache_usage_counts_for_type(CacheRequestType_multicast, sCacheUsage_MulticastHitCount, sCacheUsage_MulticastMissCount); |
| sCacheUsage_MulticastHitCount = 0; |
| sCacheUsage_MulticastMissCount = 0; |
| } |
| if (sCacheUsage_UnicastHitCount || sCacheUsage_UnicastMissCount) { |
| _post_cache_usage_counts_for_type(CacheRequestType_unicast, sCacheUsage_UnicastHitCount, sCacheUsage_UnicastMissCount); |
| sCacheUsage_UnicastHitCount = 0; |
| sCacheUsage_UnicastMissCount = 0; |
| } |
| } |
| |
| // MARK: - Exported CacheUsage Functions |
| |
| void |
| dnssd_analytics_update_cache_request(CacheRequestType inType, CacheState inState) |
| { |
| if (inType == CacheRequestType_unicast) { |
| if (inState == CacheState_hit) { |
| sCacheRequest_UnicastHitCount++; |
| } else if (inState == CacheState_miss) { |
| sCacheRequest_UnicastMissCount++; |
| } else { |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "dnssd_analytics_update_cache_request: unknown CacheState %d for unicast", inState); |
| } |
| } else if (inType == CacheRequestType_multicast) { |
| if (inState == CacheState_hit) { |
| sCacheRequest_MulticastHitCount++; |
| } else if (inState == CacheState_miss) { |
| sCacheRequest_MulticastMissCount++; |
| } else { |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "dnssd_analytics_update_cache_request: unknown CacheState %d for multicast", inState); |
| } |
| } else { |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "dnssd_analytics_update_cache_request: unknown CacheRequestType %d", inType); |
| } |
| } |
| |
| void |
| dnssd_analytics_update_cache_usage_counts(uint32_t inHitMulticastCount, uint32_t inMissMulticastCount, uint32_t inHitUnicastCount, uint32_t inMissUnicastCount) |
| { |
| sCacheUsage_MulticastHitCount += inHitMulticastCount; |
| sCacheUsage_MulticastMissCount += inMissMulticastCount; |
| sCacheUsage_UnicastHitCount += inHitUnicastCount; |
| sCacheUsage_UnicastMissCount += inMissUnicastCount; |
| } |
| |
| #endif // CACHE_ANALYTICS |
| |
| #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_ASSIST_ANALYTICS) |
| |
| static uint64_t sUnicastAssist_UnicastCount = 0; |
| static uint64_t sUnicastAssist_MulticastCount = 0; |
| static uint64_t sNonUnicastAssist_UnicastCount = 0; |
| static uint64_t sNonUnicastAssist_MulticastCount = 0; |
| |
| static void |
| _post_unicast_assist(void) |
| { |
| bool posted; |
| posted = analytics_send_event_lazy("com.apple.mDNSResponder.unicastassist", ^{ |
| xpc_object_t dict; |
| dict = xpc_dictionary_create(NULL, NULL, 0); |
| xpc_dictionary_set_uint64(dict, "unicast", sUnicastAssist_UnicastCount); |
| xpc_dictionary_set_uint64(dict, "multicast", sUnicastAssist_MulticastCount); |
| xpc_dictionary_set_uint64(dict, "non_unicast", sNonUnicastAssist_UnicastCount); |
| xpc_dictionary_set_uint64(dict, "non_multicast", sNonUnicastAssist_MulticastCount); |
| return (dict); |
| }); |
| if (!posted) { |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "com.apple.mDNSResponder.unicastassist: Analytic not posted"); |
| } |
| sUnicastAssist_UnicastCount = 0; |
| sUnicastAssist_MulticastCount = 0; |
| sNonUnicastAssist_UnicastCount = 0; |
| sNonUnicastAssist_MulticastCount = 0; |
| } |
| |
| void |
| dnssd_analytics_update_unicast_assist(bool assist, bool unicast) |
| { |
| if (assist) { |
| if (unicast) { |
| sUnicastAssist_UnicastCount++; |
| } else { |
| sUnicastAssist_MulticastCount++; |
| } |
| } else { |
| if (unicast) { |
| sNonUnicastAssist_UnicastCount++; |
| } else { |
| sNonUnicastAssist_MulticastCount++; |
| } |
| } |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_DEBUG, |
| "dnssd_analytics_update_unicast_assist Assist(unicast %s%lld, multicast %s%lld) " |
| "NonAssist(unicast %s%lld, multicast %s%lld)", |
| assist ? unicast ? "*" : "" : "", sUnicastAssist_UnicastCount, |
| assist ? unicast ? "" : "*" : "", sUnicastAssist_MulticastCount, |
| !assist ? unicast ? "*" : "" : "", sNonUnicastAssist_UnicastCount, |
| !assist ? unicast ? "" : "*" : "", sNonUnicastAssist_MulticastCount); |
| } |
| |
| #endif // UNICAST_ASSIST_ANALYTICS |
| |
| |
| #if MDNSRESPONDER_SUPPORTS(APPLE, WAB_ANALYTICS) |
| |
| #define UNSET_STR "unset" |
| |
| // MARK: - Exported WABUsage Functions |
| |
| void |
| dnssd_analytics_post_WAB_usage_event_count(WABUsageKind inKind, WABUsageType inType, WABUsageEvent inEvent, uint64_t inEventCount) |
| { |
| bool posted; |
| char * kind = UNSET_STR; |
| char * type = UNSET_STR; |
| char * event = UNSET_STR; |
| |
| if (analytics_send_event_lazy) { |
| switch (inKind) { |
| case WABUsageKind_results: { |
| kind = "results"; |
| break; |
| } |
| case WABUsageKind_session: { |
| kind = "session"; |
| break; |
| } |
| case WABUsageKind_operation: { |
| kind = "operation"; |
| break; |
| } |
| } |
| |
| switch (inType) { |
| case WABUsageType_enumeration: { |
| type = "enumeration"; |
| break; |
| } |
| case WABUsageType_query: { |
| type = "query"; |
| break; |
| } |
| case WABUsageType_push: { |
| type = "push"; |
| break; |
| } |
| case WABUsageType_llq: { |
| type = "llq"; |
| break; |
| } |
| } |
| |
| switch (inEvent) { |
| case WABUsageEvent_positive: { |
| event = "positive"; |
| break; |
| } |
| case WABUsageEvent_negative: { |
| event = "negative"; |
| break; |
| } |
| case WABUsageEvent_null: { |
| event = "null"; |
| break; |
| } |
| case WABUsageEvent_error: { |
| event = "error"; |
| break; |
| } |
| |
| case WABUsageEvent_connected: { |
| event = "connected"; |
| break; |
| } |
| case WABUsageEvent_session: { |
| event = "session"; |
| break; |
| } |
| case WABUsageEvent_reset: { |
| event = "reset"; |
| break; |
| } |
| case WABUsageEvent_idledOut: { |
| event = "idledOut"; |
| break; |
| } |
| case WABUsageEvent_goAway: { |
| event = "goAway"; |
| break; |
| } |
| case WABUsageEvent_resumedGood: { |
| event = "resumedGood"; |
| break; |
| } |
| case WABUsageEvent_resumedBad: { |
| event = "resumedBad"; |
| break; |
| } |
| |
| case WABUsageEvent_succeeded: { |
| event = "succeeded"; |
| break; |
| } |
| case WABUsageEvent_rejected: { |
| event = "rejected"; |
| break; |
| } |
| case WABUsageEvent_dsoni: { |
| event = "dsoni"; |
| break; |
| } |
| case WABUsageEvent_answered: { |
| event = "answered"; |
| break; |
| } |
| } |
| |
| posted = analytics_send_event_lazy("com.apple.mDNSResponder.CacheUsage.entries", ^{ |
| xpc_object_t dict; |
| dict = xpc_dictionary_create(NULL, NULL, 0); |
| xpc_dictionary_set_string(dict, "kind", kind); |
| xpc_dictionary_set_string(dict, "type", type); |
| xpc_dictionary_set_string(dict, "event", event); |
| xpc_dictionary_set_uint64(dict, "eventCount", inEventCount); |
| return (dict); |
| }); |
| if (!posted) { |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_WARNING, "com.apple.mDNSResponder.CacheUsage.entries: Analytic not posted"); |
| } |
| } |
| } |
| |
| #endif // WAB_ANALYTICS |
| |
| #if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS) |
| // MARK: - Exported Analytics Functions |
| |
| void |
| dnssd_analytics_init(void) |
| { |
| static dispatch_once_t sInitAnalyticsOnce = 0; |
| static dispatch_queue_t sAnalyticsQueue = NULL; |
| dispatch_once(&sInitAnalyticsOnce, ^{ |
| sAnalyticsQueue = dispatch_queue_create("com.apple.mDNSResponder.analytics-reporting-queue", DISPATCH_QUEUE_SERIAL); |
| xpc_object_t criteria = xpc_dictionary_create(NULL, NULL, 0); |
| xpc_dictionary_set_bool(criteria, XPC_ACTIVITY_REPEATING, true); |
| xpc_dictionary_set_bool(criteria, XPC_ACTIVITY_ALLOW_BATTERY, true); |
| xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_DELAY, XPC_ACTIVITY_INTERVAL_1_DAY); |
| xpc_dictionary_set_int64(criteria, XPC_ACTIVITY_GRACE_PERIOD, XPC_ACTIVITY_INTERVAL_5_MIN); |
| xpc_dictionary_set_string(criteria, XPC_ACTIVITY_PRIORITY, XPC_ACTIVITY_PRIORITY_MAINTENANCE); |
| |
| xpc_activity_register("com.apple.mDNSResponder.analytics.daily", criteria, ^(xpc_activity_t activity) { |
| if (xpc_activity_should_defer(activity)) { |
| if (xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_DEFER)) { |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_DEFAULT, "com.apple.mDNSResponder.analytics.daily: Asked to defer"); |
| } else { |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_ERROR, "com.apple.mDNSResponder.analytics.daily: Asked to defer but failed to set state"); |
| } |
| } else { |
| dispatch_async(sAnalyticsQueue, ^{ |
| #if MDNSRESPONDER_SUPPORTS(APPLE, ANALYTICS) |
| KQueueLock(); |
| mDNS_Lock(&mDNSStorage); |
| #if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS) |
| _post_cache_request_counts(); |
| _post_cache_usage_counts(); |
| #endif // CACHE_ANALYTICS |
| #if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS) |
| _post_dns_query_info(); |
| #endif // DNS_ANALYTICS |
| #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_ASSIST_ANALYTICS) |
| _post_unicast_assist(); |
| #endif // UNICAST_ASSIST_ANALYTICS |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_DEFAULT, "com.apple.mDNSResponder.analytics.daily Complete"); |
| mDNS_Unlock(&mDNSStorage); |
| KQueueUnlock("Analytics Update"); |
| #endif // ANALYTICS |
| }); |
| if (!xpc_activity_set_state(activity, XPC_ACTIVITY_STATE_DONE)) { |
| LogRedact(MDNS_LOG_CATEGORY_ANALYTICS, MDNS_LOG_ERROR, "com.apple.mDNSResponder.analytics.daily: Analytics XPC_ACTIVITY_STATE_DONE failed"); |
| } |
| } |
| }); |
| MDNS_DISPOSE_XPC(criteria); |
| }); |
| } |
| |
| void |
| dnssd_analytics_log(int fd) |
| { |
| #if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS) |
| LogToFD(fd, "---- DNS Cache Analytics -----"); |
| LogToFD(fd, "---- Unicast Requests"); |
| LogToFD(fd, "Cache Hit: %llu", sCacheRequest_UnicastHitCount); |
| LogToFD(fd, "Cache Miss: %llu", sCacheRequest_UnicastMissCount); |
| LogToFD(fd, "---- Unicast Usage"); |
| LogToFD(fd, "Cache Hit: %llu", sCacheUsage_UnicastHitCount); |
| LogToFD(fd, "Cache Miss: %llu", sCacheUsage_UnicastMissCount); |
| LogToFD(fd, "---- Multicast Requests"); |
| LogToFD(fd, "Cache Hit: %llu", sCacheRequest_MulticastHitCount); |
| LogToFD(fd, "Cache Miss: %llu", sCacheRequest_MulticastMissCount); |
| LogToFD(fd, "---- Multicast Usage"); |
| LogToFD(fd, "Cache Hit: %llu", sCacheUsage_MulticastHitCount); |
| LogToFD(fd, "Cache Miss: %llu", sCacheUsage_MulticastMissCount); |
| #endif // CACHE_ANALYTICS |
| #if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS) |
| LogToFD(fd, "---- DNS Query Analytics -----"); |
| for (uint8_t i = 0 ; i < e_index_count ; i++ ) { |
| if (s_dns_analytics[i].latency_count > 0) { |
| LogToFD(fd, "---- Network: %s\n Transport: %s", _index_to_network_string(i), _index_to_transport_string(i)); |
| LogToFD(fd, "Latency: %llums", s_dns_analytics[i].latency_total / s_dns_analytics[i].latency_count); |
| LogToFD(fd, "Query Bytes: %llu", s_dns_analytics[i].query_bytes); |
| LogToFD(fd, "Reply Bytes: %llu", s_dns_analytics[i].reply_bytes); |
| LogToFD(fd, "---- V4"); |
| LogToFD(fd, "Queries: %llu", s_dns_analytics[i].v4.queries); |
| LogToFD(fd, "Reply Pos: %llu", s_dns_analytics[i].v4.reply_pos); |
| LogToFD(fd, "Reply Neg: %llu", s_dns_analytics[i].v4.reply_neg); |
| LogToFD(fd, "---- V6"); |
| LogToFD(fd, "Queries: %llu", s_dns_analytics[i].v6.queries); |
| LogToFD(fd, "Reply Pos: %llu", s_dns_analytics[i].v6.reply_pos); |
| LogToFD(fd, "Reply Neg: %llu", s_dns_analytics[i].v6.reply_neg); |
| LogToFD(fd, "---- HTTPS"); |
| LogToFD(fd, "Queries: %llu", s_dns_analytics[i].https.queries); |
| LogToFD(fd, "Reply Pos: %llu", s_dns_analytics[i].https.reply_pos); |
| LogToFD(fd, "Reply Neg: %llu", s_dns_analytics[i].https.reply_neg); |
| } |
| } |
| #endif // DNS_ANALYTICS |
| #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_ASSIST_ANALYTICS) |
| LogToFD(fd, "---- Unicast Assist"); |
| LogToFD(fd, "Assist Unicast: %llu", sUnicastAssist_UnicastCount); |
| LogToFD(fd, "Assist Multicast: %llu", sUnicastAssist_MulticastCount); |
| LogToFD(fd, "Non-assist Unicast: %llu", sNonUnicastAssist_UnicastCount); |
| LogToFD(fd, "Non-assist Multicast: %llu", sNonUnicastAssist_MulticastCount); |
| #endif // UNICAST_ASSIST_ANALYTICS |
| } |
| |
| #endif // ANALYTICS |