Metrics.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
  2. #include "Metrics.h"
  3. #include "Batch.h"
  4. #include "esp_event.h"
  5. #include "esp_log.h"
  6. #include "esp_netif.h"
  7. #include "esp_ota_ops.h"
  8. #include "esp_system.h"
  9. #include "esp_tls.h"
  10. #include "freertos/FreeRTOS.h"
  11. #include "freertos/task.h"
  12. #include "tools.h"
  13. #include <cstdarg>
  14. #include <cstdio>
  15. #include <ctype.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <vector>
  19. #include "cJSON.h"
  20. #include "freertos/timers.h"
  21. #include "network_manager.h"
  22. // #include "Config.h"
  23. #pragma message("fixme: search for TODO below")
  24. static const char* TAG = "metrics";
  25. #if CONFIG_WITH_METRICS
  26. #define METRICS_CLIENT_ID_LEN 50
  27. #define MAX_HTTP_RECV_BUFFER 512
  28. static bool metrics_usage_gen = false;
  29. static uint32_t metrics_usage_gen_time = 0;
  30. #ifndef METRICS_API_KEY
  31. #pragma message "Metrics API key needs to be passed from the environment"
  32. #define METRICS_API_KEY "ZZZ"
  33. #endif
  34. static const char* metrics_api_key = METRICS_API_KEY;
  35. static const char* parms_str = "params";
  36. static const char* properties_str = "properties";
  37. static const char* user_properties_str = "user_properties";
  38. static const char* items_str = "items";
  39. static const char* quantity_str = "quantity";
  40. static const char* metrics_url = "https://app.posthog.com";
  41. static TimerHandle_t timer;
  42. extern cJSON* get_cmd_list();
  43. Metrics::Batch batch;
  44. static void metrics_timer_cb(void* timer_id) {
  45. if (batch.has_events()) {
  46. if (!is_network_connected()) {
  47. ESP_LOGV(TAG, "Network not connected. can't flush");
  48. } else {
  49. ESP_LOGV(TAG, "Pushing events");
  50. batch.push();
  51. }
  52. }
  53. if (gettime_ms() > metrics_usage_gen_time && !metrics_usage_gen) {
  54. metrics_usage_gen = true;
  55. ESP_LOGV(TAG, "Generate command list to pull features");
  56. cJSON* cmdlist = get_cmd_list();
  57. dump_json_content("generated cmd list", cmdlist, ESP_LOG_VERBOSE);
  58. cJSON_Delete(cmdlist);
  59. }
  60. }
  61. void metrics_init() {
  62. ESP_LOGV(TAG, "Initializing metrics");
  63. batch.configure(metrics_api_key, metrics_url);
  64. if (!timer) {
  65. ESP_LOGE(TAG, "Metrics Timer failure");
  66. } else {
  67. ESP_LOGV(TAG, "Starting timer");
  68. xTimerStart(timer, portMAX_DELAY);
  69. }
  70. // set a 20 seconds delay before generating the
  71. // features so the system has time to boot
  72. metrics_usage_gen_time = gettime_ms() + 20000;
  73. }
  74. void metrics_event_playback(const char* source) {
  75. ESP_LOGV(TAG, "Playback event: %s", source);
  76. auto event = batch.add_event("play").add_property("source", source);
  77. }
  78. void metrics_event_boot(const char* partition) {
  79. ESP_LOGV(TAG, "Boot event %s", partition);
  80. auto event = batch.add_event("start");
  81. event.add_property("partition", partition);
  82. }
  83. void metrics_add_feature_variant(const char* name, const char* format, ...) {
  84. va_list args;
  85. ESP_LOGV(TAG, "Feature %s", name);
  86. va_start(args, format);
  87. // Determine the required buffer size
  88. int size = vsnprintf(nullptr, 0, format, args);
  89. va_end(args); // Reset the va_list
  90. // Allocate buffer and format the string
  91. std::vector<char> buffer(size + 1); // +1 for the null-terminator
  92. va_start(args, format);
  93. vsnprintf(buffer.data(), buffer.size(), format, args);
  94. va_end(args);
  95. // Now buffer.data() contains the formatted string
  96. batch.add_feature_variant_event(name, buffer.data());
  97. }
  98. void metrics_add_feature(const char* name, bool active) {
  99. ESP_LOGV(TAG, "Adding feature %s: %s", name, active ? "ACTIVE" : "INACTIVE");
  100. batch.add_remove_feature_event(name, active);
  101. }
  102. void metrics_event(const char* name) {
  103. ESP_LOGV(TAG, "Adding Event %s", name);
  104. batch.add_event(name);
  105. }
  106. #else
  107. static const char * not_enabled = " - (metrics not enabled, this is just marking where the call happens)";
  108. void metrics_init(){
  109. #pragma message("Metrics disabled")
  110. ESP_LOGD(TAG,"Metrics init%s",not_enabled);
  111. }
  112. void metrics_event_boot(const char* partition){
  113. ESP_LOGD(TAG,"Metrics Event Boot from partition %s%s",partition,not_enabled);
  114. }
  115. void metrics_event(const char* name){
  116. ESP_LOGD(TAG,"Metrics Event %s%s",name,not_enabled);
  117. }
  118. void metrics_add_feature(const char* name, bool active) {
  119. ESP_LOGD(TAG,"Metrics add feature %s%s%s",name,active?"ACTIVE":"INACTIVE",not_enabled);
  120. }
  121. void metrics_add_feature_variant(const char* name, const char* format, ...){
  122. va_list args;
  123. ESP_LOGV(TAG, "Feature %s", name);
  124. va_start(args, format);
  125. // Determine the required buffer size
  126. int size = vsnprintf(nullptr, 0, format, args);
  127. va_end(args); // Reset the va_list
  128. // Allocate buffer and format the string
  129. std::vector<char> buffer(size + 1); // +1 for the null-terminator
  130. va_start(args, format);
  131. vsnprintf(buffer.data(), buffer.size(), format, args);
  132. va_end(args);
  133. ESP_LOGD(TAG,"Metrics add feature %s variant %s%s",name,buffer.data(),not_enabled);
  134. }
  135. #endif