How can I include query named parameters with AmbiguousTimeoutException?

When a query times out, we see the following log that is quite helpful during debugging:

Caused by: com.couchbase.client.core.error.AmbiguousTimeoutException: QueryRequest, Reason:TIMEOUT

{
  "cancelled": true,
  "completed": true,
  "coreId": "0x46aeb94a00000002",
  "idempotent": false,
  "lastDispatchedFrom": "redacted",
  "lastDispatchedTo": "redacted",
  "reason": "TIMEOUT",
  "requestId": 2695402,
  "requestType": "QueryRequest",
  "retried": 0,
  "service": {
    "operationId": "myOperationID",
    "statement": "select id as ids from MyBucket USE KEYS $metaId",
    "type": "query"
  },
  "timeoutMs": 500,
  "timings": {
    "totalMicros": 509745
  }
}

While the log is very helpful as is, it would be even more helpful if we had another field with the values for metaId so that we can run the query manually if needed

Is there any option to accomplish this? Can we create a feature request if it doesn’t?

Thanks

Hi @yk010123
You can use the clientContextId field for this if you like. It’s meant to be a way for the client (your app) to uniquely identify a particular request, so this is a slight abuse of the intent, but it will work.

        QueryResult result = cluster.query("select 'hello world' as Greeting", queryOptions()
                .clientContextId("metaId = ab23ca, anotherField = XYZ"));

You’ll then see a “clientContext” field in the error context. You can also retrieve it from the QueryResult if needed (in result.metaData()).

Is there any other solution?

Unfortunately I am currently using the clientContextId for a different use case

Can we extend AmbiguousTimeoutException to include this information?

You could certainly extend AmbiguousTimeoutException but of course the SDK would (unless you patched it, it’s open source) raise the unextended original.

Since clientContextId is an arbritary string, can you maybe handle it as JSON, and encode both your current use-case and the parameters in there? Or use it as a UUID indexing into a map with the values being a blob of all the info you need - something like that?

Alternatively you could surround the cluster.query() with a try-catch and logging whatever info you want on failure.

Do you know what would be the process to request this as a SDK native feature? (can I send a PR?)

This information is probably useful for other people besides my team

Yes, you can submit PR or open feature request ticket in our Jira. Guidance for both are in the contributing guide here.

If the latter it would be particular useful to get precise details on the desired behaviour. E.g. would you like all query parameters to be automatically injected into the error context, or instead the ability to insert whatever arbritrary fields you wanted (e.g. along the lines of the existing clientContextId, but extended). It would also be good to understand why the proposed workaround of encoding JSON into the clientContextId is unsuitable for your needs.

2 Likes

I can try to add it to the clientContextId if you think that clientContextId is a good field for this. To me, it sounds that it should be a separate field, but I trust your judgment

The Javadocs for clientContextId are

  /** Adds a client context ID to the request, that will be sent back in the response, allowing clients
    * to meaningfully trace requests/responses when many are exchanged.

e.g. we more intended it to be a unique identifier that an application could link up with e.g. a blob of information, or to send an existing unique request identifier through for logging help. But intent aside, it’s a string from the app that we’re going to pass straight-through, so putting arbritrary data in there (like a JSON blob) will work fine.