Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

This changelog will be used to generate documentation on [release notes page](http://azure.microsoft.com/documentation/articles/app-insights-release-notes-dotnet/).

## Version 2.9.0-beta3
- [Flatten IExtension and Unknown ITelemetry implementations for Rich Payload Event Source consumption](https://github.com/Microsoft/ApplicationInsights-dotnet/pull/1017)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is incorrect issue.

## Version 2.9.0-beta2
- [Remove unused reference to System.Web.Extensions](https://github.com/Microsoft/ApplicationInsights-dotnet/pull/956)
- [PageViewTelemetry](https://github.com/Microsoft/ApplicationInsights-dotnet/blob/8673ed1d15005713755e0bb9594acfe0ee00b869/src/Microsoft.ApplicationInsights/DataContracts/PageViewTelemetry.cs) now supports [ISupportMetrics](https://github.com/Microsoft/ApplicationInsights-dotnet/blob/39a5ef23d834777eefdd72149de705a016eb06b0/src/Microsoft.ApplicationInsights/DataContracts/ISupportMetrics.cs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public void SerializesUnknownTelemetryIntoCustomEventWithProperties()
TelemetryItem<EventTelemetry> data = obj.ToObject<TelemetryItem<EventTelemetry>>();

Assert.AreEqual("Microsoft.ApplicationInsights.Event", data.name);
Assert.AreEqual(JsonSerializer.EventNameForUnknownTelemetry, data.data.baseData.Name);
Assert.AreEqual(Constants.EventNameForUnknownTelemetry, data.data.baseData.Name);
Assert.AreEqual("testUser", data.tags["ai.user.id"]);
Assert.IsTrue(DateTimeOffset.TryParse(data.time, out DateTimeOffset testResult));
Assert.AreEqual(testTime, testResult);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;
using System.Collections.ObjectModel;
using Microsoft.ApplicationInsights.TestFramework;

/// <summary>
/// Tests the rich payload event source tracking.
Expand Down Expand Up @@ -81,6 +82,19 @@ public void RichPayloadEventSourceEventSentTest()
(client, item) => { client.TrackEvent((EventTelemetry)item); });
}

/// <summary>
/// Tests tracking unknown implementaiton of ITelemetry.
/// </summary>
[TestMethod]
public void RichPayloadEventSourceUnknownEventSentTest()
{
this.DoTracking(
RichPayloadEventSource.Keywords.Events,
new UnknownTelemetry() { Source = "source", Name = "name", ResponseCode = "200", Success = true }, // .NET 4.5 Event Source does not process empty values
typeof(External.EventData),
(client, item) => { client.Track((UnknownTelemetry)item); });
}

/// <summary>
/// RichPayloadEventSource does not copy GlobalProperties unless it is enabled.
/// </summary>
Expand Down Expand Up @@ -424,14 +438,18 @@ private void DoTracking(EventKeywords keywords, ITelemetry item, Type dataType,
item.Context.User.Id = "testUserId";
item.Context.Operation.Id = Guid.NewGuid().ToString();

item.Extension = new MyTestExtension { myIntField = 42, myStringField = "value" };

track(client, item);

var actualEvent = listener.Messages.FirstOrDefault();
#pragma warning disable CS0618 // Type or member is obsolete
Assert.IsTrue(item.Context.Properties.ContainsKey("globalproperty1"), "Item Properties should contain the globalproperties as its copied before serialization");
if (!(item is UnknownTelemetry)) // Global properties are copied directly into output properties for unknown telemetry
{
Assert.IsTrue(item.Context.Properties.ContainsKey("globalproperty1"), "Item Properties should contain the globalproperties as its copied before serialization");
}
#pragma warning restore CS0618 // Type or member is obsolete

var actualEvent = listener.Messages.FirstOrDefault();

Assert.IsNotNull(actualEvent);
Assert.AreEqual(client.InstrumentationKey, actualEvent.Payload[0]);

Expand Down Expand Up @@ -465,20 +483,43 @@ private void DoTracking(EventKeywords keywords, ITelemetry item, Type dataType,
{
object[] properties = (object[])((IDictionary<string, object>)actualEvent.Payload[2])["properties"];
#pragma warning disable CS0618 // Type or member is obsolete
if (!(item is PerformanceCounterTelemetry))
if (item is PerformanceCounterTelemetry)
#pragma warning restore CS0618 // Type or member is obsolete
{
// There should be 3 entries in properties
// There should be 6 entries in properties
// 1. from item's ISupportProperties.Properties
// 2. from item context.GlobalProperties
// 3. from item context.Properties
// 4. from myInfField in item's Extension
// 5. from myStringField in item's Extension
// 6. PerfCounter name is a custom property.
Assert.AreEqual(6, properties.Length);
}
else if (item is UnknownTelemetry)
{
// There should be 11 entries in properties, all fields are flattened into properties
// 1. from item's ISupportProperties.Properties
// 2. from item context.GlobalProperties
// 3. from item context.Properties
Assert.AreEqual(3, properties.Length);
// 3. from item context.Properties
// 4. from myInfField in item's Extension
// 5. from myStringField in item's Extension
// 6. Unknown Telemetry name.
// 7. Unknown Telemetry id
// 8. Unknown Telemetry responseCode
// 9. Unknown Telemetry source
// 10. Unknown Telemetry duration
// 11. Unknown Telemetry success
Assert.AreEqual(11, properties.Length);
}
else
{
// There should be 4 entries in properties
// 4. PerfCounter name is a custom property.
Assert.AreEqual(4, properties.Length);
// There should be 5 entries in properties
// 1. from item's ISupportProperties.Properties
// 2. from item context.GlobalProperties
// 3. from item context.Properties
// 4. from myInfField in item's Extension
// 5. from myStringField in item's Extension
Assert.AreEqual(5, properties.Length);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/Microsoft.ApplicationInsights/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ internal class Constants

internal const string DevModeTelemetryNamePrefix = "Microsoft.ApplicationInsights.Dev.";

internal const string EventNameForUnknownTelemetry = "ConvertedTelemetry";

internal const int MaxExceptionCountToSave = 10;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
[EditorBrowsable(EditorBrowsableState.Never)]
public static class JsonSerializer
{
internal const string EventNameForUnknownTelemetry = "ConvertedTelemetry";

private static readonly UTF8Encoding TransmissionEncoding = new UTF8Encoding(false);

/// <summary>
Expand Down Expand Up @@ -209,7 +207,7 @@ private static void SerializeUnknownTelemetryHelper(ITelemetry telemetryItem, Js
jsonSerializationWriter.WriteStartObject("baseData");

jsonSerializationWriter.WriteProperty("ver", 2);
jsonSerializationWriter.WriteProperty("name", EventNameForUnknownTelemetry);
jsonSerializationWriter.WriteProperty("name", Constants.EventNameForUnknownTelemetry);

jsonSerializationWriter.WriteProperty("properties", dictionarySerializationWriter.AccumulatedDictionary);
jsonSerializationWriter.WriteProperty("measurements", dictionarySerializationWriter.AccumulatedMeasurements);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,75 @@ private Action<OperationTelemetry, EventOpcode> CreateOperationStartStopHandler(
};
}

/// <summary>
/// Create handler for unknown telemetry that accepts EventData, InstrumentationKey, tags, flags
/// </summary>
private Action<EventData, string, IDictionary<string, string>, long> CreateHandlerForUnknownTelemetry(EventSource eventSource)
{
var eventSourceType = eventSource.GetType();

// EventSource.Write<T> (String, EventSourceOptions, T)
var writeGenericMethod = eventSourceType.GetMethods(BindingFlags.Instance | BindingFlags.Public)
.Where(m => m.Name == "Write" && m.IsGenericMethod == true)
.Select(m => new { Method = m, Parameters = m.GetParameters() })
.Where(m => m.Parameters.Length == 3
&& m.Parameters[0].ParameterType.FullName == "System.String"
&& m.Parameters[1].ParameterType.FullName == "System.Diagnostics.Tracing.EventSourceOptions"
&& m.Parameters[2].ParameterType.FullName == null && m.Parameters[2].ParameterType.IsByRef == false)
.Select(m => m.Method)
.SingleOrDefault();

if (writeGenericMethod == null)
{
return null;
}

var eventSourceOptionsType = eventSourceType.Assembly.GetType("System.Diagnostics.Tracing.EventSourceOptions");
var eventSourceOptionsKeywordsProperty = eventSourceOptionsType.GetProperty("Keywords", BindingFlags.Public | BindingFlags.Instance);

var eventSourceOptions = Activator.CreateInstance(eventSourceOptionsType);
var keywords = Keywords.Events;
eventSourceOptionsKeywordsProperty.SetValue(eventSourceOptions, keywords);
var dummyEventData = new EventData();
var writeMethod = writeGenericMethod.MakeGenericMethod(new
{
PartA_iKey = this.dummyPartAiKeyValue,
PartA_Tags = this.dummyPartATagsValue,
PartB_EventData = new
{
// The properties and layout should be the same as EventData_types.cs
dummyEventData.ver,
dummyEventData.name,
dummyEventData.properties,
dummyEventData.measurements
},
PartA_flags = this.dummyPartAFlagsValue,
}.GetType());

return (data, iKey, tags, flags) =>
{
if (this.EventSourceInternal.IsEnabled(EventLevel.Verbose, keywords))
{
var extendedData = new
{
// The properties and layout should be the same as the anonymous type in the above MakeGenericMethod
PartA_iKey = iKey,
PartA_Tags = tags,
PartB_EventData = new
{
data.ver,
data.name,
data.properties,
data.measurements
},
PartA_flags = flags,
};

writeMethod.Invoke(eventSource, new object[] { EventTelemetry.TelemetryName, eventSourceOptions, extendedData });
}
};
}

/// <summary>
/// Create handler for request telemetry.
/// </summary>
Expand Down
Loading