public void AddRange_OtherIsNotEmpty_ShouldAggregate() { // Arrange var target = new Dictionary <string, int> { { "one", 5 }, { "two", 34 } }; var other = new Dictionary <string, int> { { "two", 67 }, { "three", 2 } }; // Act DictionaryExtensions.AddRange(target, other, (lhs, rhs) => lhs + rhs); // Assert target.ShouldBeEquivalentTo(new Dictionary <string, int> { { "one", 5 }, { "two", 34 + 67 }, { "three", 2 } }); }
/// <summary> /// Post an Asset event. /// Asset is the target of user task or operation, e.g., Solution, Project, File, Extension, License, Designer. /// </summary> /// <param name="telemetrySession">Telemetry Session</param> /// <param name="eventName"> /// An event name following data model schema. /// It requires that event name is a unique, not null or empty string. /// It consists of 3 parts and must follows pattern [product]/[featureName]/[entityName]. FeatureName could be a one-level feature or feature hierarchy delimited by "/". /// For examples, /// vs/platform/opensolution; /// vs/platform/editor/lightbulb/fixerror; /// </param> /// <param name="assetId"> /// Used to identify the asset. The id should be immutable in the asset life cycle, even if the status or content changes over time. /// E.g., project guid is generated during project creation and will never change. This makes it a good candidate for asset id of Project asset. /// </param> /// <param name="assetEventVersion"> /// Used for customized properties versioning. /// E.g., project asset posts event with name "vs/platform/project". /// If the event is updated, uses this parameter to increment the version. /// </param> /// <param name="properties">customized properties for this asset event.</param> /// <param name="correlatedWith"> /// Specify which events to correlate by using property <see cref="P:Coding4Fun.VisualStudio.Telemetry.TelemetryEvent.Correlation" /> /// Good candidates to correlate with <see cref="T:Coding4Fun.VisualStudio.Telemetry.AssetEvent" /> are, /// <see cref="T:Coding4Fun.VisualStudio.Telemetry.AssetEvent" /> (to build up asset hierarchy/extension.) /// </param> /// <returns>The asset event correlation.</returns> public static TelemetryEventCorrelation PostAsset(this TelemetrySession telemetrySession, string eventName, string assetId, int assetEventVersion, IDictionary <string, object> properties, TelemetryEventCorrelation[] correlatedWith = null) { CodeContract.RequiresArgumentNotNull <IDictionary <string, object> >(properties, "properties"); AssetEvent assetEvent = new AssetEvent(eventName, assetId, assetEventVersion); DictionaryExtensions.AddRange <string, object>(assetEvent.Properties, properties, true); assetEvent.Correlate(correlatedWith); telemetrySession.PostEvent(assetEvent); return(assetEvent.Correlation); }
private void Reset(TelemetrySession mainSession, TelemetryManifest newManifest, DateTimeOffset timeToReset) { if (mainSession != null && (counter > threshold || whitelistCounter > threshold)) { string value = "Unknown"; TelemetryManifest currentManifest = mainSession.EventProcessor.CurrentManifest; if (currentManifest != null) { value = currentManifest.Version; } Dictionary <string, object> dictionary = new Dictionary <string, object>(); dictionary["VS.TelemetryApi.DynamicTelemetry.Manifest.Version"] = value; dictionary["VS.TelemetryApi.DynamicTelemetry.HostName"] = mainSession.HostName; dictionary["VS.TelemetryApi.ClientSideThrottling.Threshold"] = threshold; dictionary["VS.TelemetryApi.ClientSideThrottling.TimerReset"] = resetCounter; dictionary["VS.TelemetryApi.ClientSideThrottling.BucketStart"] = bucketStartTime.UtcDateTime.ToString("MM/dd/yy H:mm:ss.fffffff", CultureInfo.InvariantCulture); if (counter > threshold) { long num = counter - threshold; TelemetryEvent telemetryEvent = new TelemetryEvent("VS/TelemetryApi/ClientSideThrottling"); DictionaryExtensions.AddRange <string, object>(telemetryEvent.Properties, (IDictionary <string, object>)dictionary, true); telemetryEvent.Properties["VS.TelemetryApi.ClientSideThrottling.TotalDropped"] = num; telemetryEvent.Properties["VS.TelemetryApi.ClientSideThrottling.Events"] = StringExtensions.Join((IEnumerable <string>)droppedEvents, ","); mainSession.PostEvent(telemetryEvent); } if (whitelistCounter > threshold) { long num2 = whitelistCounter - threshold; TelemetryEvent telemetryEvent2 = new TelemetryEvent("VS/TelemetryApi/ClientSideThrottling/NoisyWhitelist"); DictionaryExtensions.AddRange <string, object>(telemetryEvent2.Properties, (IDictionary <string, object>)dictionary, true); telemetryEvent2.Properties["VS.TelemetryApi.ClientSideThrottling.TotalNoise"] = num2; telemetryEvent2.Properties["VS.TelemetryApi.ClientSideThrottling.Events"] = StringExtensions.Join((IEnumerable <string>)noisyWhiteListEvents, ","); mainSession.PostEvent(telemetryEvent2); } } counter = 0L; whitelistCounter = 0L; bucketStartTime = timeToReset; if (newManifest != null) { if (newManifest.ThrottlingThreshold > 0) { threshold = newManifest.ThrottlingThreshold; } if (newManifest.ThrottlingTimerReset > 0.0) { resetCounter = newManifest.ThrottlingTimerReset; } } droppedEvents.Clear(); noisyWhiteListEvents.Clear(); }
/// <summary> /// Don't want to expose an interface, like IClonable publicly, so we use an internal method that clones from a ChannelEvent /// </summary> /// <returns></returns> internal TelemetryEvent CloneTelemetryEvent() { TelemetryEvent obj = new TelemetryEvent(eventName, Severity, EventType) { eventId = eventId, IsOptOutFriendly = IsOptOutFriendly, Correlation = Correlation, PostTimestamp = PostTimestamp }; DictionaryExtensions.AddRange <string, object>((IDictionary <string, object>)obj.eventProperties, (IDictionary <string, object>)eventProperties, true); obj.ReservedProperties.Clear(); DictionaryExtensions.AddRange <string, object>(obj.ReservedProperties, ReservedProperties, true); return(obj); }
/// <summary> /// Creates an event for a channel from this event and session start time. /// Note: a returned event is not a pure copy of this event. /// </summary> /// <param name="processStartTime"></param> /// <param name="sessionId"></param> /// <returns></returns> internal TelemetryEvent BuildChannelEvent(long processStartTime, string sessionId) { eventId = Guid.NewGuid(); TelemetryEvent telemetryEvent = new TelemetryEvent(eventName, Severity, EventType); telemetryEvent.IsOptOutFriendly = IsOptOutFriendly; telemetryEvent.Correlation = Correlation; foreach (KeyValuePair <string, object> allProperty in GetAllProperties(DateTime.UtcNow.Ticks, processStartTime, sessionId)) { telemetryEvent.eventProperties[allProperty.Key] = allProperty.Value; } telemetryEvent.ReservedProperties.Clear(); DictionaryExtensions.AddRange <string, object>(telemetryEvent.ReservedProperties, ReservedProperties, true); return(telemetryEvent); }
public void AddRange_ThisIsEmpty_ShiuldMerge() { // Arrange var other = new Dictionary <string, int> { { "one", 5 }, { "two", 34 } }; var target = new Dictionary <string, int>(); // Act DictionaryExtensions.AddRange(target, other, (lhs, rhs) => lhs + rhs); // Assert target.ShouldBeEquivalentTo(other); }
public void AddRange_OtherIsEmpty_DoNothing() { // Arrange var expected = new Dictionary <string, int> { { "one", 5 }, { "two", 34 } }; var target = new Dictionary <string, int>(expected); // Act DictionaryExtensions.AddRange(target, null, (lhs, rhs) => lhs + rhs); // Assert target.ShouldBeEquivalentTo(expected); }
public TelemetryManifestManager(IRemoteControlClient theRemoteControlClient, ITelemetryManifestManagerSettings theSettings, ITelemetryManifestParser theManifestParser, ITelemetryScheduler theScheduler, TelemetrySession theMainSession) { CodeContract.RequiresArgumentNotNull <ITelemetryManifestParser>(theManifestParser, "theManifestParser"); CodeContract.RequiresArgumentNotNull <ITelemetryScheduler>(theScheduler, "theScheduler"); CodeContract.RequiresArgumentNotNull <TelemetrySession>(theMainSession, "theMainSession"); manifestParser = theManifestParser; scheduler = theScheduler; scheduler.InitializeTimed(ReadInterval); mainSession = theMainSession; remoteControlClient = theRemoteControlClient; settings = theSettings; RemoteControlClient.TelemetryLogger2 = ((Action <string, IDictionary <string, object>, IDictionary <string, object> >) delegate(string eventName, IDictionary <string, object> properties, IDictionary <string, object> piiProperties) { TelemetryEvent telemetryEvent = new TelemetryEvent(eventName); DictionaryExtensions.AddRange <string, object>(telemetryEvent.Properties, properties, true); DictionaryExtensions.AddRange <string, object>(telemetryEvent.Properties, (IDictionary <string, object>)((IEnumerable <KeyValuePair <string, object> >)piiProperties).ToDictionary((Func <KeyValuePair <string, object>, string>)((KeyValuePair <string, object> p) => p.Key), (Func <KeyValuePair <string, object>, object>)((KeyValuePair <string, object> p) => new TelemetryPiiProperty(p.Value))), true); mainSession.PostEvent(telemetryEvent); }); }
/// <summary> /// Create and post an event for start point, and then create a user event for end point (but not posted.) /// </summary> /// <param name="telemetrySession">Telemetry Session</param> /// <param name="eventName"> /// An event name following data model schema. /// It requires that event name is a unique, not null or empty string. /// It consists of 3 parts and must follows pattern [product]/[featureName]/[entityName]. FeatureName could be a one-level feature or feature hierarchy delimited by "/". /// For examples, /// vs/platform/opensolution; /// vs/platform/editor/lightbulb/fixerror; /// </param> /// <param name="createNewEvent">A function to create a new event.</param> /// <param name="settings">A <see cref="T:Coding4Fun.VisualStudio.Telemetry.TelemetryScopeSettings" /> object to control the TelemetryScope behavior.</param> /// <remarks> /// Because the same event name is used by both start and end events, please don't use Start or End in event name. /// </remarks> internal TelemetryScope(TelemetrySession telemetrySession, string eventName, CreateNewEvent createNewEvent, TelemetryScopeSettings settings) { isEnded = 0; TelemetrySession = telemetrySession; Guid.NewGuid(); StartTime = DateTime.UtcNow; T val = createNewEvent(OperationStageType.Start); val.Severity = settings.Severity; val.Correlate(settings.Correlations); val.IsOptOutFriendly = settings.IsOptOutFriendly; if (settings.StartEventProperties != null) { DictionaryExtensions.AddRange <string, object>(val.Properties, settings.StartEventProperties, true); } if (settings.PostStartEvent) { TelemetrySession.PostEvent(val); } EndEvent = val; EndEvent.SetPostStartEventProperty(settings.PostStartEvent); EndEvent.StageType = OperationStageType.End; }
public void WhenSourceIsNull_ThenThrowException() { Assert.Throws <ArgumentNullException>(() => DictionaryExtensions.AddRange(null, new KeyValuePair <string, string> [0])); }