66#include " duckdb/main/extension_helper.hpp"
77#include " duckdb/main/config.hpp"
88#include < cstdlib>
9+ #include < future>
910using namespace duckdb_yyjson ; // NOLINT
1011
1112namespace duckdb
1213{
1314
14- static constexpr const char *TARGET_URL = " https://duckdb-in.query-farm.services/" ;
15-
16- // Function to send the actual HTTP request
17- static void sendHTTPRequest (shared_ptr<DatabaseInstance> db, std::string json_body)
18- {
19- HTTPHeaders headers;
20- headers.Insert (" Content-Type" , " application/json" );
21-
22- auto &http_util = HTTPUtil::Get (*db);
23- unique_ptr<HTTPParams> params;
24- auto target_url = string (TARGET_URL);
25- params = http_util.InitializeParameters (*db, target_url);
26-
27- PostRequestInfo post_request (target_url,
28- headers,
29- *params,
30- reinterpret_cast <const_data_ptr_t >(json_body.data ()),
31- json_body.size ());
32- try
33- {
34- auto response = http_util.Request (post_request);
35- }
36- catch (const std::exception &e)
37- {
38- // ignore all errors.
39- }
40-
41- return ;
42- }
43-
44- // Public function to start the request thread
45- static void sendRequestAsync (shared_ptr<DatabaseInstance> db, std::string &json_body)
46- {
47- std::thread request_thread (sendHTTPRequest, db, std::move (json_body));
48- request_thread.detach (); // Let the thread run independently
49- }
50-
51- INTERNAL_FUNC void QueryFarmSendTelemetry (ExtensionLoader &loader, shared_ptr<DatabaseInstance> db, const string &extension_name, const string &extension_version)
52- {
53- const char *opt_out = std::getenv (" QUERY_FARM_TELEMETRY_OPT_OUT" );
54- if (opt_out != nullptr )
55- {
56- return ;
57- }
58-
59- auto &dbconfig = DBConfig::GetConfig (*db);
60- auto old_value = dbconfig.options .autoinstall_known_extensions ;
61- dbconfig.options .autoinstall_known_extensions = false ;
62- try
63- {
64- ExtensionHelper::AutoLoadExtension (loader.GetDatabaseInstance (), " httpfs" );
65- }
66- catch (...)
67- {
68- dbconfig.options .autoinstall_known_extensions = old_value;
69- return ;
70- }
71-
72- dbconfig.options .autoinstall_known_extensions = old_value;
73- if (!loader.GetDatabaseInstance ().ExtensionIsLoaded (" httpfs" ))
74- {
75- return ;
76- }
77-
78- // Initialize the telemetry sender
79- auto doc = yyjson_mut_doc_new (nullptr );
80-
81- auto result_obj = yyjson_mut_obj (doc);
82- yyjson_mut_doc_set_root (doc, result_obj);
83-
84- auto user_agent = " query-farm/20250915" ;
85- auto platform = DuckDB::Platform ();
86- yyjson_mut_obj_add_str (doc, result_obj, " extension_name" , extension_name.c_str ());
87- yyjson_mut_obj_add_str (doc, result_obj, " extension_version" , extension_version.c_str ());
88- yyjson_mut_obj_add_str (doc, result_obj, " user_agent" , user_agent);
89- yyjson_mut_obj_add_str (doc, result_obj, " duckdb_platform" , platform.c_str ());
90- yyjson_mut_obj_add_str (doc, result_obj, " duckdb_library_version" , DuckDB::LibraryVersion ());
91- yyjson_mut_obj_add_str (doc, result_obj, " duckdb_release_codename" , DuckDB::ReleaseCodename ());
92- yyjson_mut_obj_add_str (doc, result_obj, " duckdb_source_id" , DuckDB::SourceID ());
93-
94- size_t telemetry_len;
95- auto telemetry_data = yyjson_mut_val_write_opts (
96- result_obj,
97- YYJSON_WRITE_ALLOW_INF_AND_NAN,
98- NULL , &telemetry_len, nullptr );
99-
100- if (telemetry_data == nullptr )
101- {
102- throw SerializationException (" Failed to serialize telemetry data." );
103- }
104-
105- auto telemetry_string = string (telemetry_data, (size_t )telemetry_len);
106-
107- // Send request asynchronously
108- sendRequestAsync (db, telemetry_string);
109- }
110-
111- }
15+ namespace
16+ {
17+
18+ // Function to send the actual HTTP request
19+ void sendHTTPRequest (shared_ptr<DatabaseInstance> db, char *json_body, size_t json_body_size)
20+ {
21+ const string TARGET_URL (" https://duckdb-in.query-farm.services/" );
22+
23+ HTTPHeaders headers;
24+ headers.Insert (" Content-Type" , " application/json" );
25+
26+ auto &http_util = HTTPUtil::Get (*db);
27+ unique_ptr<HTTPParams> params = http_util.InitializeParameters (*db, TARGET_URL);
28+
29+ PostRequestInfo post_request (TARGET_URL, headers, *params, reinterpret_cast <const_data_ptr_t >(json_body),
30+ json_body_size);
31+ try
32+ {
33+ auto response = http_util.Request (post_request);
34+ }
35+ catch (const std::exception &e)
36+ {
37+ // ignore all errors.
38+ }
39+
40+ free (json_body);
41+ return ;
42+ }
43+
44+ } // namespace
45+
46+ INTERNAL_FUNC void QueryFarmSendTelemetry (ExtensionLoader &loader, const string &extension_name,
47+ const string &extension_version)
48+ {
49+ const char *opt_out = std::getenv (" QUERY_FARM_TELEMETRY_OPT_OUT" );
50+ if (opt_out != nullptr )
51+ {
52+ return ;
53+ }
54+
55+ auto &dbconfig = DBConfig::GetConfig (loader.GetDatabaseInstance ());
56+ auto old_value = dbconfig.options .autoinstall_known_extensions ;
57+ dbconfig.options .autoinstall_known_extensions = false ;
58+ try
59+ {
60+ ExtensionHelper::AutoLoadExtension (loader.GetDatabaseInstance (), " httpfs" );
61+ }
62+ catch (...)
63+ {
64+ dbconfig.options .autoinstall_known_extensions = old_value;
65+ return ;
66+ }
67+
68+ dbconfig.options .autoinstall_known_extensions = old_value;
69+ if (!loader.GetDatabaseInstance ().ExtensionIsLoaded (" httpfs" ))
70+ {
71+ return ;
72+ }
73+
74+ // Initialize the telemetry sender
75+ auto doc = yyjson_mut_doc_new (nullptr );
76+
77+ auto result_obj = yyjson_mut_obj (doc);
78+ yyjson_mut_doc_set_root (doc, result_obj);
79+
80+ auto platform = DuckDB::Platform ();
81+
82+ yyjson_mut_obj_add_str (doc, result_obj, " extension_name" , extension_name.c_str ());
83+ yyjson_mut_obj_add_str (doc, result_obj, " extension_version" , extension_version.c_str ());
84+ yyjson_mut_obj_add_str (doc, result_obj, " user_agent" , " query-farm/20251011" );
85+ yyjson_mut_obj_add_str (doc, result_obj, " duckdb_platform" , platform.c_str ());
86+ yyjson_mut_obj_add_str (doc, result_obj, " duckdb_library_version" , DuckDB::LibraryVersion ());
87+ yyjson_mut_obj_add_str (doc, result_obj, " duckdb_release_codename" , DuckDB::ReleaseCodename ());
88+ yyjson_mut_obj_add_str (doc, result_obj, " duckdb_source_id" , DuckDB::SourceID ());
89+
90+ size_t telemetry_len;
91+ auto telemetry_data =
92+ yyjson_mut_val_write_opts (result_obj, YYJSON_WRITE_ALLOW_INF_AND_NAN, NULL , &telemetry_len, nullptr );
93+
94+ if (telemetry_data == nullptr )
95+ {
96+ throw SerializationException (" Failed to serialize telemetry data." );
97+ }
98+
99+ yyjson_mut_doc_free (doc);
100+
101+ #ifndef __EMSCRIPTEN__
102+ [[maybe_unused]] auto _ = std::async (
103+ std::launch::async, [db_ptr = loader.GetDatabaseInstance ().shared_from_this (), json = telemetry_data,
104+ len = telemetry_len]() mutable
105+ { sendHTTPRequest (std::move (db_ptr), json, len); });
106+ #else
107+ sendHTTPRequest (loader.GetDatabaseInstance ().shared_from_this (), telemetry_data, telemetry_len);
108+ #endif
109+ }
110+
111+ } // namespace duckdb
0 commit comments