#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE #include "Metrics.h" #include "Batch.h" #include "esp_event.h" #include "esp_log.h" #include "esp_netif.h" #include "esp_ota_ops.h" #include "esp_system.h" #include "esp_tls.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "nvs_flash.h" #include "tools.h" #include #include #include #include #include #include #include "cJSON.h" #include "freertos/timers.h" #include "network_manager.h" #include "platform_config.h" static const char* TAG = "metrics"; #if CONFIG_WITH_METRICS extern bool is_network_connected(); #define METRICS_CLIENT_ID_LEN 50 #define MAX_HTTP_RECV_BUFFER 512 static bool metrics_usage_gen = false; static uint32_t metrics_usage_gen_time = 0; #ifndef METRICS_API_KEY #pragma message "Metrics API key needs to be passed from the environment" #define METRICS_API_KEY "ZZZ" #endif static const char* metrics_api_key = static const char* parms_str = "params"; static const char* properties_str = "properties"; static const char* user_properties_str = "user_properties"; static const char* items_str = "items"; static const char* quantity_str = "quantity"; static const char* metrics_url = "https://app.posthog.com"; static TimerHandle_t timer; extern cJSON* get_cmd_list(); Metrics::Batch batch; static void metrics_timer_cb(void* timer_id) { if (batch.has_events()) { if (!is_network_connected()) { ESP_LOGV(TAG, "Network not connected. can't flush"); } else { ESP_LOGV(TAG, "Pushing events"); batch.push(); } } if (gettime_ms() > metrics_usage_gen_time && !metrics_usage_gen) { metrics_usage_gen = true; ESP_LOGV(TAG, "Generate command list to pull features"); cJSON* cmdlist = get_cmd_list(); dump_json_content("generated cmd list", cmdlist, ESP_LOG_VERBOSE); cJSON_Delete(cmdlist); } } void metrics_init() { ESP_LOGV(TAG, "Initializing metrics"); batch.configure(metrics_api_key, metrics_url); if (!timer) { ESP_LOGE(TAG, "Metrics Timer failure"); } else { ESP_LOGV(TAG, "Starting timer"); xTimerStart(timer, portMAX_DELAY); } // set a 20 seconds delay before generating the // features so the system has time to boot metrics_usage_gen_time = gettime_ms() + 20000; } void metrics_event_playback(const char* source) { ESP_LOGV(TAG, "Playback event: %s", source); auto event = batch.add_event("play").add_property("source", source); } void metrics_event_boot(const char* partition) { ESP_LOGV(TAG, "Boot event %s", partition); auto event = batch.add_event("start"); event.add_property("partition", partition); } void metrics_add_feature_variant(const char* name, const char* format, ...) { va_list args; ESP_LOGV(TAG, "Feature %s", name); va_start(args, format); // Determine the required buffer size int size = vsnprintf(nullptr, 0, format, args); va_end(args); // Reset the va_list // Allocate buffer and format the string std::vector buffer(size + 1); // +1 for the null-terminator va_start(args, format); vsnprintf(buffer.data(), buffer.size(), format, args); va_end(args); // Now buffer.data() contains the formatted string batch.add_feature_variant_event(name, buffer.data()); } void metrics_add_feature(const char* name, bool active) { ESP_LOGV(TAG, "Adding feature %s: %s", name, active ? "ACTIVE" : "INACTIVE"); batch.add_remove_feature_event(name, active); } void metrics_event(const char* name) { ESP_LOGV(TAG, "Adding Event %s", name); batch.add_event(name); } #else static const char * not_enabled = " - (metrics not enabled, this is just marking where the call happens)"; void metrics_init(){ #pragma message("Metrics disabled") ESP_LOGD(TAG,"Metrics init%s",not_enabled); } void metrics_event_boot(const char* partition){ ESP_LOGD(TAG,"Metrics Event Boot from partition %s%s",partition,not_enabled); } void metrics_event(const char* name){ ESP_LOGD(TAG,"Metrics Event %s%s",name,not_enabled); } void metrics_add_feature(const char* name, bool active) { ESP_LOGD(TAG,"Metrics add feature %s%s%s",name,active?"ACTIVE":"INACTIVE",not_enabled); } void metrics_add_feature_variant(const char* name, const char* format, ...){ va_list args; ESP_LOGV(TAG, "Feature %s", name); va_start(args, format); // Determine the required buffer size int size = vsnprintf(nullptr, 0, format, args); va_end(args); // Reset the va_list // Allocate buffer and format the string std::vector buffer(size + 1); // +1 for the null-terminator va_start(args, format); vsnprintf(buffer.data(), buffer.size(), format, args); va_end(args); ESP_LOGD(TAG,"Metrics add feature %s variant %s%s",name,buffer.data(),not_enabled); } #endif