Skip to content
This repository has been archived by the owner on Jun 1, 2024. It is now read-only.

String fromatter #283

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Serilog.Events;
using Serilog.Formatting.Elasticsearch;

namespace Host
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change the namespace?

{
/// <summary>
/// A JSON formatter which ensures no type conflicts arieses in Elasticsearch by casting everything to strings.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo. arieses -> arises.

///
/// Note that using this formatter comes at the cost that the exception tree
/// with inner exceptions can grow deep.
/// </summary>
public class ElasticsearchStringifyFormatter : ExceptionAsObjectJsonFormatter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The power of ES is that it can understand the different types. Although I understand what you want here, it reduces functionality in order to fix another issue. A formatter that prefixes the type I can see living in this repository, this class is a small addition for specific use cases. Can it not exist only in your project (or a separate nuget package)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know this was possible and would've loved if it was a part of the original package! Very cool, and solves my issue as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know this was possible and would've loved if it was a part of the original package! Very cool, and solves my issue as well.

Are you then okay with closing this PR and use it directly from your code only?

{
/// <summary>
/// Construct a <see cref="ElasticsearchJsonFormatter"/>.
/// </summary>
/// <param name="omitEnclosingObject">If true, the properties of the event will be written to
/// the output without enclosing braces. Otherwise, if false, each event will be written as a well-formed
/// JSON object.</param>
/// <param name="closingDelimiter">A string that will be written after each log event is formatted.
/// If null, <see cref="Environment.NewLine"/> will be used. Ignored if <paramref name="omitEnclosingObject"/>
/// is true.</param>
/// <param name="renderMessage">If true, the message will be rendered and written to the output as a
/// property named RenderedMessage.</param>
/// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
/// <param name="serializer">Inject a serializer to force objects to be serialized over being ToString()</param>
/// <param name="inlineFields">When set to true values will be written at the root of the json document</param>
/// <param name="formatStackTraceAsArray">If true, splits the StackTrace by new line and writes it as a an array of strings</param>
/// <param name="renderMessageTemplate">If true, the message template will be rendered and written to the output as a
/// property named RenderedMessageTemplate.</param>
public ElasticsearchStringifyFormatter(
bool omitEnclosingObject = false,
string closingDelimiter = null,
bool renderMessage = true,
IFormatProvider formatProvider = null,
ISerializer serializer = null,
bool inlineFields = false,
bool formatStackTraceAsArray = false,
bool renderMessageTemplate = true) : base(omitEnclosingObject, closingDelimiter, renderMessage,
formatProvider, serializer, inlineFields, formatStackTraceAsArray, renderMessageTemplate)
{
}

/// <summary>
/// Writes out the attached exception
/// </summary>
protected override void WriteProperties(
IReadOnlyDictionary<string, LogEventPropertyValue> properties, TextWriter output) =>
base.WriteProperties(Stringify(properties), output);

private static IReadOnlyDictionary<string, LogEventPropertyValue> Stringify(
IReadOnlyDictionary<string, LogEventPropertyValue> properties) =>
properties.ToDictionary(entry => entry.Key, entry => Stringify(entry.Value));

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");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,18 @@ public class ExceptionAsObjectJsonFormatter : ElasticsearchJsonFormatter
/// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
/// <param name="serializer">Inject a serializer to force objects to be serialized over being ToString()</param>
/// <param name="inlineFields">When set to true values will be written at the root of the json document</param>
/// <param name="renderMessageTemplate">If true, the message template will be rendered and written to the output as a
/// property named RenderedMessageTemplate.</param>
/// <param name="formatStackTraceAsArray">If true, splits the StackTrace by new line and writes it as a an array of strings</param>
public ExceptionAsObjectJsonFormatter(bool omitEnclosingObject = false,
string closingDelimiter = null,
bool renderMessage = false,
IFormatProvider formatProvider = null,
ISerializer serializer = null,
bool inlineFields = false,
bool formatStackTraceAsArray = false)
: base(omitEnclosingObject, closingDelimiter, renderMessage, formatProvider, serializer, inlineFields, true, formatStackTraceAsArray)
bool formatStackTraceAsArray = false,
bool renderMessageTemplate = true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change; introducing a new (even optional) parameter. Why do you want to change this?

: base(omitEnclosingObject, closingDelimiter, renderMessage, formatProvider, serializer, inlineFields, renderMessageTemplate, formatStackTraceAsArray)
{
}

Expand Down