/// <summary> /// Convert a Serilog <see cref="LogEventPropertyValue"/> for JavaScript interop. /// </summary> public static object ToInteropValue(LogEventPropertyValue value, string format = null) { if (value is ScalarValue sv) { if (format == null) { return(sv.Value); } var sw = new StringWriter(); sv.Render(sw, format); return(sw.ToString()); } if (value is SequenceValue sqv) { return(sqv.Elements .Select(e => ToInteropValue(e)) .ToArray()); } if (value is StructureValue st) { return(st.Properties .ToDictionary(kv => kv.Name, kv => ToInteropValue(kv.Value))); } var dv = (DictionaryValue)value; return(dv.Elements .ToDictionary(kv => ToInteropValue(kv.Key), kv => ToInteropValue(kv.Value))); }
/// <summary> /// Visit the root node type. This method delegates to /// a concrete Visit*Value() method appropriate for the value. /// </summary> /// <param name="state">Operation state.</param> /// <param name="value">The value to visit.</param> /// <returns>The result of visiting <paramref name="value"/>.</returns> protected virtual TResult Visit(TState state, LogEventPropertyValue value) { if (value == null) { throw new ArgumentNullException(nameof(value)); } if (value is ScalarValue sv) { return(VisitScalarValue(state, sv)); } if (value is SequenceValue seqv) { return(VisitSequenceValue(state, seqv)); } if (value is StructureValue strv) { return(VisitStructureValue(state, strv)); } if (value is DictionaryValue dictv) { return(VisitDictionaryValue(state, dictv)); } return(VisitUnsupportedValue(state, value)); }
/// <summary> /// Simplify the object so as to make handling the serialized /// representation easier. /// </summary> /// <param name="value">The value to simplify (possibly null).</param> /// <param name="format">A format string applied to the value, or null.</param> /// <param name="formatProvider">A format provider to apply to the value, or null to use the default.</param> /// <returns>An Azure Storage entity EntityProperty</returns> public static EntityProperty ToEntityProperty(LogEventPropertyValue value, string format = null, IFormatProvider formatProvider = null) { var scalar = value as ScalarValue; if (scalar != null) { return(SimplifyScalar(scalar.Value)); } var dict = value as DictionaryValue; if (dict != null) { return(new EntityProperty(dict.ToString(format, formatProvider))); } var seq = value as SequenceValue; if (seq != null) { return(new EntityProperty(seq.ToString(format, formatProvider))); } var str = value as StructureValue; if (str != null) { return(new EntityProperty(str.ToString(format, formatProvider))); } return(null); }
public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result) { if (value is TodoItemQuery todoItemQuery) { result = new StructureValue(new List <LogEventProperty> { new LogEventProperty(nameof(todoItemQuery.Id), new ScalarValue(todoItemQuery.Id)), new LogEventProperty(nameof(todoItemQuery.NamePattern), new ScalarValue(todoItemQuery.NamePattern)), new LogEventProperty(nameof(todoItemQuery.IsComplete), new ScalarValue(todoItemQuery.IsComplete)), new LogEventProperty(nameof(todoItemQuery.Owner), new ScalarValue(todoItemQuery.Owner.GetNameOrDefault())), new LogEventProperty(nameof(todoItemQuery.PageIndex), new ScalarValue(todoItemQuery.PageIndex)), new LogEventProperty(nameof(todoItemQuery.PageSize), new ScalarValue(todoItemQuery.PageSize)), new LogEventProperty(nameof(todoItemQuery.SortBy), new ScalarValue(todoItemQuery.SortBy)), new LogEventProperty(nameof(todoItemQuery.IsSortAscending), new ScalarValue(todoItemQuery.IsSortAscending)) }); return(true); } result = null; return(false); }
private static LogEventPropertyValue Stringify(LogEventPropertyValue value) { switch (value) { case ScalarValue scalar: var element = scalar.Value.ToString(); return(new ScalarValue(element)); case SequenceValue sequence: var elements = sequence.Elements.Select(Stringify); return(new SequenceValue(elements)); case DictionaryValue dictionary: var entries = dictionary.Elements.Select(entry => new KeyValuePair <ScalarValue, LogEventPropertyValue>( (ScalarValue)Stringify(entry.Key), Stringify(entry.Value))); return(new DictionaryValue(entries)); case StructureValue structure: var properties = structure.Properties.Select(property => new LogEventProperty(property.Name, Stringify(property.Value))); return(new StructureValue(properties)); default: throw new ArgumentException("Invalid property type"); } }
// Convert scalars into a small set of primitive types; leave everything else unchanged. This // makes it easier to flow values through operations. public static object Represent(LogEventPropertyValue value) { var sv = value as ScalarValue; if (sv != null) { if (sv.Value == null) { return(null); } if (Array.IndexOf(AllowedTypes, sv.Value.GetType()) != -1) { return(sv.Value); } if (Array.IndexOf(NumericTypes, sv.Value.GetType()) != -1) { return(Convert.ChangeType(sv.Value, typeof(decimal))); } return(sv.Value.ToString()); } return(value); }
/// <summary> /// Writes event properties as labels for a GCP log entry. /// GCP log labels are a flat key/value namespace so all child event properties will be prefixed with parent property names "parentkey.childkey" similar to json path. /// </summary> private void WritePropertyAsLabel(LogEntry log, string propertyKey, LogEventPropertyValue propertyValue) { switch (propertyValue) { case ScalarValue scalarValue when scalarValue.Value is null: log.Labels.Add(propertyKey, String.Empty); break; case ScalarValue scalarValue: var stringValue = scalarValue.Value.ToString(); log.Labels.Add(propertyKey, stringValue); CheckIfSourceContext(log, propertyKey, stringValue); break; case SequenceValue sequenceValue: log.Labels.Add(propertyKey, String.Join(",", sequenceValue.Elements)); break; case StructureValue structureValue when structureValue.Properties.Count > 0: foreach (var childProperty in structureValue.Properties) { WritePropertyAsLabel(log, propertyKey + "." + childProperty.Name, childProperty.Value); } break; case DictionaryValue dictionaryValue when dictionaryValue.Elements.Count > 0: foreach (var childProperty in dictionaryValue.Elements) { WritePropertyAsLabel(log, propertyKey + "." + childProperty.Key.ToString().Replace("\"", ""), childProperty.Value); } break; } }
/// <summary> /// Removes the structure of <see cref="LogEventPropertyValue"/> implementations introduced /// by Serilog and brings properties closer to the structure of the original object. /// This enables Exceptionless to display the properties in a nicer way. /// </summary> private static object FlattenProperties(LogEventPropertyValue value) { var scalar = value as ScalarValue; if (scalar != null) { return(scalar.Value); } var sequence = value as SequenceValue; if (sequence != null) { return(sequence.Elements.Select(FlattenProperties)); } var structure = value as StructureValue; if (structure != null) { return(structure.Properties.ToDictionary(p => p.Name, p => FlattenProperties(p.Value))); } var dictionary = value as DictionaryValue; if (dictionary != null) { return(dictionary.Elements.ToDictionary(p => p.Key.Value, p => FlattenProperties(p.Value))); } return(value); }
static JToken ConvertPropertyValue(LogEventPropertyValue value) { var scalar = value as ScalarValue; if (scalar != null) { return(ConvertScalarValue(scalar)); } var seq = value as SequenceValue; if (seq != null) { return(ConvertSequenceValue(seq)); } var strct = value as StructureValue; if (strct != null) { return(ConvertStructureValue(strct)); } var dict = value as DictionaryValue; if (dict != null) { return(ConvertDictionaryValue(dict)); } // TODO: Log or something. return(JValue.CreateUndefined()); }
private static object PropertyValueToObject(LogEventPropertyValue propertyValue) { if (propertyValue is SequenceValue values) { return(values.Elements.Select(e => PropertyValueToObject(e)).ToArray()); } if (propertyValue is ScalarValue sv) { return(sv.Value); } else if (propertyValue is DictionaryValue dv) { return(dv.Elements.ToDictionary(keySelector: (kvp) => ToSnakeCase(kvp.Key.Value.ToString()), elementSelector: (kvp) => PropertyValueToObject(kvp.Value))); } else if (propertyValue is StructureValue ov) { var dict = ov.Properties.ToDictionary(p => p.Name, p => PropertyValueToObject(p.Value)); if (ov.TypeTag != null) { dict.Add("$type", ov.TypeTag); } return(dict); } else { return(propertyValue); } }
async Task SendEvent(LogEvent logEvent) { LogEventPropertyValue datasetProperty = null; logEvent.Properties.TryGetValue(DatasetPropertyKey, out datasetProperty); string dataset = ((datasetProperty as ScalarValue)?.Value as string) ?? this.defaultDataset; var request = new HttpRequestMessage(HttpMethod.Post, "events/" + dataset) { Content = new StringContent( content: JsonConvert.SerializeObject(EventToJObject(logEvent)), encoding: Encoding.UTF8, mediaType: "application/json" ), Headers = { { "X-Honeycomb-Event-Time", logEvent.Timestamp.ToString("o") }, } }; using (HttpResponseMessage message = await client.SendAsync(request)) { // TODO: Log if unsuccessful. This requires... hum. if (!message.IsSuccessStatusCode) { string msg = await message.Content.ReadAsStringAsync(); Console.WriteLine($"Warning: Failed to send event: {message.StatusCode}: {msg}"); } } }
static object ToData(LogEventPropertyValue value) { switch (value) { case ScalarValue sv: return(sv.Value); case StructureValue str: var props = str.Properties.ToDictionary(kv => kv.Name, kv => ToData(kv.Value)); if (str.TypeTag != null) { props["$type"] = str.TypeTag; } return(props); case SequenceValue seq: return(seq.Elements.Select(ToData).ToArray()); case DictionaryValue dv: var dict = new Dictionary <object, object>(); foreach (var kvp in dv.Elements) { dict[ToData(kvp.Key)] = ToData(kvp.Value); } return(dict); default: throw new NotSupportedException($"Value type {value} is not supported."); } }
public ExpressionFilter(string filterExpression) { Func <LogEvent, bool> filter; // Our custom Serilog Functions to extend Serilog.Expressions // In this case we are plugging the gap for the missing Has() // function from porting away from Serilog.Filters.Expressions to Serilog.Expressions // Along with patching support for the more verbose built in property names var customSerilogFunctions = new SerilogLegacyNameResolver(typeof(SerilogExpressionsFunctions)); if (string.IsNullOrEmpty(filterExpression)) { return; } // If the expression is one word and doesn't contain a serilog operator then we can perform a like search if (!filterExpression.Contains(" ") && !filterExpression.ContainsAny(s_expressionOperators.Select(c => c))) { filter = PerformMessageLikeFilter(filterExpression); } else // check if it's a valid expression { // If the expression evaluates then make it into a filter if (SerilogExpression.TryCompile(filterExpression, null, customSerilogFunctions, out CompiledExpression compiled, out var error)) { filter = evt => { LogEventPropertyValue result = compiled(evt); return(ExpressionResult.IsTrue(result)); }; }
private static object PropertyValueToObject(LogEventPropertyValue propertyValue) { switch (propertyValue) { case SequenceValue values: return(values.Elements.Select(PropertyValueToObject).ToArray()); case ScalarValue sv: return(sv.Value); case DictionaryValue dv: return(dv.Elements.ToDictionary(keySelector: kvp => ToSnakeCase(kvp.Key.Value.ToString()), elementSelector: (kvp) => PropertyValueToObject(kvp.Value))); case StructureValue ov: { var dict = ov.Properties.ToDictionary(p => p.Name, p => PropertyValueToObject(p.Value)); if (ov.TypeTag != null) { dict.Add("$type", ov.TypeTag); } return(dict); } default: return(propertyValue); } }
/// <summary> /// Visit a <see cref="SequenceValue"/> value. /// </summary> /// <param name="state">Operation state.</param> /// <param name="sequence">The value to visit.</param> /// <returns>The result of visiting <paramref name="sequence"/>.</returns> protected override LogEventPropertyValue VisitSequenceValue(TState state, SequenceValue sequence) { if (sequence == null) { throw new ArgumentNullException(nameof(sequence)); } for (var i = 0; i < sequence.Elements.Count; ++i) { var original = sequence.Elements[i]; if (!ReferenceEquals(original, Visit(state, original))) { var contents = new LogEventPropertyValue[sequence.Elements.Count]; // There's no need to visit any earlier elements: they all evaluated to // a reference equal with the original so just fill in the array up until `i`. for (var j = 0; j < i; ++j) { contents[j] = sequence.Elements[j]; } for (var k = i; k < contents.Length; ++k) { contents[k] = Visit(state, sequence.Elements[k]); } return(new SequenceValue(contents)); } } return(sequence); }
/// <summary> /// Format <paramref name="value"/> as JSON to <paramref name="output"/>. /// </summary> /// <param name="value">The value to format</param> /// <param name="output">The output</param> public void Format(LogEventPropertyValue value, TextWriter output) { // Parameter order of ITextFormatter is the reverse of the visitor one. // In this class, public methods and methods with Format*() names use the // (x, output) parameter naming convention. Visit(output, value); }
public static LogEventPropertyValue AsSensitive(this LogEventPropertyValue eventPropertyValue) { return(new DictionaryValue(new Dictionary <ScalarValue, LogEventPropertyValue> { [new ScalarValue(Constants.SensitiveInformation)] = eventPropertyValue, })); }
private static object ToRawValue(LogEventPropertyValue logEventValue) { // Special-case a few types of LogEventPropertyValue that allow us to maintain better type fidelity. // For everything else take the default string rendering as the data. ScalarValue scalarValue = logEventValue as ScalarValue; if (scalarValue != null) { return(scalarValue.Value); } SequenceValue sequenceValue = logEventValue as SequenceValue; if (sequenceValue != null) { object[] arrayResult = sequenceValue.Elements.Select(e => ToRawScalar(e)).ToArray(); if (arrayResult.Length == sequenceValue.Elements.Count) { // All values extracted successfully, it is a flat array of scalars return(arrayResult); } } StructureValue structureValue = logEventValue as StructureValue; if (structureValue != null) { IDictionary <string, object> structureResult = new Dictionary <string, object>(structureValue.Properties.Count); foreach (var property in structureValue.Properties) { structureResult[property.Name] = ToRawScalar(property.Value); } if (structureResult.Count == structureValue.Properties.Count) { if (structureValue.TypeTag != null) { structureResult["$type"] = structureValue.TypeTag; } return(structureResult); } } DictionaryValue dictionaryValue = logEventValue as DictionaryValue; if (dictionaryValue != null) { IDictionary <string, object> dictionaryResult = dictionaryValue.Elements .Where(kvPair => kvPair.Key.Value is string) .ToDictionary(kvPair => (string)kvPair.Key.Value, kvPair => ToRawScalar(kvPair.Value)); if (dictionaryResult.Count == dictionaryValue.Elements.Count) { return(dictionaryResult); } } // Fall back to string rendering of the value return(logEventValue.ToString()); }
/// <summary> /// Checks a <see cref="LogEventPropertyValue"/> to have the correct data value type. /// </summary> /// <param name="receivedPropertyName">The key to use when writing the data value as GELF property.</param> /// <param name="property">The <see cref="LogEventPropertyValue"/> containing the data value.</param> /// <returns>A <see cref="GraylogPropertyCheckResult"/> with the check result.</returns> public GraylogPropertyCheckResult CheckProperty(string receivedPropertyName, LogEventPropertyValue property) { var res = new GraylogPropertyCheckResult { ReceivedPropertyName = receivedPropertyName }; var pos = IndexOfKey(receivedPropertyName); if (pos == -1) { res.CheckResult |= GraylogPropertyCheckResultType.ErrorNameNotRegistered; return(res); } res.ExpectedPropertyName = Keys[pos]; if (!receivedPropertyName.Equals(res.ExpectedPropertyName)) { res.CheckResult |= GraylogPropertyCheckResultType.ErrorNameSpelling; } res.PropertyValue = GetValue(property, out var receivedType); var expectedType = Values[pos]; if (expectedType == GraylogPropertyType.Object && receivedType != GraylogPropertyType.String || !expectedType.HasFlag(receivedType)) { res.CheckResult |= GraylogPropertyCheckResultType.ErrorValueTypeNotMatching; res.ExpectedValueType = expectedType; res.ReceivedValueType = receivedType; } return(res); }
/// <inheritdoc/> public void Format(LogEvent logEvent, TextWriter output) { if (logEvent == null) { throw new ArgumentNullException(nameof(logEvent)); } if (output == null) { throw new ArgumentNullException(nameof(output)); } output.Write("{\"time\":\""); output.Write(logEvent.Timestamp.ToEpoch().ToString(CultureInfo.InvariantCulture)); output.Write("\",\"event\":{\"Severity\":\""); output.Write(logEvent.Level); output.Write('"'); // Configure common event source properties LogEventPropertyValue eventName = null; foreach (var eventSourcePropertyName in EventSourceProperties) { if (logEvent.Properties.TryGetValue(eventSourcePropertyName, out eventName)) { if (eventSourcePropertyName == "SourceContext") { output.Write($",\"LoggerName\":"); } else { output.Write($",\"{eventSourcePropertyName}\":"); } ValueFormatter.Format(eventName, output); } } if (logEvent.Exception != null) { output.Write(",\"Exception\":"); JsonValueFormatter.WriteQuotedJsonString(logEvent.Exception.ToString(), output); } var propertiesToRender = logEvent.Properties.Where(IsRenderedProperty); if (propertiesToRender.Count() != 0) { WriteProperties(propertiesToRender, output); } var message = logEvent.RenderMessage(null); if (!(string.IsNullOrWhiteSpace(message) || message == EventLogger.EventDataTemplate)) { output.Write(",\"Message\":"); JsonValueFormatter.WriteQuotedJsonString(message, output); } output.WriteLine(suffix); }
private int GetIntValue(LogEventPropertyValue value) { if (value is ScalarValue scalar) { return((int)scalar.Value); } return(0); }
private string GetTextValue(LogEventPropertyValue value) { if (value is ScalarValue scalar) { return(scalar.Value.ToString()); } return(""); }
public static void HasPropertyValue(object propertyValue, string propertyName, LogEvent logEvent) { HasProperty(propertyName, logEvent); LogEventPropertyValue value = logEvent.Properties[propertyName]; Assert.That(value.LiteralValue(), Is.EqualTo(propertyValue), "The property value was not as expected"); }
private static object GetPropertyValue(LogEventPropertyValue propertyValue) { return(propertyValue switch { SequenceValue sequenceValue => sequenceValue.Elements.Select(RenderSequenceValue).ToArray(), ScalarValue scalarValue => scalarValue.Value, _ => propertyValue.ToString() });
/// <summary> /// Visit a value of an unsupported type. /// </summary> /// <param name="state">Operation state.</param> /// <param name="value">The value to visit.</param> /// <returns>The result of visiting <paramref name="value"/>.</returns> // ReSharper disable once UnusedParameter.Global // ReSharper disable once VirtualMemberNeverOverriden.Global protected virtual TResult VisitUnsupportedValue(TState state, LogEventPropertyValue value) { if (value == null) { throw new ArgumentNullException(nameof(value)); } throw new NotSupportedException($"The value {value} is not of a type supported by this visitor."); }
public static bool CoerceToScalarBoolean(LogEventPropertyValue value) { if (value is ScalarValue sv && sv.Value is bool b) { return(b); } return(false); }
static string Format(LogEventPropertyValue value) { var formatter = new TestThemedJsonValueFormatter(); var output = new StringWriter(); formatter.Format(value, output, null); return(output.ToString()); }
public static bool MatchesStringRepresentationOfLogEventPropertyValue( string expectedValue, LogEventPropertyValue property) { var actualValue = ExtractStringRepresentationOfLogEventPropertyValue(property); var valueMatches = actualValue.Equals(expectedValue, StringComparison.InvariantCultureIgnoreCase); return(valueMatches); }
public static string AsString(this LogEventPropertyValue propertyValue) { if (!(propertyValue is ScalarValue scalar)) { return(null); } // Handle string values differently as the ToString() method will wrap the string in unwanted quotes return(scalar.Value is string s ? s : scalar.ToString()); }
public static object[] SequenceValues(this LogEventPropertyValue @this) { if (@this is SequenceValue sequenceValue) { return(sequenceValue.Elements.Select(x => x.LiteralValue()).ToArray()); } return(null); }