private async Task <string> LoadInstrumentationKey() { //if the AI key is specified in the Telimena Portal, it should override the local one //however, checking if it is specified in Telimena will take time, and we are inside a constructor here - we don't want to block string key = null; try { using (HttpClient client = new HttpClient() { BaseAddress = this.telimenaProperties.TelemetryApiBaseUrl }) { HttpResponseMessage response = await client.GetAsync(ApiRoutes.GetInstrumentationKey(this.telimenaProperties.TelemetryKey)); key = await response.Content.ReadAsStringAsync(); response.EnsureSuccessStatusCode(); return(key?.Trim('"')); } } catch (Exception ex) { TelemetryDebugWriter.WriteError($"Error while loading instrumentation key. Error: {ex}. Response: {key}"); return(null); } }
public async Task <string> GetUserTrackingSettings(Guid telemetryKey) { string stringified = null; try { using (HttpClient client = new HttpClient() { BaseAddress = this.baseUrl }) { HttpResponseMessage response = await client.GetAsync(ApiRoutes.GetTelemetrySettings(telemetryKey)); stringified = await response.Content.ReadAsStringAsync(); response.EnsureSuccessStatusCode(); return(stringified); } } catch (Exception ex) { TelemetryDebugWriter.WriteError($"Error while loading instrumentation key. Error: {ex}. Response: {stringified}"); return(null); } }
private void LogResult(HttpWebResponseWrapper response, string endpoint) { if (response.StatusCode < 200 || response.StatusCode >= 300) { TelemetryDebugWriter.WriteLine($"Error while transmitting telemetry to {endpoint}. Status code: {response.StatusCode}. Description: [{response.StatusDescription}]. {response.Content}"); } }
public void Track(ITelemetry telemetry) { // TALK TO YOUR TEAM MATES BEFORE CHANGING THIS. // This method needs to be public so that we can build and ship new telemetry types without having to ship core. // It is hidden from intellisense to prevent customer confusion. if (this.IsEnabled()) { this.Initialize(telemetry); if (string.IsNullOrEmpty(telemetry.Context.InstrumentationKey)) { TelemetryDebugWriter.WriteTelemetry(telemetry); return; } // If someone created configuration from scratch and forgot to initialize channel - use default if (this.configuration.TelemetryChannel == null) { this.configuration.TelemetryChannel = new InMemoryChannel(); } // invokes the Process in the first processor in the chain this.configuration.TelemetryProcessorChain.Process(telemetry); #if !CORE_PCL // logs rich payload ETW event for any partners to process it RichPayloadEventSource.Log.Process(telemetry); #endif } }
public TelemetryClient GetClient() { try { lock (this.telemetryClientBuildingLock) { TelemetryConfiguration config = TelemetryConfiguration.Active; this.LoadTelemetryChannel(config); this.LoadInitializers(config); var client = new TelemetryClient(config); this.InitializeContext(client); if (this.properties.InstrumentationKey != null) { config.InstrumentationKey = this.properties.InstrumentationKey; client.InstrumentationKey = this.properties.InstrumentationKey; } return(client); } } catch (Exception e) { TelemetryDebugWriter.WriteLine($"Failed to load {nameof(TelemetryClient)}. Error: {e}"); return(null); } }
private void LogResult(HttpWebResponseWrapper response) { if (response.StatusCode < 200 || response.StatusCode >= 300) { TelemetryDebugWriter.WriteLine($"Status code: {response.StatusCode}. Description: [{response.StatusDescription}]. {response.Content}"); } }
internal Telimena(ITelimenaStartupInfo startupInfo) { try { this.SetConnectionSecurityProtocol(); this.propertiesInternal = new TelimenaProperties(startupInfo); this.Locator = new Locator(this.Properties.StaticProgramInfo); this.telemetryModule = new TelemetryModule(this.Properties); this.updates = new UpdatesModule(this); this.httpClient = new TelimenaHttpClient(new HttpClient { BaseAddress = this.propertiesInternal.StartupInfo.TelemetryApiBaseUrl }); this.Messenger = new Messenger(this.Serializer, this.httpClient); ((TelemetryModule)this.telemetryModule).InitializeTelemetryClient(); if (startupInfo.RegisterUnhandledExceptionsTracking) { AppDomain.CurrentDomain.UnhandledException += this.CurrentDomain_UnhandledException; } } catch (Exception e) { TelemetryDebugWriter.WriteLine($"Error while initializing {nameof(Telimena)}. Error: {e}"); //above all, we don't want to throw errors in client apps. //No telemetry is better than boom. throw; } }
private void StoreSettings(UserTrackingSettings settings) { try { string stringified = this.serializer.Serialize(settings); string path = Path.Combine(this.locator.GetWorkingDirectory().FullName, TrackingSettingsFileName); File.WriteAllText(path, stringified); } catch (Exception ex) { TelemetryDebugWriter.WriteError("Error while storing user tracking settings: " + ex); } }
private UserTrackingSettings Deserialize(string serializedSettings) { if (string.IsNullOrEmpty(serializedSettings)) { return(null); } try { return(this.serializer.Deserialize <UserTrackingSettings>(serializedSettings)); } catch (Exception ex) { TelemetryDebugWriter.WriteError("Error while deserializing user tracking settings: " + ex); return(null); } }
private UserTrackingSettings GetStoredSettings() { try { string path = Path.Combine(this.locator.GetWorkingDirectory().FullName, TrackingSettingsFileName); if (File.Exists(path)) { var stringified = File.ReadAllText(path); return(this.serializer.Deserialize <UserTrackingSettings>(stringified)); } } catch (Exception ex) { TelemetryDebugWriter.WriteError("Error while restoring user tracking settings: " + ex); } return(null); }
/// <summary> /// Process a collected telemetry item. /// </summary> /// <param name="item">A collected Telemetry item.</param> public void Process(ITelemetry item) { if (this.SamplingPercentage < 100.0 - 1.0E-12) { var samplingSupportingTelemetry = item as ISupportSampling; if (samplingSupportingTelemetry != null) { var excludedTypesHashSetRef = this.excludedTypesHashSet; var includedTypesHashSetRef = this.includedTypesHashSet; if (excludedTypesHashSetRef.Count > 0 && excludedTypesHashSetRef.Contains(item.GetType())) { if (TelemetryChannelEventSource.Log.IsVerboseEnabled) { TelemetryChannelEventSource.Log.SamplingSkippedByType(item.ToString()); } } else if (includedTypesHashSetRef.Count > 0 && !includedTypesHashSetRef.Contains(item.GetType())) { if (TelemetryChannelEventSource.Log.IsVerboseEnabled) { TelemetryChannelEventSource.Log.SamplingSkippedByType(item.ToString()); } } else if (!samplingSupportingTelemetry.SamplingPercentage.HasValue) { samplingSupportingTelemetry.SamplingPercentage = this.SamplingPercentage; if (!this.IsSampledIn(item)) { if (TelemetryChannelEventSource.Log.IsVerboseEnabled) { TelemetryChannelEventSource.Log.ItemSampledOut(item.ToString()); } TelemetryDebugWriter.WriteTelemetry(item, this.GetType().Name); return; } } } } this.Next.Process(item); }
private static Uri GetTelemetryUriFromConfig(Uri telemetryApiBaseUrl) { var setting = ConfigurationManager.AppSettings.Get(TelimenaUrlSettingsKey); if (!string.IsNullOrEmpty(setting)) { try { var uri = new Uri(setting); return(uri); } catch (Exception ex) { TelemetryDebugWriter.WriteLine($"ERROR - Cannot convert AppSetting [{setting}] to URI. Telimena will NOT WORK. Error: {ex}"); } } var path = Path.Combine(Directory.GetCurrentDirectory(), TelimenaUrlSettingsKey); if (File.Exists(path)) { var text = File.ReadAllText(path); try { var uri = new Uri(text); return(uri); } catch (Exception ex) { TelemetryDebugWriter.WriteError($"ERROR - Cannot convert content of file {path} - [{text}] to URI. Telimena will NOT WORK. Error: {ex}"); return(null); } } if (telemetryApiBaseUrl == null) { string message = $"ERROR - Telimena URL not specified. " + $"Either add AppSetting [{TelimenaUrlSettingsKey}] or create a [{TelimenaUrlSettingsKey}] file in your app working directory." + $"The setting value/file content should be JUST THE BASE URL to Telimena instance."; TelemetryDebugWriter.WriteError(message); } return(null); }
private void SetUserIdentifier(UserInfo value, string fileName, bool shared) { var directory = this.locator.GetWorkingDirectory(); if (shared) { directory = directory.Parent; } try { string filePath = Path.Combine(directory.FullName, fileName); var lines = new string[] { value.UserIdentifier, value.MachineName }; File.WriteAllLines(filePath, lines); } catch (Exception e) { //thats bad, but maybe it will succeed next time. Impact is smaller than throwing an error. TelemetryDebugWriter.WriteError($"Error while storing user identifier. Error: {e}"); } }
/// <summary> /// Process a collected telemetry item. /// </summary> /// <param name="item">A collected Telemetry item.</param> public void Process(ITelemetry item) { if (this.SamplingPercentage < 100.0 - 1.0E-12) { var samplingSupportingTelemetry = item as ISupportSampling; if (samplingSupportingTelemetry != null) { var excludedTypesHashSetRef = this.excludedTypesHashSet; if (excludedTypesHashSetRef.Count > 0 && excludedTypesHashSetRef.Contains(item.GetType())) { if (TelemetryChannelEventSource.Log.IsVerboseEnabled) { TelemetryChannelEventSource.Log.SamplingSkippedByType(item.ToString()); } } else { // set sampling percentage on telemetry item, current codebase assumes it is the only one updating SamplingPercentage. samplingSupportingTelemetry.SamplingPercentage = this.SamplingPercentage; if (!this.IsSampledIn(item)) { if (TelemetryChannelEventSource.Log.IsVerboseEnabled) { TelemetryChannelEventSource.Log.ItemSampledOut(item.ToString()); } TelemetryDebugWriter.WriteTelemetry(item, this.GetType().Name); return; } } } } this.Next.Process(item); }
/// <summary> /// Process a collected telemetry item. /// </summary> /// <param name="item">A collected Telemetry item.</param> public void Process(ITelemetry item) { double samplingPercentage = this.SamplingPercentage; //// If sampling rate is 100% and we aren't distinguishing between evaluated/unevaluated items, there is nothing to do: if (samplingPercentage >= 100.0 - 1.0E-12 && this.SampledNext.Equals(this.UnsampledNext)) { this.HandlePossibleProactiveSampling(item, samplingPercentage); return; } //// So sampling rate is not 100%, or we must evaluate further var advancedSamplingSupportingTelemetry = item as ISupportAdvancedSampling; // If someone implemented ISupportSampling and hopes that SamplingTelemetryProcessor will continue to work for them: var samplingSupportingTelemetry = advancedSamplingSupportingTelemetry ?? item as ISupportSampling; //// If null was passed in as item or if sampling not supported in general, do nothing: if (samplingSupportingTelemetry == null) { this.UnsampledNext.Process(item); return; } //// If telemetry was excluded by type, do nothing: if (advancedSamplingSupportingTelemetry != null && !this.IsSamplingApplicable(advancedSamplingSupportingTelemetry.ItemTypeFlag)) { if (TelemetryChannelEventSource.IsVerboseEnabled) { TelemetryChannelEventSource.Log.SamplingSkippedByType(item.ToString()); } this.UnsampledNext.Process(item); return; } //// If telemetry was already sampled, do nothing: bool itemAlreadySampled = samplingSupportingTelemetry.SamplingPercentage.HasValue; if (itemAlreadySampled) { this.UnsampledNext.Process(item); return; } //// Ok, now we can actually sample: samplingSupportingTelemetry.SamplingPercentage = samplingPercentage; bool isSampledIn; // if this is executed in adaptive sampling processor (rate ratio has value), // and item supports proactive sampling and was sampled in before, we'll give it more weight if (this.ProactiveSamplingPercentage.HasValue && advancedSamplingSupportingTelemetry != null && advancedSamplingSupportingTelemetry.ProactiveSamplingDecision == SamplingDecision.SampledIn) { // if current rate of proactively sampled-in telemetry is too high, ProactiveSamplingPercentage is low: // we'll sample in as much proactively sampled in items as we can (based on their sampling score) // so that we still keep target rate. // if current rate of proactively sampled-in telemetry is less that configured, ProactiveSamplingPercentage // is high - it could be > 100 - and we'll sample in all items with proactive SampledIn decision (plus some more in else branch). isSampledIn = SamplingScoreGenerator.GetSamplingScore(item) < this.ProactiveSamplingPercentage; } else { isSampledIn = SamplingScoreGenerator.GetSamplingScore(item) < samplingPercentage; } if (isSampledIn) { if (advancedSamplingSupportingTelemetry != null) { this.HandlePossibleProactiveSampling(item, samplingPercentage, advancedSamplingSupportingTelemetry); } else { this.SampledNext.Process(item); } } else { if (TelemetryChannelEventSource.IsVerboseEnabled) { TelemetryChannelEventSource.Log.ItemSampledOut(item.ToString()); } TelemetryDebugWriter.WriteTelemetry(item, nameof(SamplingTelemetryProcessor)); } }
/// <summary> /// Process a collected telemetry item. /// </summary> /// <param name="item">A collected Telemetry item.</param> public void Process(ITelemetry item) { double samplingPercentage = this.SamplingPercentage; //// If sampling rate is 100% and we aren't distinguishing between evaluated/unevaluated items, there is nothing to do: if (this.SampledNext.Equals(this.UnsampledNext) && samplingPercentage >= 100.0 - 1.0E-12) { this.SampledNext.Process(item); return; } //// So sampling rate is not 100%, or we must evaluate further //// If null was passed in as item or if sampling not supported in general, do nothing: var samplingSupportingTelemetry = item as ISupportSampling; if (samplingSupportingTelemetry == null) { this.UnsampledNext.Process(item); return; } //// If telemetry was excluded by type, do nothing: if (!this.IsSamplingApplicable(item.GetType())) { if (TelemetryChannelEventSource.IsVerboseEnabled) { TelemetryChannelEventSource.Log.SamplingSkippedByType(item.ToString()); } this.UnsampledNext.Process(item); return; } //// If telemetry was already sampled, do nothing: bool itemAlreadySampled = samplingSupportingTelemetry.SamplingPercentage.HasValue; if (itemAlreadySampled) { this.UnsampledNext.Process(item); return; } //// Ok, now we can actually sample: samplingSupportingTelemetry.SamplingPercentage = samplingPercentage; bool isSampledIn = SamplingScoreGenerator.GetSamplingScore(item) < samplingPercentage; if (isSampledIn) { this.SampledNext.Process(item); } else { if (TelemetryChannelEventSource.IsVerboseEnabled) { TelemetryChannelEventSource.Log.ItemSampledOut(item.ToString()); } TelemetryDebugWriter.WriteTelemetry(item, this.GetType().Name); } }
/// <summary> /// Initializes/Adds operation id to the existing telemetry item. /// </summary> /// <param name="telemetryItem">Target telemetry item to add operation id.</param> public void Initialize(ITelemetry telemetryItem) { try { var itemContext = telemetryItem.Context.Operation; var telemetryProp = telemetryItem as ISupportProperties; bool isActivityAvailable = false; isActivityAvailable = ActivityExtensions.TryRun(() => { var currentActivity = Activity.Current; if (currentActivity != null) { if (string.IsNullOrEmpty(itemContext.Id)) { itemContext.Id = currentActivity.RootId; if (string.IsNullOrEmpty(itemContext.ParentId)) { itemContext.ParentId = currentActivity.Id; } foreach (var baggage in currentActivity.Baggage) { if (telemetryProp != null && !telemetryProp.Properties.ContainsKey(baggage.Key)) { telemetryProp.Properties.Add(baggage); } } } string operationName = currentActivity.GetOperationName(); if (string.IsNullOrEmpty(itemContext.Name) && !string.IsNullOrEmpty(operationName)) { itemContext.Name = operationName; } } }); if (!isActivityAvailable) { if (string.IsNullOrEmpty(itemContext.ParentId) || string.IsNullOrEmpty(itemContext.Id) || string.IsNullOrEmpty(itemContext.Name)) { var parentContext = CallContextHelpers.GetCurrentOperationContext(); if (parentContext != null) { if (string.IsNullOrEmpty(itemContext.ParentId) && !string.IsNullOrEmpty(parentContext.ParentOperationId)) { itemContext.ParentId = parentContext.ParentOperationId; } if (string.IsNullOrEmpty(itemContext.Id) && !string.IsNullOrEmpty(parentContext.RootOperationId)) { itemContext.Id = parentContext.RootOperationId; } if (string.IsNullOrEmpty(itemContext.Name) && !string.IsNullOrEmpty(parentContext.RootOperationName)) { itemContext.Name = parentContext.RootOperationName; } if (parentContext.CorrelationContext != null) { foreach (var item in parentContext.CorrelationContext) { if (telemetryProp != null && !telemetryProp.Properties.ContainsKey(item.Key)) { telemetryProp.Properties.Add(item); } } } } } } } catch (Exception ex) { TelemetryDebugWriter.WriteLine( "Something went wrong when initializing [" + this.GetType().Name + "]. This initializer will be ignored." + ex); } }
/// <summary> /// Process a collected telemetry item. /// </summary> /// <param name="item">A collected Telemetry item.</param> public void Process(ITelemetry item) { double samplingPercentage = this.SamplingPercentage; //// If sampling rate is 100% and we aren't distinguishing between evaluated/unevaluated items, there is nothing to do: if (samplingPercentage >= 100.0 - 1.0E-12 && this.SampledNext.Equals(this.UnsampledNext)) { this.HandlePossibleProactiveSampling(item, samplingPercentage); return; } //// So sampling rate is not 100%, or we must evaluate further var advancedSamplingSupportingTelemetry = item as ISupportAdvancedSampling; // If someone implemented ISupportSampling and hopes that SamplingTelemetryProcessor will continue to work for them: var samplingSupportingTelemetry = advancedSamplingSupportingTelemetry ?? item as ISupportSampling; //// If null was passed in as item or if sampling not supported in general, do nothing: if (samplingSupportingTelemetry == null) { this.UnsampledNext.Process(item); return; } //// If telemetry was excluded by type, do nothing: if (advancedSamplingSupportingTelemetry != null && !this.IsSamplingApplicable(advancedSamplingSupportingTelemetry.ItemTypeFlag)) { if (TelemetryChannelEventSource.IsVerboseEnabled) { TelemetryChannelEventSource.Log.SamplingSkippedByType(item.ToString()); } this.UnsampledNext.Process(item); return; } //// If telemetry was already sampled, do nothing: bool itemAlreadySampled = samplingSupportingTelemetry.SamplingPercentage.HasValue; if (itemAlreadySampled) { this.UnsampledNext.Process(item); return; } //// Ok, now we can actually sample: samplingSupportingTelemetry.SamplingPercentage = samplingPercentage; bool isSampledIn = SamplingScoreGenerator.GetSamplingScore(item) < samplingPercentage; if (isSampledIn) { if (advancedSamplingSupportingTelemetry != null) { this.HandlePossibleProactiveSampling(item, samplingPercentage, advancedSamplingSupportingTelemetry); } else { this.SampledNext.Process(item); } } else { if (TelemetryChannelEventSource.IsVerboseEnabled) { TelemetryChannelEventSource.Log.ItemSampledOut(item.ToString()); } TelemetryDebugWriter.WriteTelemetry(item, nameof(SamplingTelemetryProcessor)); } }