microsoft / ApplicationInsights-dotnet

ApplicationInsights-dotnet
MIT License
564 stars 282 forks source link

Strong typed extensibility for Telemetry types #871

Closed cijothomas closed 5 years ago

cijothomas commented 5 years ago

Application Insights today allows extensibility of existing Telemetry types via property bags of (string,string). There is extensibility on the TelemetryContext as well via Properties and the newly introduced GlobalProperties. (https://github.com/Microsoft/ApplicationInsights-dotnet/issues/820)

While the above is sufficient for most use cases, there can be requirements to have strongly-typed extensibility to existing types. To support this, we are introducing the following changes.

ITelemetry (and hence all implementing Telemetry types like RequestTelemetry, DependencyTelemetry etc.) will define a new field, Extension of type IExtension. The interface IExtension defines the following methods. void Serialize(ISerializationWriter writer); IExtension DeepClone();

ISerializationWriter is another new interface which has methods enabling the author of IExtension implementations to emit serialization information about the new type. Its defined like follows. (Will be changing this api frequently during beta period based on feedback)

    public interface ISerializationWriter
    {
        void WriteProperty(string name, string value);        
        void WriteProperty(string name, double? value);
        void WriteProperty(string name, int? value);
        void WriteProperty(string name, bool? value);
        void WriteProperty(string name, TimeSpan? value);
        void WriteList(string name, IList<string> items);
        void WriteDictionary(string name, IDictionary<string, string> items);
        void WriteStartObject(string name);
        void WriteEndObject(string name);       
    }

These allow a user to extend any existing Telemetry types with new strongly-typed classes, provided the new class implements the interface IExtension. The channel which sends the data to backend, can supply its own ISerializationWriter to serialize the extension.

Please note that as of now, Application Insights back-end does not accept any new fields other than the current property bags. This strongly-typed extension is currently targeted for users who uses Application Insights SDK with custom non Application-Insights channel.

ISerializationWriter based strongly-typed extensibility will be used for extending an existing type like RequestTelemetry and also to define completely new ITelemetry types. ITelemetry will be defining a new method void SerializeData(ISerializationWriter serializationWriter).

Users who define new telemetry type will have implement ITelemetry interface. The SerializeData method should be implemented by the author of this new type to help channels with serialization of the data from new class. Fields defined on ITelemetry itself, like Extension, Context etc. will be serialized by the channel itself. Again, this is only applicable to users who use non Application-Insights channel and back-end.

The following example shows how a user can defined a new Telemetry type.

    class MyNewTelemetryType : ITelemetry
    {
     // Define fields/methods for this new type.

     // implements fields/methods from ITelemetry (includes SerializeData, DeepClone etc)
    }

    // Instances on MyNewTelemetryType can be used in Track() method, `TelemetryInitializer`, `TelemetryProcessor` just like existing types.
    TelemetryClient tc = new TelemetryClient();
    tc.Track(new MyNewTelemetryType());

Note again that, Application-Insights channel will ignore these newly types events as Application-Insights backend do not support this yet.

Leonardo-Ferreira commented 8 months ago

any news here? does app insights supports this fully yet?

im starting a new front on my side to generate aggregation custom metrics for requests and dependencies in a way that you could create a custom dashboard that is "lets fiddle with the data sampling"-proof... I was thinking about just throwing all the data on that custom dimensions, but that is quite bad because you have to keep tostring(parse_json(tostring(customDimensions["myField"])))["myStringField"]