UserJourney

This commit is contained in:
Admin 2025-12-26 06:14:09 -05:00
parent 64177a5434
commit 2a6b68ba6d
4 changed files with 120 additions and 39 deletions

View File

@ -5,6 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageOutputPath>C:\Users\logik\Dropbox\Nugets</PackageOutputPath>
<!-- NuGet Package Properties --> <!-- NuGet Package Properties -->
<PackageId>IronTelemetry.Client</PackageId> <PackageId>IronTelemetry.Client</PackageId>
@ -17,6 +18,7 @@
<RepositoryUrl>https://github.com/ironservices/irontelemetry-client</RepositoryUrl> <RepositoryUrl>https://github.com/ironservices/irontelemetry-client</RepositoryUrl>
<PackageProjectUrl>https://www.irontelemetry.com</PackageProjectUrl> <PackageProjectUrl>https://www.irontelemetry.com</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile> <PackageReadmeFile>README.md</PackageReadmeFile>
<PackageIcon>nuget_it.png</PackageIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -24,6 +26,12 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="nuget_it.png">
<Pack>true</Pack>
<PackagePath>\</PackagePath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>true</Visible>
</None>
<None Include="README.md" Pack="true" PackagePath="\" Condition="Exists('README.md')" /> <None Include="README.md" Pack="true" PackagePath="\" Condition="Exists('README.md')" />
</ItemGroup> </ItemGroup>

View File

@ -1,3 +1,5 @@
using System.Diagnostics;
namespace IronTelemetry.Client; namespace IronTelemetry.Client;
/// <summary> /// <summary>
@ -9,6 +11,31 @@ public static class IronTelemetry
{ {
private static TelemetryClient? _client; private static TelemetryClient? _client;
private static readonly object _lock = new(); private static readonly object _lock = new();
private static bool _enableDebugLogging;
/// <summary>
/// Enable verbose debug output during development.
/// When enabled, all events are written to System.Diagnostics.Debug.WriteLine.
/// </summary>
/// <example>
/// IronTelemetry.EnableDebugLogging = true; // Enable during development
/// </example>
public static bool EnableDebugLogging
{
get => _enableDebugLogging;
set => _enableDebugLogging = value;
}
/// <summary>
/// Writes a debug message if EnableDebugLogging is true.
/// </summary>
internal static void DebugLog(string message)
{
if (_enableDebugLogging)
{
Debug.WriteLine($"[IronTelemetry] {message}");
}
}
/// <summary> /// <summary>
/// Initialize IronTelemetry with a DSN. /// Initialize IronTelemetry with a DSN.
@ -61,6 +88,29 @@ public static class IronTelemetry
_client!.CaptureMessage(message, level); _client!.CaptureMessage(message, level);
} }
/// <summary>
/// Log a message with a title, message, and optional metadata.
/// This is useful for debugging and informational logging without exceptions.
/// </summary>
/// <param name="level">Log level: "info", "warning", "error", "debug"</param>
/// <param name="title">Short title for the log entry</param>
/// <param name="message">Detailed message (optional)</param>
/// <param name="data">Optional additional data</param>
public static void LogMessage(string level, string title, string? message = null, Dictionary<string, object>? data = null)
{
EnsureInitialized();
_client!.LogMessage(level, title, message, data);
}
/// <summary>
/// Get all current breadcrumbs. Useful for viewing breadcrumbs in a debug UI.
/// </summary>
public static IReadOnlyList<Breadcrumb> GetBreadcrumbs()
{
EnsureInitialized();
return _client!.GetBreadcrumbs();
}
/// <summary> /// <summary>
/// Add a breadcrumb to the current context. /// Add a breadcrumb to the current context.
/// </summary> /// </summary>

View File

