Skip to content

Instantly share code, notes, and snippets.

@Skamiplan
Created May 7, 2019 14:22
Show Gist options
  • Save Skamiplan/5f42eb1efe78aecd7febc099efc2214a to your computer and use it in GitHub Desktop.
Save Skamiplan/5f42eb1efe78aecd7febc099efc2214a to your computer and use it in GitHub Desktop.
internal class MongoTracking
{
private readonly Action<CommandStartedEvent> onCommandStartEvent;
private readonly Action<CommandSucceededEvent> onCommandSucceededEvent;
private readonly Action<CommandFailedEvent> onCommandFailedEvent;
private IEnumerable<string> NotTrackedCommands { get; } = new[]
{"isMaster", "buildInfo", "getLastError", "saslStart", "saslContinue"};
private readonly ConcurrentDictionary<int, string> queriesBuffer = new ConcurrentDictionary<int, string>();
private ILog logger;
public MongoTracking()
{
var notTrackedCommands = this.NotTrackedCommands.Select(v => v.ToLower()).ToImmutableHashSet();
this.onCommandStartEvent = e =>
{
try
{
if (e.Command != null && !notTrackedCommands.Contains(e.CommandName.ToLower()))
{
// ReSharper disable once SpecifyACultureInStringConversionExplicitly
this.queriesBuffer.TryAdd(e.RequestId, e.Command.ToString());
}
}
catch (Exception exception)
{
this.logger?.Error(exception);
}
};
this.onCommandSucceededEvent = e =>
{
if (notTrackedCommands.Contains(e.CommandName.ToLower()))
return;
try
{
if (this.queriesBuffer.TryRemove(e.RequestId, out var query))
{
this.OnCommandCompleted(
new MongoCommandCompletedEventArgs(e.CommandName, query, true,
e.Duration));
}
}
catch (Exception exception)
{
this.logger?.Error(exception);
}
};
this.onCommandFailedEvent = e =>
{
if (notTrackedCommands.Contains(e.CommandName.ToLower()))
return;
try
{
if (this.queriesBuffer.TryRemove(e.RequestId, out var query))
this.OnCommandCompleted(
new MongoCommandCompletedEventArgs(e.CommandName, query, false,
e.Duration));
}
catch (Exception exception)
{
this.logger?.Error(exception);
}
};
}
private void OnCommandCompleted(MongoCommandCompletedEventArgs args)
{
if (this.logger == null)
{
this.logger = (ILog)BuilderExtension.ServiceProvider.GetService(typeof(ILog));
}
this.logger?.Debug($"{args.CommandName} {args.Query} {args.Success} {args.Duration}");
}
private class MongoCommandCompletedEventArgs : EventArgs
{
public MongoCommandCompletedEventArgs(string commandName, string query, bool success, TimeSpan duration)
{
this.CommandName = commandName;
this.Query = query;
this.Success = success;
this.Duration = duration;
}
public string CommandName { get; }
public string Query { get; }
public bool Success { get; }
public TimeSpan Duration { get; }
}
public void ConfigureTracking(MongoClientSettings clientSettings)
{
clientSettings.ClusterConfigurator += cb =>
{
cb.Subscribe(this.onCommandStartEvent);
cb.Subscribe(this.onCommandSucceededEvent);
cb.Subscribe(this.onCommandFailedEvent);
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment