diff --git a/IronTelemetry.Client.csproj b/IronTelemetry.Client.csproj index 15fe789..739b20b 100644 --- a/IronTelemetry.Client.csproj +++ b/IronTelemetry.Client.csproj @@ -5,6 +5,7 @@ enable enable true + C:\Users\logik\Dropbox\Nugets IronTelemetry.Client @@ -17,6 +18,7 @@ https://github.com/ironservices/irontelemetry-client https://www.irontelemetry.com README.md + nuget_it.png @@ -24,6 +26,12 @@ + + true + \ + PreserveNewest + true + diff --git a/IronTelemetry.cs b/IronTelemetry.cs index db8ac6c..10f6dc7 100644 --- a/IronTelemetry.cs +++ b/IronTelemetry.cs @@ -1,3 +1,5 @@ +using System.Diagnostics; + namespace IronTelemetry.Client; /// @@ -9,6 +11,31 @@ public static class IronTelemetry { private static TelemetryClient? _client; private static readonly object _lock = new(); + private static bool _enableDebugLogging; + + /// + /// Enable verbose debug output during development. + /// When enabled, all events are written to System.Diagnostics.Debug.WriteLine. + /// + /// + /// IronTelemetry.EnableDebugLogging = true; // Enable during development + /// + public static bool EnableDebugLogging + { + get => _enableDebugLogging; + set => _enableDebugLogging = value; + } + + /// + /// Writes a debug message if EnableDebugLogging is true. + /// + internal static void DebugLog(string message) + { + if (_enableDebugLogging) + { + Debug.WriteLine($"[IronTelemetry] {message}"); + } + } /// /// Initialize IronTelemetry with a DSN. @@ -61,6 +88,29 @@ public static class IronTelemetry _client!.CaptureMessage(message, level); } + /// + /// Log a message with a title, message, and optional metadata. + /// This is useful for debugging and informational logging without exceptions. + /// + /// Log level: "info", "warning", "error", "debug" + /// Short title for the log entry + /// Detailed message (optional) + /// Optional additional data + public static void LogMessage(string level, string title, string? message = null, Dictionary? data = null) + { + EnsureInitialized(); + _client!.LogMessage(level, title, message, data); + } + + /// + /// Get all current breadcrumbs. Useful for viewing breadcrumbs in a debug UI. + /// + public static IReadOnlyList GetBreadcrumbs() + { + EnsureInitialized(); + return _client!.GetBreadcrumbs(); + } + /// /// Add a breadcrumb to the current context. /// diff --git a/TelemetryClient.cs b/TelemetryClient.cs index b7e569f..675a027 100644 --- a/TelemetryClient.cs +++ b/TelemetryClient.cs @@ -1,4 +1,5 @@ using System.Collections.Concurrent; +using System.Diagnostics; using System.Net.Http.Json; using System.Runtime.InteropServices; using System.Text.Json; @@ -127,7 +128,7 @@ public class TelemetryClient : IDisposable StepId = currentStep?.StepId, TraceId = context?.TraceId, SpanId = context?.SpanId, - Breadcrumbs = GetBreadcrumbs(), + Breadcrumbs = GetBreadcrumbPayloads(), Metadata = MergeMetadata(context?.Extras, currentJourney?.Metadata) }; @@ -143,23 +144,43 @@ public class TelemetryClient : IDisposable _pendingItems.Enqueue(item); AddToLocalLog(item); - if (_options.Debug) - { - var journeyInfo = currentJourney != null ? $" (journey: {currentJourney.Name})" : ""; - Console.WriteLine($"[IronTelemetry] Captured exception: {ex.GetType().Name}: {ex.Message}{journeyInfo}"); - } + var journeyInfo = currentJourney != null ? $" (journey: {currentJourney.Name})" : ""; + LogDebug($"Captured exception: {ex.GetType().Name}: {ex.Message}{journeyInfo}"); } public void CaptureMessage(string message, TelemetryLevel level) + { + LogMessage(level.ToString(), message, null, null); + } + + /// + /// Log a message with a title, message, and optional metadata. + /// This is useful for debugging and informational logging without exceptions. + /// + /// Log level: "info", "warning", "error", "debug" + /// Short title for the log entry + /// Detailed message + /// Optional additional data + public void LogMessage(string level, string title, string? message = null, Dictionary? data = null) { var currentJourney = JourneyContext.Current; var currentStep = JourneyContext.CurrentStep; + var metadata = new Dictionary(_extras); + if (data != null) + { + foreach (var kvp in data) + { + metadata[kvp.Key] = kvp.Value; + } + } + var item = new EnvelopeItem { Type = "message", - ExceptionType = level.ToString(), - Message = message, + ExceptionType = level, + Name = title, + Message = message ?? title, AppVersion = _options.AppVersion, AppBuild = _options.AppBuild, Environment = _options.Environment, @@ -167,12 +188,14 @@ public class TelemetryClient : IDisposable UserEmail = currentJourney?.UserEmail ?? _userEmail, JourneyId = currentJourney?.JourneyId, StepId = currentStep?.StepId, - Breadcrumbs = GetBreadcrumbs(), - Metadata = new Dictionary(_extras) + Breadcrumbs = GetBreadcrumbPayloads(), + Metadata = metadata }; _pendingItems.Enqueue(item); AddToLocalLog(item); + + LogDebug($"[{level.ToUpperInvariant()}] {title}: {message}"); } public void AddBreadcrumb(Breadcrumb breadcrumb) @@ -234,10 +257,7 @@ public class TelemetryClient : IDisposable _pendingItems.Enqueue(item); AddToLocalLog(item); - if (_options.Debug) - { - Console.WriteLine($"[IronTelemetry] Started journey: {journey.Name} ({journey.JourneyId})"); - } + LogDebug($"Started journey: {journey.Name} ({journey.JourneyId})"); } internal void EnqueueJourneyEnd(JourneyScope journey) @@ -256,10 +276,7 @@ public class TelemetryClient : IDisposable _pendingItems.Enqueue(item); AddToLocalLog(item); - if (_options.Debug) - { - Console.WriteLine($"[IronTelemetry] Ended journey: {journey.Name} ({journey.Status})"); - } + LogDebug($"Ended journey: {journey.Name} ({journey.Status})"); } internal void EnqueueStepStart(StepScope step, string journeyId) @@ -277,10 +294,7 @@ public class TelemetryClient : IDisposable _pendingItems.Enqueue(item); AddToLocalLog(item); - if (_options.Debug) - { - Console.WriteLine($"[IronTelemetry] Started step: {step.Name}"); - } + LogDebug($"Started step: {step.Name}"); } internal void EnqueueStepEnd(StepScope step, string journeyId) @@ -304,10 +318,7 @@ public class TelemetryClient : IDisposable _pendingItems.Enqueue(item); AddToLocalLog(item); - if (_options.Debug) - { - Console.WriteLine($"[IronTelemetry] Ended step: {step.Name} ({step.Status})"); - } + LogDebug($"Ended step: {step.Name} ({step.Status})"); } #endregion @@ -349,10 +360,7 @@ public class TelemetryClient : IDisposable // Queue for retry _offlineQueue.Enqueue(items); - if (_options.Debug) - { - Console.WriteLine($"[IronTelemetry] Queued {items.Count} items for offline retry"); - } + LogDebug($"Queued {items.Count} items for offline retry"); } } finally @@ -373,19 +381,13 @@ public class TelemetryClient : IDisposable var response = await _httpClient.PostAsJsonAsync(url, envelope, JsonOptions); - if (_options.Debug) - { - Console.WriteLine($"[IronTelemetry] Sent {items.Count} items, status: {response.StatusCode}"); - } + LogDebug($"Sent {items.Count} items, status: {response.StatusCode}"); return response.IsSuccessStatusCode; } catch (Exception ex) { - if (_options.Debug) - { - Console.WriteLine($"[IronTelemetry] Failed to send: {ex.Message}"); - } + LogDebug($"Failed to send: {ex.Message}"); return false; } } @@ -421,7 +423,12 @@ public class TelemetryClient : IDisposable return true; } - private List GetBreadcrumbs() + /// + /// Get all current breadcrumbs. Useful for viewing breadcrumbs in a debug UI. + /// + public IReadOnlyList GetBreadcrumbs() => _breadcrumbs.ToArray(); + + private List GetBreadcrumbPayloads() { return _breadcrumbs.Select(b => new BreadcrumbPayload { @@ -488,6 +495,22 @@ public class TelemetryClient : IDisposable return (baseUrl, publicKey); } + + /// + /// Write a debug log message. Uses Debug.WriteLine if EnableDebugLogging is set, + /// otherwise Console.WriteLine if options.Debug is set. + /// + private void LogDebug(string message) + { + if (IronTelemetry.EnableDebugLogging) + { + Debug.WriteLine($"[IronTelemetry] {message}"); + } + else if (_options.Debug) + { + Console.WriteLine($"[IronTelemetry] {message}"); + } + } } /// diff --git a/nuget_it.png b/nuget_it.png new file mode 100644 index 0000000..fec3960 Binary files /dev/null and b/nuget_it.png differ