12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- [[painless-debugging]]
- === Painless Debugging
- ==== Debug.Explain
- Painless doesn't have a
- https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop[REPL]
- and while it'd be nice for it to have one day, it wouldn't tell you the
- whole story around debugging painless scripts embedded in Elasticsearch because
- the data that the scripts have access to or "context" is so important. For now
- the best way to debug embedded scripts is by throwing exceptions at choice
- places. While you can throw your own exceptions
- (`throw new Exception('whatever')`), Painless's sandbox prevents you from
- accessing useful information like the type of an object. So Painless has a
- utility method, `Debug.explain` which throws the exception for you. For
- example, you can use {ref}/search-explain.html[`_explain`] to explore the
- context available to a {ref}/query-dsl-script-query.html[script query].
- [source,js]
- ---------------------------------------------------------
- PUT /hockey/player/1?refresh
- {"first":"johnny","last":"gaudreau","goals":[9,27,1],"assists":[17,46,0],"gp":[26,82,1]}
- POST /hockey/player/1/_explain
- {
- "query": {
- "script": {
- "script": "Debug.explain(doc.goals)"
- }
- }
- }
- ---------------------------------------------------------
- // CONSOLE
- // TEST[s/_explain/_explain?error_trace=false/ catch:/painless_explain_error/]
- // The test system sends error_trace=true by default for easier debugging so
- // we have to override it to get a normal shaped response
- Which shows that the class of `doc.first` is
- `org.elasticsearch.index.fielddata.ScriptDocValues.Longs` by responding with:
- [source,js]
- ---------------------------------------------------------
- {
- "error": {
- "type": "script_exception",
- "to_string": "[1, 9, 27]",
- "painless_class": "org.elasticsearch.index.fielddata.ScriptDocValues.Longs",
- "java_class": "org.elasticsearch.index.fielddata.ScriptDocValues$Longs",
- ...
- },
- "status": 400
- }
- ---------------------------------------------------------
- // TESTRESPONSE[s/\.\.\./"script_stack": $body.error.script_stack, "script": $body.error.script, "lang": $body.error.lang, "caused_by": $body.error.caused_by, "root_cause": $body.error.root_cause, "reason": $body.error.reason/]
- You can use the same trick to see that `_source` is a `LinkedHashMap`
- in the `_update` API:
- [source,js]
- ---------------------------------------------------------
- POST /hockey/player/1/_update
- {
- "script": "Debug.explain(ctx._source)"
- }
- ---------------------------------------------------------
- // CONSOLE
- // TEST[continued s/_update/_update?error_trace=false/ catch:/painless_explain_error/]
- The response looks like:
- [source,js]
- ---------------------------------------------------------
- {
- "error" : {
- "root_cause": ...,
- "type": "illegal_argument_exception",
- "reason": "failed to execute script",
- "caused_by": {
- "type": "script_exception",
- "to_string": "{gp=[26, 82, 1], last=gaudreau, assists=[17, 46, 0], first=johnny, goals=[9, 27, 1]}",
- "painless_class": "java.util.LinkedHashMap",
- "java_class": "java.util.LinkedHashMap",
- ...
- }
- },
- "status": 400
- }
- ---------------------------------------------------------
- // TESTRESPONSE[s/"root_cause": \.\.\./"root_cause": $body.error.root_cause/]
- // TESTRESPONSE[s/\.\.\./"script_stack": $body.error.caused_by.script_stack, "script": $body.error.caused_by.script, "lang": $body.error.caused_by.lang, "caused_by": $body.error.caused_by.caused_by, "reason": $body.error.caused_by.reason/]
- // TESTRESPONSE[s/"to_string": ".+"/"to_string": $body.error.caused_by.to_string/]
- Once you have a class you can go to <<painless-api-reference>> to see a list of
- available methods.
|