Skip to content

Commit

Permalink
Removal of Plugins Store
Browse files Browse the repository at this point in the history
  • Loading branch information
MscrmTools committed Oct 31, 2023
1 parent d92ff25 commit d98b4bd
Show file tree
Hide file tree
Showing 6 changed files with 481 additions and 116 deletions.
16 changes: 1 addition & 15 deletions XrmToolBox.sln
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XrmToolBox.Extensibility",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XrmToolBox.AutoUpdater", "XrmToolBox.AutoUpdater\XrmToolBox.AutoUpdater.csproj", "{564C72C8-586E-4218-B6B3-F464F7C3903A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XrmToolBox.PluginsStore", "XrmToolBox.PluginsStore\XrmToolBox.PluginsStore.csproj", "{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LicenseChecker", "LicenseChecker", "{08305693-A5D7-41FA-B476-20874647809B}"
ProjectSection(SolutionItems) = preProject
LicenseChecker\McTools.StopAdvertisement.dll = LicenseChecker\McTools.StopAdvertisement.dll
Expand Down Expand Up @@ -73,18 +71,6 @@ Global
{564C72C8-586E-4218-B6B3-F464F7C3903A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{564C72C8-586E-4218-B6B3-F464F7C3903A}.Release|x86.ActiveCfg = Release|Any CPU
{564C72C8-586E-4218-B6B3-F464F7C3903A}.Release|x86.Build.0 = Release|Any CPU
{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}.Debug|x86.ActiveCfg = Debug|Any CPU
{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}.Debug|x86.Build.0 = Debug|Any CPU
{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}.Release|Any CPU.Build.0 = Release|Any CPU
{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}.Release|x86.ActiveCfg = Release|Any CPU
{EBCB3D22-03F2-40D2-B949-05CAE575F2EA}.Release|x86.Build.0 = Release|Any CPU
{626AEBA8-4315-4D82-B8B9-B94200FD7589}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{626AEBA8-4315-4D82-B8B9-B94200FD7589}.Debug|Any CPU.Build.0 = Debug|Any CPU
{626AEBA8-4315-4D82-B8B9-B94200FD7589}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
Expand All @@ -105,8 +91,8 @@ Global
{5BF1E228-F898-40CF-B8FB-8412D8C81CFF} = {1A7814D2-1185-484E-92CC-7DD71DDE6488}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
BuildVersion_ConfigurationName = Release
SolutionGuid = {5CC3AFE2-F092-40F3-A540-539389A045B6}
BuildVersion_ConfigurationName = Release
EndGlobalSection
GlobalSection(CodealikeProperties) = postSolution
SolutionGuid = 2bf66b53-ea6f-433b-b455-00e70ee33cd0
Expand Down
340 changes: 340 additions & 0 deletions XrmToolBox/AppCode/AppInsights/AppInsights.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,340 @@
/* ***********************************************************
* XTBAppInsights.cs
* Found at: https://gist.github.com/rappen/fbdbb644b3fffec1305b00a51b007fa6
* Created by: Jonas Rapp https://jonasr.app/
* Immensely inspired by: code from Jason Lattimer https://github.com/jlattimer/D365AppInsights
*
* Simplifies logging to Azure Application Insights from XrmToolBox tools.
*
* Sample from tool constructor:
* ai = new AppInsights("https://dc.services.visualstudio.com/v2/track", "[a guid that is the key to your appinsights resource]", Assembly.GetExecutingAssembly(), "[my custom tool name]");
* Sample call:
* ai.WriteEvent(action, count, duration, HandleAIResult);
* Sample HandleAIResult:
* private void HandleAIResult(string result)
* {
* if (!string.IsNullOrEmpty(result)) { LogError("Failed to write to Application Insights:\n{0}", result); }
* }
*
* Enjoy responsibly.
* **********************************************************/

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using XrmToolBox.AppCode.AppInsights;

public static class Extensions
{
public static string PaddedVersion(this Version version, int majorpad, int minorpad, int buildpad, int revisionpad)
{
return string.Format($"{{0:D{majorpad}}}.{{1:D{minorpad}}}.{{2:D{buildpad}}}.{{3:D{revisionpad}}}", version.Major, version.Minor, version.Build, version.Revision);
}
}

public class AiConfig
{
/// <summary>
/// Initializes Application Insights configuration.
/// When called from a tool, make sure to pass Assembly.GetExecutingAssembly() as loggingassembly parameter!!
/// </summary>
/// <param name="endpoint">AppInsights endpoint, usually https://dc.services.visualstudio.com/v2/track</param>
/// <param name="ikey">Instrumentation Key for the AppInsights instance in the Azure portal</param>
/// <param name="loggingassembly">Assembly info to include in logging, usually pass Assembly.GetExecutingAssembly()</param>
/// <param name="toolname">Override name of the tool, defaults to last part of the logging assembly name</param>
public AiConfig(string endpoint, string ikey, Assembly loggingassembly = null, string toolname = null)
{
AiEndpoint = endpoint;
InstrumentationKey = ikey;
LoggingAssembly = loggingassembly ?? Assembly.GetExecutingAssembly();
PluginName = toolname ?? GetLastDotPart(LoggingAssembly.GetName().Name);
PluginVersion = LoggingAssembly.GetName().Version.PaddedVersion(1, 4, 2, 2);
InstallationId = InstallationInfo.Instance.InstallationId;
// This will disable logging if the calling assembly is compiled with debug configuration
LogEvents = !LoggingAssembly.GetCustomAttributes<DebuggableAttribute>().Any(d => d.IsJITTrackingEnabled);

var isc = new XrmToolBox.Extensibility.ItSecurityChecker();
LogEvents = LogEvents && !isc.IsStatisticsCollectDisabled();
}

public string AiEndpoint { get; }
public Guid InstallationId { get; set; }
public string InstrumentationKey { get; }
public bool LogEvents { get; set; } = true;
public Assembly LoggingAssembly { get; }
public string OperationName { get; set; }
public string PluginName { get; set; }
public string PluginVersion { get; set; }
public Guid SessionId { get; } = Guid.NewGuid();
public string XTBVersion { get; set; } = GetLastDotPart(Assembly.GetEntryAssembly().GetName().Name) + " " + Assembly.GetEntryAssembly().GetName().Version.PaddedVersion(1, 4, 2, 2);

private static string GetLastDotPart(string identifier)
{
return identifier == null ? null : !identifier.Contains(".") ? identifier : identifier.Substring(identifier.LastIndexOf('.') + 1);
}
}

public class AppInsights
{
private readonly AiConfig _aiConfig;
private int seq = 1;

/// <summary>
/// Initializes Application Insights instance.
/// When called from a tool, make sure to pass Assembly.GetExecutingAssembly() as loggingassembly parameter!!
/// </summary>
/// <param name="endpoint">AppInsights endpoint, usually https://dc.services.visualstudio.com/v2/track</param>
/// <param name="ikey">Instrumentation Key for the AppInsights instance in the Azure portal</param>
/// <param name="loggingassembly">Assembly info to include in logging, usually pass Assembly.GetExecutingAssembly()</param>
/// <param name="toolname">Override name of the tool, defaults to last part of the logging assembly name</param>
public AppInsights(string endpoint, string ikey, Assembly loggingassembly, string toolname = null)
{
_aiConfig = new AiConfig(endpoint, ikey, loggingassembly, toolname);
}

/// <summary>
/// Obsolete constructor
/// </summary>
/// <param name="aiConfig">Application Insights configuration</param>
[Obsolete("Use constructor accepting parameters endpoint, ikey, loggingassembly and toolname instead.", false)]
public AppInsights(AiConfig aiConfig)
{
_aiConfig = aiConfig;
}

public void WriteEvent(string eventName, double? count = null, double? duration = null, Action<string> resultHandler = null)
{
if (!_aiConfig.LogEvents) return;
var logRequest = GetLogRequest("Event");
logRequest.Data.BaseData.Name = eventName;
if (count != null || duration != null)
{
logRequest.Data.BaseData.Measurements = new AiMeasurements
{
Count = count ?? 0,
Duration = duration ?? 0
};
}
var json = SerializeRequest<AiLogRequest>(logRequest);
SendToAi(json, resultHandler);
}

public void WritePageView(string pluginName, string pluginVersion, double? count = null, double? duration = null, Action<string> resultHandler = null)
{
if (!_aiConfig.LogEvents) return;
var logRequest = GetLogRequest("PageView");
logRequest.Data.BaseData.Name = pluginName;
logRequest.Data.BaseData.Properties = new AiProperties
{
PluginVersion = pluginVersion
};

if (count != null || duration != null)
{
logRequest.Data.BaseData.Measurements = new AiMeasurements
{
Count = count ?? 0,
Duration = duration ?? 0
};
}
var json = SerializeRequest<AiLogRequest>(logRequest);
SendToAi(json, resultHandler);
}

public void WritePluginEvent(string pluginName, string pluginVersion, string eventName, double? count = null, double? duration = null, Action<string> resultHandler = null)
{
if (!_aiConfig.LogEvents) return;
var logRequest = GetLogRequest("Event");
logRequest.Data.BaseData.Name = eventName;
logRequest.Data.BaseData.Properties = new AiProperties
{
PluginName = pluginName,
PluginVersion = pluginVersion
};
if (count != null || duration != null)
{
logRequest.Data.BaseData.Measurements = new AiMeasurements
{
Count = count ?? 0,
Duration = duration ?? 0
};
}
var json = SerializeRequest<AiLogRequest>(logRequest);
SendToAi(json, resultHandler);
}

private static string SerializeRequest<T>(object o)
{
using (MemoryStream stream = new MemoryStream())
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
serializer.WriteObject(stream, o);
stream.Position = 0;
StreamReader reader = new StreamReader(stream);
string json = reader.ReadToEnd();

return json;
}
}

private AiLogRequest GetLogRequest(string action)
{
return new AiLogRequest(seq++, _aiConfig, action);
}

private async void SendToAi(string json, Action<string> handleresult = null)
{
var result = string.Empty;
#if DEBUG
#else
try
{
using (HttpClient client = HttpHelper.GetHttpClient())
{
var content = new StringContent(json, Encoding.UTF8, "application/x-json-stream");
var response = await client.PostAsync(_aiConfig.AiEndpoint, content);

if (!response.IsSuccessStatusCode)
{
result = response.ToString();
}
}
}
catch (Exception e)
{
result = e.ToString();
}
#endif
handleresult?.Invoke(result);
}
}

