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

时间:2016-01-04 21:19:28

标签: c# cassandra cql cassandra-2.0

我们有一个ASP.NET 4.5 webapi解决方案,它将数据写入Cassandra。我们遇到了删除操作无法正常工作的问题。我们希望了解C#驱动程序的内容。我们已将CassandraTraceSwitch设置为详细,但它并未提供有用的数据。我希望看到它对Cassandra产生和执行的实际查询,以及它回复的响应。

2 个答案:

答案 0 :(得分:3)

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

我在跟踪级别为Verbose时创建了ticket to include the generated query in the output,您可以关注JIRA的进度或发送拉取请求。

答案 1 :(得分:1)

就像一个想法。它没有完全回答原始问题,但可能会有所帮助。您可以创建 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);
}