Expressions

To use eXvisory dev you configure logic rules from a limited palette of logic rule types (faults, fault groups, eliminators, query tests and synthetic tests) and fit them together into a visual fault containment hierarchy that models how experts troubleshoot product support issues. This page describes how these logic rules inter-connect via conditions, variables and logic expressions.

Conditions

Evaluating each of the logic rule types typically evaluates a set of tests (defined in the logic rule's conditions clause), assigns the results of these tests to variables and combines these variables in logic expressions to obtain a result for the logic rule. This is just like an expert troubleshooter performing a series of diagnostic tests and combining the results to arrive at a conclusion.

Let's look at an example:

  • In the fault containment hierarchy click on the cell node (it's below device and network in the hierarchy) to select and zoom in on it.

  • On the right hand side of the editor select the Tests tab and use the pulldown menus to select the cell activity text variant.

  • The editor should look like the screenshot below.

Example logic expression: cell activity text

Cell activity text is a synthetic test (a test that combines the results of other tests) that evaluates the three tests listed in its conditions clause. The first condition is a special variant condition, which we'll ingore for now because it's covered in Variants. The second messaging type test returns the kind of messaging app being used and assigns it to the variable ?type. The third messaging subsymptom test asks the user for messaging-related symptoms and stores the result in the variable ?subsymptom.

eXvisory variables begin with a ? character (and by convention have the same name as the label of the test from which they are assigned). The ? prefix means evaluate the condition (if not already evaluated). An alternative $ prefix means only assign the variable if the condition has already been evaluated.

The result of the cell activity text synthetic test combines the second and third test conditions using a logic expression that refers to the ?type and ?subsymptom variables. The great thing about logic expressions is that they are quite readable. The cell activity text synthetic test deduces that there must be cell activity if the problem relates to text messages (?type equals the string "msg_text") AND the messaging-related symptom is NOT no messages at all.

Variables

eXvisory is like a programming language, with a constrained syntax to keep a lid on complexity. All logic variables are basically strings, but can be interpreted in three different ways:

  • Text For example the device user sample test is a query test that prompts the user for their name and returns it as a simple text string. Text strings cannot be used in logic expressions.

  • Multiple choice For example the messaging type sample test is a query test that prompts the user for the type of messaging app they are using. It returns a string from a list of logic values ("msg_email", "msg_text", "msg_text_wifi" or "msg_app"). These values are used in logic expressions but should not be presented to the user. The messaging type sample test defines resources with user-legible choices corresponding to each of the logic values.

  • Boolean For an example see the device roaming sample query test. A special case of multiple choice with logic values "y" and "n" and default choices "Yes" and "No". Boolean logic values can appear in logic expressions and in some contexts are written as "TRUE" or "FALSE" ("TRUE" corresponds to "y").

Variables returned by test conditions are prefixed with ? or $ symbols. See Conditions.

Functions

eXvisory defines a familar set of logic functions (using LISP syntax) that can operate on logic variables within logic expressions. All logic functions return a boolean value and operands can themselves be logic functions.

Function

Variables

Returns

exists

variable

TRUE if variable has been evaluated.

Example: (exists ?browser_name)

is

boolean

TRUE if operand is TRUE.

Example: (is ?connected)

not

boolean

TRUE if operand is FALSE.

Example: (not ?enabled)

and

>= 1 booleans

TRUE if all operands are TRUE.

Example: (and ?connected ?enabled)

or

>= 1 booleans

TRUE if any of the operands are TRUE.

Example: (or ?disabled ?disconnected)

eq

variable

literal

TRUE if variable equals literal. Comparisons are case-insensitive (except for special FOUND, SCOPED, ELIMINATED and UNKOWN literals). Use is or not for boolean variables.

Examples: (eq ?symptom no_internet)

neq

variable

literal

TRUE if variable does not equal literal. Comparisons are case-insensitive (except for special FOUND, SCOPED, ELIMINATED and UNKOWN literals). Use is or not for boolean variables.

Examples: (neq ?symptom internet)

any

variable

>=1 literals

TRUE if variable eq any of the literals.

Example: (any ?symptom call browser messaging)

none

variable

>=1 literals

TRUE if variable neq all of the literals.

Example: (none ?symptom call browser messaging)

webhook

none

Invokes a webhook (if configured) to obtain information from another cloud service. Returns a logic variable.

Example: (webhook)

Expressions

eXvisory logic expressions uses syntax from the famous LISP AI programming language. It's a little different from logic expressions in more popular programming languages like Javascript, Java or Python but with practice it's actually easier to understand.

Let's look at some logic expressions at https://dev.exvisory.ai/apps/sample-mobile. First a simple one from the audio has_mute sample synthetic test (search in eXvisory dev for "mute").

{
"_class" : "audio",
"label" : "has_mute",
"comment" : "TRUE if device has a mute switch",
"conditions" : [
{ "_class" : "device", "label" : "os", "result" : "?os" }
],
"result" : "(eq ?os ios)"
}

The device os query test condition returns a multiple choice logic value (right-click on the condition to Goto and inspect the test and use the button to return). Most logic expressions are enclosed in parentheses, which is LISP syntax for a function. In this case the function eq compares the variable ?os with the string ios and returns the boolean value "TRUE" if they are equal ("FALSE" if they are not).

String values in logic expressions do not use quotes.

Now a couple of even simpler logic expressions (from the sample tests audio mute not_supported and hotspot cellular_data)

"result" : "FALSE"
"result" : "?browse",

These logic expressions don't have parentheses because they immediately evaluate to either a logic constant (in this case the boolean logic constant "FALSE") or the value of a logic variable (in this case the logic variable ?browse from a hotspot cellular_data condition. ?browse is a boolean logic variable so an equivalent but preferred way of writing this logic expression would be (is ?browse). The function is returns "TRUE" if the variable ?browse is boolean and "TRUE", which is easier to read.

Now a more complicated logic expression from the browser protocol sample test.

"result" : "(or (not ?http_public) (not ?https_public))"

The variables ?http_public and ?https_public contain boolean values and the logic expression is a little more complicated because it has nested parentheses. Expressions within paretheses are evaluated first, then their containing expressions, etc. So this logic expression means "return TRUE if the user cannot browse to public HTTP sites or the user cannot browse to public HTTPS sites".

Resource expressions

Resources are a special kind of logic expression, which can refer to logic rule resources.

Resource expressions are potentially very powerful (because of the expressivity of resource templates) but we recommend keeping them simple, so that your deep logic network remains legible at scale.

Here's a sample resource expression from a device which query test in our sample https://dev.exvisory.ai/apps/sample-mobile.

device which (query test) at https://dev.exvisory.ai/apps/sample-mobile
{
"_class" : "device",
"label" : "which",
"comment" : "identify device",
"conditions" : [
{ "_class" : "device", "label" : "os", "result" : "?os" },
{ "_class" : "device", "label" : "os_version", "result" : "?os_version" },
{ "_class" : "device", "label" : "type", "result" : "?type" },
{ "_class" : "device", "label" : "make", "result" : "?make" },
{ "_class" : "device", "label" : "model", "result" : "?model" }
],
"result" : "x_test_device_which_make_model",
"resources" : {
"make_model" : "{{ device_make }} {{ device_model }}",
"pre_help" : [
"I need to ask you some questions about your mobile device."
],
"result" : [
"Thanks, that's enough device questions for now. ",
"Let's get back to troubleshooting your problem ",
"by checking {{ device_which}} settings and performing tests."
]
}
}

The test result "x_test_device_which_make_model" is a resource expression. Resource expressions begin with "x_test_", followed by the test "<_class>_<label>" and a resource key (in this example "make_model"). The resource is evaluated (it will normally use templates to refer to the results of previous logic rule evaluations) to give the result of the resource expression.

In this example the "x_test_device_which_make_model" resource expression evaluates to a string containing the make and model of a mobile device, for example "Apple iPhone".