Skip to main content
Glama
SerilogAdapter.cs4.31 kB
#if SERILOG using System; using System.Collections.Generic; using Serilog.Core; using Serilog.Events; namespace AI.Logging.Adapters { /// <summary> /// Serilog sink that forwards logs to AI Logger /// </summary> public class AILoggerSink : ILogEventSink { private readonly AILogger logger; private readonly IFormatProvider formatProvider; /// <summary> /// Create a new AI Logger sink /// </summary> /// <param name="formatProvider">Format provider</param> public AILoggerSink(IFormatProvider formatProvider = null) { this.logger = new AILogger("Serilog"); this.formatProvider = formatProvider; } /// <summary> /// Create a new AI Logger sink with the specified logger /// </summary> /// <param name="logger">AI Logger to forward logs to</param> /// <param name="formatProvider">Format provider</param> public AILoggerSink(AILogger logger, IFormatProvider formatProvider = null) { this.logger = logger; this.formatProvider = formatProvider; } /// <summary> /// Emit a log event /// </summary> /// <param name="logEvent">Log event to emit</param> public void Emit(LogEvent logEvent) { var level = ConvertLogLevel(logEvent.Level); var message = logEvent.RenderMessage(formatProvider); var properties = new Dictionary<string, object>(); // Extract properties foreach (var property in logEvent.Properties) { properties[property.Key] = ConvertPropertyValue(property.Value); } logger.Log(level, message, new { properties = properties, exception = logEvent.Exception != null ? new { message = logEvent.Exception.Message, stackTrace = logEvent.Exception.StackTrace, type = logEvent.Exception.GetType().FullName } : null, timestamp = logEvent.Timestamp }); } private LogLevel ConvertLogLevel(LogEventLevel level) { switch (level) { case LogEventLevel.Verbose: case LogEventLevel.Debug: return LogLevel.Debug; case LogEventLevel.Information: return LogLevel.Info; case LogEventLevel.Warning: return LogLevel.Warning; case LogEventLevel.Error: return LogLevel.Error; case LogEventLevel.Fatal: return LogLevel.Critical; default: return LogLevel.Info; } } private object ConvertPropertyValue(LogEventPropertyValue value) { if (value is ScalarValue scalarValue) { return scalarValue.Value; } if (value is SequenceValue sequenceValue) { var result = new List<object>(); foreach (var element in sequenceValue.Elements) { result.Add(ConvertPropertyValue(element)); } return result; } if (value is StructureValue structureValue) { var result = new Dictionary<string, object>(); foreach (var property in structureValue.Properties) { result[property.Name] = ConvertPropertyValue(property.Value); } return result; } if (value is DictionaryValue dictionaryValue) { var result = new Dictionary<object, object>(); foreach (var element in dictionaryValue.Elements) { result[ConvertPropertyValue(element.Key)] = ConvertPropertyValue(element.Value); } return result; } return value.ToString(); } } } #endif

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TSavo/Unity-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server