public class HttpHelper
{
public static HttpClient GetHttpClient()
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Connection", "close");

return client;
}
}

#region DataContracts

[DataContract]
public class AiBaseData
{
[DataMember(Name = "measurements")]
public AiMeasurements Measurements { get; set; }

[DataMember(Name = "name")]
public string Name { get; set; }

[DataMember(Name = "properties")]
public AiProperties Properties { get; set; }
}

[DataContract]
public class AiData
{
[DataMember(Name = "baseData")]
public AiBaseData BaseData { get; set; }

[DataMember(Name = "baseType")]
public string BaseType { get; set; }
}

[DataContract]
public class AiLogRequest
{
public AiLogRequest(int sequence, AiConfig aiConfig, string action)
{
Name = $"Microsoft.ApplicationInsights.{aiConfig.InstrumentationKey}.{action}";
Time = $"{DateTime.UtcNow:O}";
Sequence = sequence.ToString("0000000000");
InstrumentationKey = aiConfig.InstrumentationKey;
Tags = new AiTags
{
OSVersion = aiConfig.XTBVersion,
DeviceType = aiConfig.PluginName,
ApplicationVersion = aiConfig.PluginVersion,
UserId = aiConfig.InstallationId.ToString(),
SessionId = aiConfig.SessionId.ToString(),
OperationName = aiConfig.OperationName
};
Data = new AiData
{
BaseType = $"{action}Data",
BaseData = new AiBaseData()
};
}

[DataMember(Name = "data")]
public AiData Data { get; set; }

[DataMember(Name = "iKey")]
public string InstrumentationKey { get; set; }

[DataMember(Name = "name")]
public string Name { get; set; }

[DataMember(Name = "seq")]
public string Sequence { get; set; }

[DataMember(Name = "tags")]
public AiTags Tags { get; set; }

[DataMember(Name = "time")]
public string Time { get; set; }
}

[DataContract]
public class AiMeasurements
{
[DataMember(Name = "count")]
public double Count { get; set; }

[DataMember(Name = "duration")]
public double Duration { get; set; }
}

[DataContract]
public class AiProperties
{
[DataMember(Name = "pluginName")]
public string PluginName { get; set; }

[DataMember(Name = "pluginVersion")]
public string PluginVersion { get; set; }
}

[DataContract]
public class AiTags
{
[DataMember(Name = "ai.application.ver")]
public string ApplicationVersion { get; set; }

[DataMember(Name = "ai.device.type")]
public string DeviceType { get; set; }

[DataMember(Name = "ai.operation.name")]
public string OperationName { get; set; }

[DataMember(Name = "ai.device.osVersion")]
public string OSVersion { get; set; }

[DataMember(Name = "ai.session.id")]
public string SessionId { get; set; } = Guid.NewGuid().ToString();

[DataMember(Name = "ai.user.id")]
public string UserId { get; set; }
}

#endregion DataContracts
Loading

0 comments on commit d98b4bd

Please sign in to comment.