2

We have a ASP.NET 4.5 webapi solution, which writes data to Cassandra. We are having an issue with a delete operation not working. We'd like to see what is going on with the C# driver under the hood. We've set the CassandraTraceSwitch to Verbose, but it doesn't give much useful data. I'd like to see the actual queries it's generating and executing against Cassandra, as well as the response it gets back.

Dan Csharpster
  • 2,662
  • 1
  • 26
  • 50
  • I've been looking through the source for the driver and do not any anything beyond tracing that they allow. We were able to solve our problem by debugging into the source. There is a known bug that cached statements are not differentiated across keyspaces, so our statement was not getting executed. Setting NoPrepare to true worked around our problem for now. – Dan Csharpster Jan 05 '16 at 20:59
  • [I see that you found the underlying issue](http://stackoverflow.com/a/34723969/208683), cool! – jorgebg Jan 11 '16 at 14:38

2 Answers2

4

There is no way to output the query generated, but it is a good idea.

I've created a ticket to include the generated query in the output when the trace level is Verbose, you can follow the progress on JIRA or send a pull request for it.

jorgebg
  • 6,560
  • 1
  • 22
  • 31
  • Thanks! I cloned the repo and found the place in code where I would add it. I was considering creating a pull request for it. Maybe I could link that to your ticket – Dan Csharpster Jan 11 '16 at 19:45
1

Just as an idea. It does not fully answer original question but might help. You can create DispatchProxy and intercept CQL queries. I do it this way

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;
        }
    }
}

Then in code I just decorate ISession instance, i.e.

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

Stanislav Berkov
  • 5,929
  • 2
  • 30
  • 36