@ -1,4 +1,5 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics;
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text.Json; using System.Text.Json;
@ -127,7 +128,7 @@ public class TelemetryClient : IDisposable
StepId = currentStep?.StepId, StepId = currentStep?.StepId,
TraceId = context?.TraceId, TraceId = context?.TraceId,
SpanId = context?.SpanId, SpanId = context?.SpanId,
Breadcrumbs = GetBreadcrumbs(), Breadcrumbs = GetBreadcrumbPayloads(),
Metadata = MergeMetadata(context?.Extras, currentJourney?.Metadata) Metadata = MergeMetadata(context?.Extras, currentJourney?.Metadata)
}; };
@ -143,23 +144,43 @@ public class TelemetryClient : IDisposable
_pendingItems.Enqueue(item); _pendingItems.Enqueue(item);
AddToLocalLog(item); AddToLocalLog(item);
if (_options.Debug) var journeyInfo = currentJourney != null ? $" (journey: {currentJourney.Name})" : "";
{ LogDebug($"Captured exception: {ex.GetType().Name}: {ex.Message}{journeyInfo}");
var journeyInfo = currentJourney != null ? $" (journey: {currentJourney.Name})" : "";
Console.WriteLine($"[IronTelemetry] Captured exception: {ex.GetType().Name}: {ex.Message}{journeyInfo}");
}
} }
public void CaptureMessage(string message, TelemetryLevel level) public void CaptureMessage(string message, TelemetryLevel level)
{
LogMessage(level.ToString(), message, null, null);
}
/// <summary>
/// Log a message with a title, message, and optional metadata.
/// This is useful for debugging and informational logging without exceptions.
/// </summary>
/// <param name="level">Log level: "info", "warning", "error", "debug"</param>
/// <param name="title">Short title for the log entry</param>
/// <param name="message">Detailed message</param>
/// <param name="data">Optional additional data</param>
public void LogMessage(string level, string title, string? message = null, Dictionary<string, object>? data = null)
{ {
var currentJourney = JourneyContext.Current; var currentJourney = JourneyContext.Current;
var currentStep = JourneyContext.CurrentStep; var currentStep = JourneyContext.CurrentStep;
var metadata = new Dictionary<string, object>(_extras);
if (data != null)
{
foreach (var kvp in data)
{
metadata[kvp.Key] = kvp.Value;
}
}
var item = new EnvelopeItem var item = new EnvelopeItem
{ {
Type = "message", Type = "message",
ExceptionType = level.ToString(), ExceptionType = level,
Message = message, Name = title,
Message = message ?? title,
AppVersion = _options.AppVersion, AppVersion = _options.AppVersion,
AppBuild = _options.AppBuild, AppBuild = _options.AppBuild,
Environment = _options.Environment, Environment = _options.Environment,
@ -167,12 +188,14 @@ public class TelemetryClient : IDisposable
UserEmail = currentJourney?.UserEmail ?? _userEmail, UserEmail = currentJourney?.UserEmail ?? _userEmail,
JourneyId = currentJourney?.JourneyId, JourneyId = currentJourney?.JourneyId,
StepId = currentStep?.StepId, StepId = currentStep?.StepId,
Breadcrumbs = GetBreadcrumbs(), Breadcrumbs = GetBreadcrumbPayloads(),
Metadata = new Dictionary<string, object>(_extras) Metadata = metadata
}; };
_pendingItems.Enqueue(item); _pendingItems.Enqueue(item);
AddToLocalLog(item); AddToLocalLog(item);
LogDebug($"[{level.ToUpperInvariant()}] {title}: {message}");
} }
public void AddBreadcrumb(Breadcrumb breadcrumb) public void AddBreadcrumb(Breadcrumb breadcrumb)
@ -234,10 +257,7 @@ public class TelemetryClient : IDisposable
_pendingItems.Enqueue(item); _pendingItems.Enqueue(item);
AddToLocalLog(item); AddToLocalLog(item);
if (_options.Debug) LogDebug($"Started journey: {journey.Name} ({journey.JourneyId})");
{
Console.WriteLine($"[IronTelemetry] Started journey: {journey.Name} ({journey.JourneyId})");
}
} }
internal void EnqueueJourneyEnd(JourneyScope journey) internal void EnqueueJourneyEnd(JourneyScope journey)
@ -256,10 +276,7 @@ public class TelemetryClient : IDisposable
_pendingItems.Enqueue(item); _pendingItems.Enqueue(item);
AddToLocalLog(item); AddToLocalLog(item);
if (_options.Debug) LogDebug($"Ended journey: {journey.Name} ({journey.Status})");
{
Console.WriteLine($"[IronTelemetry] Ended journey: {journey.Name} ({journey.Status})");
}
} }
internal void EnqueueStepStart(StepScope step, string journeyId) internal void EnqueueStepStart(StepScope step, string journeyId)
@ -277,10 +294,7 @@ public class TelemetryClient : IDisposable
_pendingItems.Enqueue(item); _pendingItems.Enqueue(item);
AddToLocalLog(item); AddToLocalLog(item);
if (_options.Debug) LogDebug($"Started step: {step.Name}");
{
Console.WriteLine($"[IronTelemetry] Started step: {step.Name}");
}
} }
internal void EnqueueStepEnd(StepScope step, string journeyId) internal void EnqueueStepEnd(StepScope step, string journeyId)
@ -304,10 +318,7 @@ public class TelemetryClient : IDisposable
_pendingItems.Enqueue(item); _pendingItems.Enqueue(item);
AddToLocalLog(item); AddToLocalLog(item);
if (_options.Debug) LogDebug($"Ended step: {step.Name} ({step.Status})");
{
Console.WriteLine($"[IronTelemetry] Ended step: {step.Name} ({step.Status})");
}
} }
#endregion #endregion
@ -349,10 +360,7 @@ public class TelemetryClient : IDisposable
// Queue for retry // Queue for retry
_offlineQueue.Enqueue(items); _offlineQueue.Enqueue(items);
if (_options.Debug) LogDebug($"Queued {items.Count} items for offline retry");
{
Console.WriteLine($"[IronTelemetry] Queued {items.Count} items for offline retry");
}
} }
} }
finally finally
@ -373,19 +381,13 @@ public class TelemetryClient : IDisposable
var response = await _httpClient.PostAsJsonAsync(url, envelope, JsonOptions); var response = await _httpClient.PostAsJsonAsync(url, envelope, JsonOptions);
if (_options.Debug) LogDebug($"Sent {items.Count} items, status: {response.StatusCode}");
{
Console.WriteLine($"[IronTelemetry] Sent {items.Count} items, status: {response.StatusCode}");
}
return response.IsSuccessStatusCode; return response.IsSuccessStatusCode;
} }
catch (Exception ex) catch (Exception ex)
{ {
if (_options.Debug) LogDebug($"Failed to send: {ex.Message}");
{
Console.WriteLine($"[IronTelemetry] Failed to send: {ex.Message}");
}
return false; return false;
} }
} }
@ -421,7 +423,12 @@ public class TelemetryClient : IDisposable
return true; return true;
} }
private List<BreadcrumbPayload> GetBreadcrumbs() /// <summary>
/// Get all current breadcrumbs. Useful for viewing breadcrumbs in a debug UI.
/// </summary>
public IReadOnlyList<Breadcrumb> GetBreadcrumbs() => _breadcrumbs.ToArray();
private List<BreadcrumbPayload> GetBreadcrumbPayloads()
{ {
return _breadcrumbs.Select(b => new BreadcrumbPayload return _breadcrumbs.Select(b => new BreadcrumbPayload
{ {
@ -488,6 +495,22 @@ public class TelemetryClient : IDisposable
return (baseUrl, publicKey); return (baseUrl, publicKey);
} }
/// <summary>
/// Write a debug log message. Uses Debug.WriteLine if EnableDebugLogging is set,
/// otherwise Console.WriteLine if options.Debug is set.
/// </summary>
private void LogDebug(string message)
{
if (IronTelemetry.EnableDebugLogging)
{
Debug.WriteLine($"[IronTelemetry] {message}");
}
else if (_options.Debug)
{
Console.WriteLine($"[IronTelemetry] {message}");
}
}
} }
/// <summary> /// <summary>

BIN
nuget_it.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB