对Cassandra C#驱动程序进行故障排除,包括查看CQL语句



我们有一个ASP.NET 4.5 webapi解决方案,它将数据写入Cassandra。我们遇到了删除操作不起作用的问题。我们想看看引擎盖下的C#驱动程序是怎么回事。我们已经将CassandraTraceSwitch设置为Verbose,但它不会提供太多有用的数据。我想看看它对Cassandra生成和执行的实际查询,以及它得到的响应。

没有办法输出生成的查询,但这是一个好主意。

我已经创建了一个票证,以便在跟踪级别为Verbose时将生成的查询包含在输出中,您可以跟踪JIRA的进度或发送请求。

只是一个想法。它并不能完全回答最初的问题,但可能会有所帮助。您可以创建DispatchProxy并拦截CQL查询。我这样做

using Cassandra;
using System;
using System.Reflection;
using Cassandra.Data.Linq;
using Wpfe.Logging;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
namespace Wpfe.Storage {
    public class QueryTracingProxy<T> : DispatchProxy where T : class {
        private static readonly ILogger _logger = AppLogFactory.CreateLogger("Wpfe.StorageQuery");
        static Lazy<PropertyInfo> cqlPropertyInfo = new Lazy<PropertyInfo>(
            () => typeof(PreparedStatement).GetProperty("Cql", BindingFlags.NonPublic | BindingFlags.Instance));
        public T Target { get; private set; }
        public static T Decorate(T target) {
            var proxy = Create<T, QueryTracingProxy<T>>() as QueryTracingProxy<T>;
            proxy.Target = target;
            return proxy as T;
        }
        [DebuggerStepThrough]
        protected override object Invoke(MethodInfo targetMethod, object[] args) {
            try {
                if (targetMethod.Name.Equals(nameof(ISession.Execute))) {
                    if (args.Length > 0) {
                        var arg1 = args[0];
                        if (arg1 is string) {
                            var str = (string)arg1;
                            _logger.LogInformation(str);
                        }
                        else if (arg1 is CqlCommand) {
                            var cmd = (CqlCommand)arg1;
                            var values = string.Join("n", cmd.QueryValues);
                            _logger.LogInformation(string.Concat(cmd.QueryString, "n", values));
                        }
                    }
                }
                else if (targetMethod.Name.Equals(nameof(ISession.ExecuteAsync)) && args.Length == 1) {
                    var statement = args[0] as BoundStatement;
                    if (statement != null) {
                        var preparedStatement = statement.PreparedStatement;
                        if (preparedStatement != null) {
                            var cql = cqlPropertyInfo.Value.GetValue(preparedStatement);
                            var values = string.Join("n", statement.QueryValues);
                            _logger.LogInformation(string.Concat(cql, "n", values));
                        }
                    }
                }
                var result = targetMethod.Invoke(Target, args);
                return result;
            }
            catch (TargetInvocationException exc) {
                throw exc.InnerException;
            }
        }
    }
    public static class QueryTracer {
        private static readonly ILogger _logger = AppLogFactory.CreateLogger("Wpfe.StorageQuery");
        public static ISession HookUp(ISession session) {
            if (_logger.IsEnabled(LogLevel.Information) || _logger.IsEnabled(LogLevel.Debug)) {
                var proxy = QueryTracingProxy<ISession>.Decorate(session);
                return proxy;
            }
            return session;
        }
    }
}

然后在代码中,我只是装饰ISession实例,即

private static ISession createDefaultSession() {
   var cluster = EntityManagerFactory.BuildCluster(StorageGlobalOptions.Value.DatabaseEffective);
   var session = cluster.Connect();
   return QueryTracer.HookUp(session);
}

最新更新