forked from dotnet/sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAllowEmptyTelemetry.cs
83 lines (77 loc) · 3.21 KB
/
AllowEmptyTelemetry.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Build.Framework;
using Microsoft.NET.Build.Tasks;
namespace Microsoft.Build.Tasks
{
/// <summary>
/// Task that logs telemetry.
/// </summary>
public sealed class AllowEmptyTelemetry : TaskBase
{
public AllowEmptyTelemetry()
{
EventData = Array.Empty<ITaskItem>();
EventName = string.Empty;
}
/// <summary>
/// Gets or sets an array of ITaskItems. The ItemSpec of the item will be the 'key' of the telemetry event property. The 'Value' metadata will be the value.
/// If the 'Hash' metadata is present and set to 'true', the value will be hashed before being logged.
/// </summary>
public ITaskItem[] EventData { get; set; }
[Required] public string EventName { get; set; }
protected override void ExecuteCore()
{
if (EventData == null)
{
(BuildEngine as IBuildEngine5)?.LogTelemetry(EventName, null);
}
else
{
IDictionary<string, string> properties = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var item in EventData)
{
var key = item.ItemSpec;
var availableNames = item.MetadataNames.Cast<string>();
var hasValue = availableNames.Contains("Value");
var value = hasValue ? item.GetMetadata("Value") : null;
var hasHash = availableNames.Contains("Hash");
var hash = hasHash ? bool.Parse(item.GetMetadata("Hash")) : false;
if (hash && value != null)
{
value = HashWithNormalizedCasing(value);
}
if (string.IsNullOrEmpty(value))
{
properties[key] = "null";
}
else
{
properties[key] = value;
}
}
(BuildEngine as IBuildEngine5)?.LogTelemetry(EventName, properties);
}
}
// A local copy of Sha256Hasher.HashWithNormalizedCasing from the Microsoft.DotNet.Cli.Utils project.
// We don't want to introduce a project<->project dependency, and the logic is straightforward enough.
private static string HashWithNormalizedCasing(string text)
{
var utf8UpperBytes = Encoding.UTF8.GetBytes(text.ToUpperInvariant());
#if NETFRAMEWORK
var crypt = System.Security.Cryptography.SHA256.Create();
var hash = new System.Text.StringBuilder();
byte[] crypto = crypt.ComputeHash(utf8UpperBytes);
foreach (byte theByte in crypto)
{
hash.Append(theByte.ToString("x2"));
}
return hash.ToString().ToLowerInvariant();
#endif
#if NET
byte[] hash = System.Security.Cryptography.SHA256.HashData(utf8UpperBytes);
return Convert.ToHexStringLower(hash);
#endif
}
}
}