Skip to content

Commit

Permalink
Merge branch 'release/v5.2.1' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaben committed Sep 3, 2022
2 parents 17467c1 + b7877f7 commit b670fa3
Show file tree
Hide file tree
Showing 17 changed files with 880 additions and 875 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ jobs:

- name: Pack
run: dotnet pack -c Release -p:PackageVersion=${{ steps.gitversion.outputs.nuGetVersion }} -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
# && (github.ref_name == 'master')

- name: Publish
if: github.event_name != 'pull_request'
if: github.event_name != 'pull_request' && (github.ref_name == 'master')
run: |
dotnet nuget push **/*.nupkg --source 'https://api.nuget.org/v3/index.json' -k ${{ secrets.NUGETKEY }}
118 changes: 53 additions & 65 deletions src/Serilog.Sinks.MongoDB/Helpers/MongoDbDocumentHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,79 +19,67 @@

using Serilog.Events;

namespace Serilog.Helpers
namespace Serilog.Helpers;

internal static class MongoDbDocumentHelpers
{
internal static class MongoDbDocumentHelpers
/// <summary>
/// Credit to @IvaskevychYuriy for this excellent solution:
/// https://github.com/ChangemakerStudios/serilog-sinks-mongodb/pull/59#issuecomment-830079904
/// </summary>
/// <param name="document"></param>
/// <returns></returns>
internal static BsonDocument SanitizeDocumentRecursive(this BsonDocument document)
{
/// <summary>
/// Credit to @IvaskevychYuriy for this excellent solution:
/// https://github.com/ChangemakerStudios/serilog-sinks-mongodb/pull/59#issuecomment-830079904
/// </summary>
/// <param name="document"></param>
/// <returns></returns>
internal static BsonDocument SanitizeDocumentRecursive(this BsonDocument document)
{
if (document == null) throw new ArgumentNullException(nameof(document));
if (document == null) throw new ArgumentNullException(nameof(document));

var sanitizedElements = document.Select(
e => new BsonElement(
SanitizedElementName(e.Name),
e.Value.IsBsonDocument
? SanitizeDocumentRecursive(e.Value.AsBsonDocument)
: e.Value));
var sanitizedElements = document.Select(
e => new BsonElement(
SanitizedElementName(e.Name),
e.Value.IsBsonDocument
? SanitizeDocumentRecursive(e.Value.AsBsonDocument)
: e.Value));

return new BsonDocument(sanitizedElements);
}
return new BsonDocument(sanitizedElements);
}

internal static string SanitizedElementName(this string? name)
{
if (name == null) return "[NULL]";
internal static string SanitizedElementName(this string? name)
{
if (name == null) return "[NULL]";

return name.Replace('.', '-').Replace('$', '_');
}
return name.Replace('.', '-').Replace('$', '_');
}

internal static BsonValue? ToBsonValue(this LogEventPropertyValue? value)
internal static BsonValue? ToBsonValue(this LogEventPropertyValue? value)
{
if (value == null) return null;

if (value is ScalarValue scalar)
{
if (value == null) return null;

if (value is ScalarValue scalar)
{
if (scalar.Value is Uri uri)
{
return BsonValue.Create(uri.ToString());
}

if (scalar.Value is TimeSpan ts)
{
return BsonValue.Create(ts.ToString());
}

if (scalar.Value is DateTimeOffset dto)
{
return BsonValue.Create(dto.ToString());
}

return BsonValue.Create(scalar.Value);
}

if (value is StructureValue sv)
{
return BsonDocument.Create(
sv.Properties.ToDictionary(
s => SanitizedElementName(s.Name),
s => ToBsonValue(s.Value)));
}

if (value is DictionaryValue dv)
return BsonDocument.Create(
dv.Elements.ToDictionary(
s => SanitizedElementName(s.Key.Value?.ToString()),
s => ToBsonValue(s.Value)));

if (value is SequenceValue sq)
return BsonValue.Create(sq.Elements.Select(ToBsonValue).ToArray());

return null;
if (scalar.Value is Uri uri) return BsonValue.Create(uri.ToString());

if (scalar.Value is TimeSpan ts) return BsonValue.Create(ts.ToString());

if (scalar.Value is DateTimeOffset dto) return BsonValue.Create(dto.ToString());

return BsonValue.Create(scalar.Value);
}

if (value is StructureValue sv)
return BsonDocument.Create(
sv.Properties.ToDictionary(
s => SanitizedElementName(s.Name),
s => ToBsonValue(s.Value)));

if (value is DictionaryValue dv)
return BsonDocument.Create(
dv.Elements.ToDictionary(
s => SanitizedElementName(s.Key.Value?.ToString()),
s => ToBsonValue(s.Value)));

if (value is SequenceValue sq)
return BsonValue.Create(sq.Elements.Select(ToBsonValue).ToArray());

return null;
}
}
156 changes: 79 additions & 77 deletions src/Serilog.Sinks.MongoDB/Helpers/MongoDbHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,101 +20,103 @@
using Serilog.Debugging;
using Serilog.Sinks.MongoDB;

namespace Serilog.Helpers
namespace Serilog.Helpers;

internal static class MongoDbHelper
{
internal static class MongoDbHelper
/// <summary>
/// Returns true if a collection exists on the mongodb server.
/// </summary>
/// <param name="database">The database.</param>
/// <param name="collectionName">Name of the collection.</param>
/// <returns></returns>
internal static bool CollectionExists(this IMongoDatabase database, string collectionName)
{
var filter = new BsonDocument("name", collectionName);
var collectionCursor =
database.ListCollections(new ListCollectionsOptions { Filter = filter });
return collectionCursor.Any();
}

/// <summary>
/// Verifies the collection exists. If it doesn't, create it using the Collection Creation Options provided.
/// </summary>
/// <param name="database">The database.</param>
/// <param name="collectionName">Name of the collection.</param>
/// <param name="collectionCreationOptions">The collection creation options.</param>
internal static void VerifyCollectionExists(
this IMongoDatabase database,
string collectionName,
CreateCollectionOptions? collectionCreationOptions = null)
{
/// <summary>
/// Returns true if a collection exists on the mongodb server.
/// </summary>
/// <param name="database">The database.</param>
/// <param name="collectionName">Name of the collection.</param>
/// <returns></returns>
internal static bool CollectionExists(this IMongoDatabase database, string collectionName)
if (database == null) throw new ArgumentNullException(nameof(database));
if (collectionName == null) throw new ArgumentNullException(nameof(collectionName));

if (database.CollectionExists(collectionName)) return;

try
{
var filter = new BsonDocument("name", collectionName);
var collectionCursor =
database.ListCollections(new ListCollectionsOptions { Filter = filter });
return collectionCursor.Any();
database.CreateCollection(collectionName, collectionCreationOptions);
}
catch (MongoCommandException e) when (e.ErrorMessage.Contains(
"collection already exists",
StringComparison.InvariantCultureIgnoreCase))
{
// handled
}
}

internal static void VerifyExpireTTLSetup(
this IMongoDatabase database,
string collectionName,
TimeSpan? expireTtl)
{
const string ExpireTTLIndexName = "serilog_sink_expired_ttl";

var logCollection = database.GetCollection<LogEntry>(collectionName);

/// <summary>
/// Verifies the collection exists. If it doesn't, create it using the Collection Creation Options provided.
/// </summary>
/// <param name="database">The database.</param>
/// <param name="collectionName">Name of the collection.</param>
/// <param name="collectionCreationOptions">The collection creation options.</param>
internal static void VerifyCollectionExists(
this IMongoDatabase database,
string collectionName,
CreateCollectionOptions? collectionCreationOptions = null)
if (expireTtl.HasValue)
{
if (database == null) throw new ArgumentNullException(nameof(database));
if (collectionName == null) throw new ArgumentNullException(nameof(collectionName));
var indexKeysDefinition =
Builders<LogEntry>.IndexKeys.Ascending(s => s.UtcTimeStamp);
var indexOptions = new CreateIndexOptions
{ Name = ExpireTTLIndexName, ExpireAfter = expireTtl };
var indexModel = new CreateIndexModel<LogEntry>(indexKeysDefinition, indexOptions);

if (database.CollectionExists(collectionName)) return;
try
{
logCollection.Indexes.CreateOne(indexModel);

return;
}
catch (MongoCommandException ex) when (ex.ErrorMessage.Contains(
"already exists with different options"))
{
// handled -- just drop and recreate
logCollection.Indexes.DropOne(ExpireTTLIndexName);
}

try
{
database.CreateCollection(collectionName, collectionCreationOptions);
// delete the index and re-create since it exists with different expiration value
logCollection.Indexes.CreateOne(indexModel);
}
catch (MongoCommandException e) when (e.ErrorMessage.Contains("collection already exists"))
catch (MongoCommandException ex)
{
// handled
SelfLog.WriteLine(
"Failure dropping/creating MongoDB Expire TTL Index: {0}",
ex.ErrorMessage);
}
}

internal static void VerifyExpireTTLSetup(
this IMongoDatabase database,
string collectionName,
TimeSpan? expireTtl)
else
{
const string ExpireTTLIndexName = "serilog_sink_expired_ttl";

var logCollection = database.GetCollection<LogEntry>(collectionName);

if (expireTtl.HasValue)
// make sure the expire TTL index doesn't exist
try
{
var indexKeysDefinition =
Builders<LogEntry>.IndexKeys.Ascending(s => s.UtcTimeStamp);
var indexOptions = new CreateIndexOptions
{ Name = ExpireTTLIndexName, ExpireAfter = expireTtl };
var indexModel = new CreateIndexModel<LogEntry>(indexKeysDefinition, indexOptions);

try
{
logCollection.Indexes.CreateOne(indexModel);

return;
}
catch (MongoCommandException ex) when (ex.ErrorMessage.Contains("already exists with different options"))
{
// handled -- just drop and recreate
logCollection.Indexes.DropOne(ExpireTTLIndexName);
}

try
{
// delete the index and re-create since it exists with different expiration value
logCollection.Indexes.CreateOne(indexModel);
}
catch (MongoCommandException ex)
{
SelfLog.WriteLine(
"Failure dropping/creating MongoDB Expire TTL Index: {0}",
ex.ErrorMessage);
}
logCollection.Indexes.DropOne(ExpireTTLIndexName);
}
else
catch (MongoCommandException)
{
// make sure the expire TTL index doesn't exist
try
{
logCollection.Indexes.DropOne(ExpireTTLIndexName);
}
catch (MongoCommandException)
{
}
}
}
}
Expand Down
Loading

0 comments on commit b670fa3

Please sign in to comment.