3
3
#include < iostream>
4
4
#include < iterator>
5
5
#include < fstream>
6
+ #include < chrono>
6
7
7
8
#include " LogManager.hpp"
8
9
@@ -71,6 +72,40 @@ const char* defaultConfig = static_cast<const char *> JSON_CONFIG
71
72
}
72
73
);
73
74
75
+ // Mock function that performs random selection of destination URL. 1DS SDK does not define how the app needs to perform
76
+ // the region determination. Products should use MSGraph API, OCPS, or other remote config provisioning sources, such as
77
+ // ECS: https://learn.microsoft.com/en-us/deployedge/edge-configuration-and-experiments - in order to identify what 1DS
78
+ // collector to use for specific Enterprise or Consumer end-user telemetry uploads. Note that the EUDB URL determination
79
+ // is performed asynchronously and could take a few seconds. EUDB URL for Enterprise applications may be cached
80
+ // in app-specific configuration storage. 1DS SDK does not provide a feature to cache the data collection URL used for
81
+ // a previous session.
82
+ //
83
+ // Note that this function to determine the URL is called once, early at boot.
84
+ std::string GetEudbCollectorUrl ()
85
+ {
86
+ const auto randSeed = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now ().time_since_epoch ()).count ();
87
+ srand (static_cast <unsigned >(randSeed));
88
+ return (rand () % 2 ) ? " https://us-mobile.events.data.microsoft.com/OneCollector/1.0/" : " https://eu-mobile.events.data.microsoft.com/OneCollector/1.0/" ;
89
+ }
90
+
91
+ void UpdateUploadUrl ()
92
+ {
93
+ printf (" Performing collector URL detection...\n " );
94
+ // Transmissions must be paused prior to adjusting the URL.
95
+ LogManager::PauseTransmission ();
96
+
97
+ // Obtain a reference to current configuration.
98
+ auto & config = LogManager::GetLogConfiguration ();
99
+
100
+ // Update configuration in-place. This is done once after the regional data collection URL is determined.
101
+ config[CFG_STR_COLLECTOR_URL] = GetEudbCollectorUrl ();
102
+
103
+ // Resume transmission once EUDB collector URL detection is obtained. In case if EUDB collector determination fails, only required
104
+ // system diagnostics data containing no EUPI MAY be uploaded to global data collection endpoint. It is up to product teams to
105
+ // decide what strategy works best for their product.
106
+ LogManager::ResumeTransmission ();
107
+ }
108
+
74
109
int main (int argc, char *argv[])
75
110
{
76
111
// 2nd (optional) parameter - path to custom SDK configuration
@@ -87,24 +122,43 @@ int main(int argc, char *argv[])
87
122
88
123
// LogManager configuration
89
124
auto & config = LogManager::GetLogConfiguration ();
90
- config = MAT::FromJSON (jsonConfig);
125
+ auto customLogConfig = MAT::FromJSON (jsonConfig);
126
+ config = customLogConfig; // Assignment operation COLLATES the default + custom config
91
127
92
128
// LogManager initialization
93
129
ILogger *logger = LogManager::Initialize ();
94
- bool utcActive = (bool )(config[CFG_STR_UTC][CFG_BOOL_UTC_ACTIVE]);
130
+ const bool utcActive = (bool )(config[CFG_STR_UTC][CFG_BOOL_UTC_ACTIVE]);
95
131
96
132
printf (" Running in %s mode...\n " , (utcActive) ? " UTC" : " direct upload" );
97
133
if (utcActive)
98
134
{
99
- printf (" UTC provider group Id: %s\n " , ( const char *) (config[CFG_STR_UTC][CFG_STR_PROVIDER_GROUP_ID]));
100
- printf (" UTC large payloads: %s\n " , (( bool ) (config[CFG_STR_UTC][CFG_BOOL_UTC_LARGE_PAYLOADS]) ) ? " supported" : " not supported" );
135
+ printf (" UTC provider group Id: %s\n " , static_cast < const char *> (config[CFG_STR_UTC][CFG_STR_PROVIDER_GROUP_ID]));
136
+ printf (" UTC large payloads: %s\n " , static_cast < bool > (config[CFG_STR_UTC][CFG_BOOL_UTC_LARGE_PAYLOADS]) ? " supported" : " not supported" );
101
137
}
102
138
else
103
139
{
104
- printf (" Collector URL: %s\n " , (const char *)(config[CFG_STR_COLLECTOR_URL]));
140
+ // LogManager::ILogConfiguration[CFG_STR_COLLECTOR_URL] defaults to global URL.
141
+ //
142
+ // If app-provided JSON config is empty on start, means the app intended to asynchronously
143
+ // obtain the data collection URL for EUDB compliance. App subsequently sets an empty URL -
144
+ // by assigning an empty value to the log manager instance CFG_STR_COLLECTOR_URL. At this
145
+ // point the Uploads are not performed until EUDB-compliant endpoint URL is obtained.
146
+ //
147
+ // Note that since ILogConfiguration configuration tree does not provide a thread-safety
148
+ // guarantee between the main thread and SDK uploader thread(s), adjusting the upload
149
+ // parameters, e.g. URL or timers, requires the app to pause transmission, adjust params,
150
+ // then resume transmission.
151
+ //
152
+ if (!customLogConfig.HasConfig (CFG_STR_COLLECTOR_URL))
153
+ {
154
+ // If configuration provided as a parameter does not contain the URL
155
+ UpdateUploadUrl ();
156
+ }
157
+ const std::string url = config[CFG_STR_COLLECTOR_URL];
158
+ printf (" Collector URL: %s\n " , url.c_str ());
105
159
}
106
160
107
- printf (" Token (iKey): %s\n " , ( const char *) (config[CFG_STR_PRIMARY_TOKEN]));
161
+ printf (" Token (iKey): %s\n " , static_cast < const char *> (config[CFG_STR_PRIMARY_TOKEN]));
108
162
109
163
#if 0
110
164
// Code example that shows how to convert ILogConfiguration to JSON
0 commit comments