Skip to content

Commit

Permalink
Merge pull request #1 from unoplatform/dev/jela/first
Browse files Browse the repository at this point in the history
chore: Add original source from uno@4dabe7d629771d24e312a9da948f24241387b167
  • Loading branch information
jeromelaban authored Dec 5, 2024
2 parents 83a9278 + 41d965f commit 5c6df1c
Show file tree
Hide file tree
Showing 26 changed files with 2,171 additions and 2 deletions.
75 changes: 75 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: CI

on:
push:
branches:
- main
- release/**

pull_request:
types: [opened, synchronize, reopened]
branches:
- main
- release/**

jobs:
build:
name: Build
runs-on: windows-2022
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0

- uses: dotnet/nbgv@f088059084cb5d872e9d1a994433ca6440c2bf72 # v0.4.2
with:
toolVersion: 3.6.139
setAllVars: true

- name: Build
run: |
cd src
dotnet build -c Release -p:PackageVersion=$env:NBGV_SemVer2 -p:Version=$env:NBGV_SemVer2 "-p:InformationalVersion=$env:NBGV_SemVer2+$env:NBGV_BuildingRef" "/p:PackageOutputPath=$env:GITHUB_WORKSPACE\artifacts"
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: NuGet
path: .\artifacts

publish:
name: Publish
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) }}
runs-on: windows-latest
needs:
- build
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Download Artifacts
uses: actions/download-artifact@v4
with:
name: NuGet
path: artifacts

- name: Setup .NET SDK
uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.x'

- name: Setup SignClient
run: |
dotnet tool install --tool-path build SignClient
- name: SignClient
run: |
if ("${{ secrets.SIGN_CLIENT_USER }}" -ne "")
{
build\SignClient sign -i artifacts\*.nupkg -c build\SignClient.json -r "${{ secrets.SIGN_CLIENT_USER }}" -s "${{ secrets.SIGN_CLIENT_SECRET }}" -n "Uno.Devtools.Telemetry" -d "Uno.Devtools.Telemetry" -u "https://github.com/unoplatform/uno.devtools.telemetry"
}
- name: NuGet Push
run: |
dotnet nuget push artifacts\*.nupkg -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET_ORG_API_KEY }}
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# template
# Uno Platform Developer tools for Telemetry

template for brand new github repositories
Learn how to [get started with Uno Platform](https://aka.platform.uno/get-started).

This repository contains the telemetry source used through Uno Platform's developer tools, derived from the existing `dotnet.exe` telemetry.

The package generated from this repository is not integrated into end-user apps, and should be not be referenced directly.
13 changes: 13 additions & 0 deletions build/SignClient.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"SignClient": {
"AzureAd": {
"AADInstance": "https://login.microsoftonline.com/",
"ClientId": "80441c68-7fd8-4866-8dd1-8c78ff585a8a",
"TenantId": "a297d6c0-b635-41a3-b1e3-558efe71e413"
},
"Service": {
"Url": "https://uno-signservice.azurewebsites.net",
"ResourceId": "https://SignService.platformuno.onmicrosoft.com/6dd8824b-6147-4b02-a1af-ea83b0ffebdb"
}
}
}
Binary file added src/.icons/uno.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project>
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<GenerateSBOM>true</GenerateSBOM>
<NoWarn>$(NoWarn);NU1507</NoWarn>
</PropertyGroup>
</Project>
3 changes: 3 additions & 0 deletions src/Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Project>
<Import Project="UnoMetadata.targets" />
</Project>
9 changes: 9 additions & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project>
<ItemGroup>
<PackageVersion Include="Microsoft.Sbom.Targets" Version="3.0.0" />
<PackageVersion Include="Microsoft.ApplicationInsights" Version="2.20.0" />
<PackageVersion Include="Microsoft.DotNet.PlatformAbstractions" Version="3.1.6" />
<PackageVersion Include="PolySharp" Version="1.15.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="1.1.1"/>
</ItemGroup>
</Project>
25 changes: 25 additions & 0 deletions src/Uno.DevTools.Telemetry.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.13.35507.96 d17.13
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Uno.DevTools.Telemetry", "Uno.DevTools.Telemetry\Uno.DevTools.Telemetry.csproj", "{291C2E10-5CAA-465B-A14E-CB7954AB25A8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{291C2E10-5CAA-465B-A14E-CB7954AB25A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{291C2E10-5CAA-465B-A14E-CB7954AB25A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{291C2E10-5CAA-465B-A14E-CB7954AB25A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{291C2E10-5CAA-465B-A14E-CB7954AB25A8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {61360D76-7CDA-40DE-B87B-383F28CF50BF}
EndGlobalSection
EndGlobal
45 changes: 45 additions & 0 deletions src/Uno.DevTools.Telemetry/HashBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using Microsoft.CodeAnalysis;

namespace Uno.UI.SourceGenerators.Helpers
{
internal class HashBuilder
{
/// <summary>
/// Creates a non-cryptographically secure hash of the provided string, clamped to 16 bytes.
/// </summary>
/// <remarks>
/// The 16 bytes clamping is required on some platforms combinations to avoid having long file paths. The hash is used
/// to limit collisions for duplicate file names in different folders, used in the same generator.
/// </remarks>
/// <param name="input">The string to hash</param>
/// <param name="algoritm">The algorithm to use</param>
/// <returns>A hex-formatted string of the hash</returns>
public static string Build(string input)
{
using (var algorithm = SHA256.Create())
{
var data = algorithm.ComputeHash(Encoding.UTF8.GetBytes(input));

var min = Math.Min(data.Length, 16);

Span<char> span = stackalloc char[32];
int i = 0, j = 0;
while (i < min)
{
var b = data[i++];
var nib = (b >> 4);
span[j++] = nib > 9 ? (char)(nib + 'W') : (char)(nib + '0');
nib = (b & 0xf);
span[j++] = nib > 9 ? (char)(nib + 'W') : (char)(nib + '0');
}

return span.Slice(0, min * 2).ToString();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
// 2019/04/12 (Jerome Laban <[email protected]>):
// - Extracted from dotnet.exe
// 2024/12/05 (Jerome Laban <[email protected]>):
// - Updated for nullability
//

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights.Channel;

namespace Uno.UI.SourceGenerators.Telemetry.PersistenceChannel
{
internal abstract class BaseStorageService
{
/// <summary>
/// Peeked transmissions dictionary (maps file name to its full path). Holds all the transmissions that were peeked.
/// </summary>
/// <remarks>
/// Note: The value (=file's full path) is not required in the Storage implementation.
/// If there was a concurrent Abstract Data Type Set it would have been used instead.
/// However, since there is no concurrent Set, dictionary is used and the second value is ignored.
/// </remarks>
protected IDictionary<string, string>? PeekedTransmissions;

/// <summary>
/// Gets or sets the maximum size of the storage in bytes. When limit is reached, the Enqueue method will drop new
/// transmissions.
/// </summary>
internal ulong CapacityInBytes { get; set; }

/// <summary>
/// Gets or sets the maximum number of files. When limit is reached, the Enqueue method will drop new transmissions.
/// </summary>
internal uint MaxFiles { get; set; }

internal abstract string? StorageDirectoryPath { get; }

/// <summary>
/// Initializes the <see cref="BaseStorageService" />
/// </summary>
/// <param name="desireStorageDirectoryPath">A folder name. Under this folder all the transmissions will be saved.</param>
internal abstract void Init(string? desireStorageDirectoryPath);

internal abstract StorageTransmission? Peek();

internal abstract void Delete(StorageTransmission transmission);

internal abstract Task EnqueueAsync(Transmission transmission);

protected void OnPeekedItemDisposed(string fileName)
{
try
{
if (PeekedTransmissions is not null
&& PeekedTransmissions.ContainsKey(fileName))
{
PeekedTransmissions.Remove(fileName);
}
}
catch (Exception e)
{
PersistenceChannelDebugLog.WriteException(e, "Failed to remove the item from storage items.");
}
}
}
}
50 changes: 50 additions & 0 deletions src/Uno.DevTools.Telemetry/PersistenceChannel/FixedSizeQueue.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
// 2019/04/12 (Jerome Laban <[email protected]>):
// - Extracted from dotnet.exe
// 2024/12/05 (Jerome Laban <[email protected]>):
// - Updated for nullability
//

using System.Collections.Generic;

namespace Uno.UI.SourceGenerators.Telemetry.PersistenceChannel
{
/// <summary>
/// A light fixed size queue. If Enqueue is called and queue's limit has reached the last item will be removed.
/// This data structure is thread safe.
/// </summary>
internal class FixedSizeQueue<T>
{
private readonly int _maxSize;
private readonly Queue<T> _queue = new Queue<T>();
private readonly object _queueLockObj = new object();

internal FixedSizeQueue(int maxSize)
{
_maxSize = maxSize;
}

internal void Enqueue(T item)
{
lock (_queueLockObj)
{
if (_queue.Count == _maxSize)
{
_queue.Dequeue();
}

_queue.Enqueue(item);
}
}

internal bool Contains(T item)
{
lock (_queueLockObj)
{
return _queue.Contains(item);
}
}
}
}
64 changes: 64 additions & 0 deletions src/Uno.DevTools.Telemetry/PersistenceChannel/FlushManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// // Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
// 2019/04/12 (Jerome Laban <[email protected]>):
// - Extracted from dotnet.exe
// 2024/12/05 (Jerome Laban <[email protected]>):
// - Updated for nullability
//

using System;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility.Implementation;
using IChannelTelemetry = Microsoft.ApplicationInsights.Channel.ITelemetry;

namespace Uno.UI.SourceGenerators.Telemetry.PersistenceChannel
{
/// <summary>
/// This class handles all the logic for flushing the In Memory buffer to the persistent storage.
/// </summary>
internal class FlushManager
{
/// <summary>
/// The storage that is used to persist all the transmissions.
/// </summary>
private readonly BaseStorageService _storage;

/// <summary>
/// Initializes a new instance of the <see cref="FlushManager" /> class.
/// </summary>
/// <param name="storage">The storage that persists the telemetries.</param>
internal FlushManager(BaseStorageService storage)
{
_storage = storage;
}

/// <summary>
/// Gets or sets the service endpoint.
/// </summary>
/// <remarks>
/// Q: Why flushManager knows about the endpoint?
/// A: Storage stores Transmission objects and Transmission objects contain the endpoint address.
/// </remarks>
internal Uri? EndpointAddress { get; set; }


/// <summary>
/// Persist the in-memory telemetry items.
/// </summary>
internal void Flush(IChannelTelemetry telemetryItem)
{
if (telemetryItem != null)
{
byte[] data = JsonSerializer.Serialize(new[] { telemetryItem });
Transmission transmission = new Transmission(
EndpointAddress,
data,
"application/x-json-stream",
JsonSerializer.CompressionType);

_storage.EnqueueAsync(transmission).ConfigureAwait(false).GetAwaiter().GetResult();
}
}
}
}
Loading

0 comments on commit 5c6df1c

Please sign in to comment.