Creating an investigation in Portal using NQL
Investigations along with the new Nexthink Query Language (NQL) are released as a technical preview.
Enabling and accessing Investigations technical preview
Follow instructions on Enabling and accessing investigations page to set proper access to the Investigations technical preview.
Executing a query
To execute a query (eg: “devices”), write it in the code editor and click on the Run button. The query returns the following results:

50 results are displayed by default, to reveal more results click on the Load more button at the bottom of the page. Another set of 50 results will be displayed.
Writing a query
Select the table
In NQL you always start by typing the name of the table you want to query.
Executing the query will select the default fields of the users table.
users
Name |
---|
nxt-gcarlisa |
nxt-wmirjam |
… |
list - select the fields
The list operator allows you to specify which fields you want to select. Between operators, the | delimiter is required.
Select the name, type, and user_id from the users table.
users
| list username, type
Name | Type |
---|---|
Hemi Charmian | LOCAL_USER |
Wangchuk Mirjam | LOCAL_ADMIN |
… | … |
asc, desc - sort the results
The asc and desc operators sort the results by a field in ascending or descending order, respectively.
Sort users by their name in ascending order.
users
| list username, type
| asc username
Name | Type |
---|---|
Alice Smith | LOCAL_USER |
Amanda Carella | LOCAL_ADMIN |
… | … |
Sort users by their name in descending order.
users
| list username, type, user_id
| desc username
Name | Type |
---|---|
Zion Bush | LOCAL_USER |
Zachary Doe | LOCAL_ADMIN |
… | … |
limit - request a maximum number of results
The limit operator will return the first N results requested.
Select the first 15 users, maximum.
users
| limit 15
Name | Type |
---|---|
Hemi Charmian | LOCAL_USER |
Wangchuk Mirjam | LOCAL_ADMIN |
… | … |
where - filter your results
The where operator allows you to add conditions to your query.
Select the devices which have the Windows platform.
devices
| where platform == Windows
Name | Platform |
---|---|
nxt-gcarlisa | Windows |
nxt-wmirjam | Windows |
Select the devices which don’t have the Windows platform.
devices
| where platform != Windows
| list name, platform
Name | Platform |
---|---|
nxt-jdoe | Mac |
nxt-vlatona | Mac |
Select the users whose name contains “abc”
users
| where username contains "jo"
Name |
---|
John Fisher |
John Doe |
compute - count your results
The compute operator allows you to count the number of results.
Count the number of devices will display by default a list of alias number_of_devices
containing the result of the count(). You can name number_of_devices
as you wish, for example, my_alias
devices
| compute number_of_devices = count()
number_of_devices |
---|
285 |
It is possible to compute by a field if it is supported.
Count the number of devices by platform will display by default a list number_of_devices
and the field which was used after.
devices
| compute number_of_devices = count() by platform
number_of_devices | Platform |
---|---|
41 | Windows |
244 | Mac |
compute - sum your fields
The compute operator allows you to count the sum of the value of a field across all results.
Sum the size of all the binaries
binaries
| compute total_size = executable_size.sum()
total_size |
---|
611.3G |
Bucketized event tables
Those are events aggregated over a period of time. For example, Application Experience will measure the navigations of users inside of a monitored web application. When there are multiple navigations from 9:00 to 9:15 it will bundle those with the same set of values together, in order to cope with the volume of data.
For appex.navigations events that have the same user, device, binary, application, and timeframe (9:00 - 9:15) will be grouped in the same bucket.
appex.navigations
| list device.name, user.username, binary.name, application.name
Device name | User name | Executable name | Application name |
---|---|---|---|
nxt-jdoe | John Doe | chrome.exe | Confluence |
nxt-vlatona | Vassily Latona | firefox.exe | Salesforce |
The following query returns the total number of navigations.
appex.navigations
| compute total_navigations = number_of_navigations.sum()
It will go inside each bucket, take the number_of_navigations and sum it among all buckets.
total_navigations |
---|
1.19M |
The following query returns the number_of_navigations per application.
appex.navigations
| compute total_navigations = number_of_navigations.sum() by application
total_navigations | Application name |
---|---|
18.9k | Zoom |
5.14k | Expensify |
1.93k | Aha! |
… | … |
You can also combine it with desc and limit to see the 10 most navigated applications.
appex.navigations
| compute total_navigations = number_of_navigations.sum() by application
| limit 10
| desc total_navigations
total_navigations | Application name |
---|---|
226.5k | Salesforce Lightning |
165.9k | |
85.1k | Zendesk |
… | … |
during past - specify the timeframe
The during past operator allows you to filter your results over a period of time when querying event tables.
The number of navigations in the past 45 minutes
appex.navigations during past 45min
| compute total_navigations = number_of_navigations.sum()
The number of navigations in the past 12 hours
appex.navigations during past 12h
| compute total_navigations = number_of_navigations.sum()
The number of navigations in the past 3 days
appex.navigations during past 3d
| compute total_navigations = number_of_navigations.sum()
from … to … - specify the timeframe
The from to operator allows you to apply custom timeframe filters when querying event tables.
When specifying a date and time the user time zone is taken whenever possible. If the request goes too far in the past the customer-defined time zone is applied but the results will always be displayed in the time zone of the user.
The number of navigations from June 1 to June 15
appex.navigations from Jun 1 to Jun 15
| compute total_navigations = number_of_navigations.sum()
The number of navigations from June 15 at 12:30 to June 15 at 16:15
appex.navigations from Jun 15, 12:30 to Jun 15, 16:15
| compute total_navigations = number_of_navigations.sum()
The number of navigations on June 15
appex.navigations on Jun 15
| compute total_navigations = number_of_navigations.sum()
on - specify the date
The on operator allows you to select a specific day when querying event tables.
When specifying a date and time the user time zone is taken whenever possible. If the request goes too far in the past the customer-defined time zone is applied but the results will always be displayed in the time zone of the user.
The number of navigations on July 15
appex.navigations on Jul 5
| compute total_navigations = number_of_navigations.sum()
Saving and sharing investigations
Investigations can be saved for future reference and shared with your colleagues.
Follow these steps to access, run and save your investigations:
Click on the investigation icon on the left to reveal the list of saved investigations.

From the list, select Investigate at the top of the list to create a new investigation.
Write your NQL queries and press Run to see the results.
Save your investigation by pressing the Save button.
Enter the name of the investigation in the pop-up and press Done.
Every time you make changes to an existing investigation press Save to update it.
You may Edit and Delete an existing investigation by pressing on the action menu. Ensure to save the investigation after you edit its name.

Click on the Share button to copy the link to the investigation, which you may share with colleagues who have access to the investigations feature. You may share your investigations at any time, without saving them first.
Applying privacy policy to investigations
There are four levels of data privacy defined in the account profile that specify access rights and are relevant to data visibility in the Investigations dashboard. These levels can be set, as shown in the illustration below.

Anonymous users, devices, destinations and web domains: The names of users, devices, destinations, and web domains are not visible to the account. Please note that destinations and web domains do not apply to NQL.
Anonymous users and devices: The names of users and devices are not visible to the account.
Anonymous users: Only the names of users are not visible to the account.
None (full access): There are no restrictions, all names are visible.
Visit the Establishing a privacy policy document for more information on various privacy options and how they are applied to Nexthink Experience.
When a certain anonymization level is applied to the user profile, it will affect the way information in the Investigations dashboard is displayed. As seen in the illustration below, the User username and User type columns of the navigations table are displayed as hidden.

The Investigations datamodel
Table | Table type | Table associations | Field | Type | Description |
---|---|---|---|---|---|
binaries | Inventory | architecture | enum | The binary architecture | |
company | string | Application company | |||
description | string | Description as it appears in the binary file | |||
name | string | Binary name | |||
size | bytes | Binary file size | |||
md5_hash | bytes | Indicates the MD5 hash of the binary | |||
sha1_hash | bytes | Indicates the SHA_1 hash of the binary | |||
sha256_hash | bytes | Indicates the SHA_256 hash of the binary | |||
application_name | string | Application name | |||
version | version | Version of the binary | |||
platform | enum | The platform (operating system family) on which the binary is running | |||
has_user_interface | bool | Application has interactive user interface | |||
devices | Inventory | sid | string | ||
name | string | ||||
platform | platform | ||||
distinguished_name | string | ||||
ad_site | string | ||||
entity | string | ||||
membership_type | enum | ||||
group_name | string | ||||
collector.uid | string | Indicates the Collector assignment license id | |||
collector.tag_id | string | Indicates the Collector installation tag | |||
collector.tag_string | string | Indicates the Collector string tag | |||
collector.version | version | Indicates the version of the Nexthink Collector installed on the device | |||
hardware.model | string | Indicates the model of the device | |||
hardware.type | enum | Indicates the device type: desktop/laptop/server/mobile | |||
hardware.manufacturer | string | Indicates the device manufacturer | |||
hardware.product_id | string | Indicates the product id of the device. Similar to model in most devices | |||
hardware.product_line | string | Device product line | |||
hardware.serial_number_bios | string | Indicates the bios serial number | |||
hardware.serial_number_machine | string | Indicates the device serial number | |||
hardware.serial_number_chassis | string | Indicates the chassis serial number | |||
hardware.installed_memory | bytes | Total amount of RAM | |||
os.architecture | enum | Architecture of device operating system (x86/x64) | |||
os.name | string | Indicates name, version and architecture (when applicable) of the operating system | |||
os.build | string | Indicates the build number of the operating system. '0.0.0.0': incompatible collector version or the data is not yet available | |||
os.wmi_status | enum | Windows WMI service status (ok, failure) | |||
os.last_update | datetime | Time of last system update | |||
os.is_activated | bool | Indicates if Windows is activated | |||
security.user_account_control_status | enum | User account control status (UAC). Possible values: ok, at risk or unknown | |||
users | Inventory | username | string | User logon name | |
type | enum | Type of user (local/domain/system/unknown) | |||
sid | string | Indicates the Windows security identifier for the user | |||
appex.navigations | Bucketized event | devices, users, binaries, application, key_page | url | string | URL navigated to |
is_soft_navigation | boolean | Indicates if the page load is a soft or a hard navigation. More information about this can be found in the “Monitoring web applications” documentation. | |||
number_of_navigations | integer | The number of navigation events (page loads) that were aggregated together. | |||
perceived_duration | seconds | The total time after which the application is usable as perceived by the user. In other words, this is the page load time. | |||
perceived_count | integer | The number of perceived durations measured | |||
unload_event_duration | seconds | The sum of all aggregated document unload event durations | |||
unload_event_count | integer | The number of aggregated unload events An unload event is thrown when the user navigates away from the page. Even a page reload will first create an unload event. If a page has already been displayed, it needs to be unloaded before navigating to the new page. | |||
redirect_duration | seconds | The sum of all aggregated HTTP redirect durations: time spent following HTTP redirects | |||
redirect_count | integer | The number of aggregated HTTP redirects | |||
domain_lookup_duration | seconds | The sum of all aggregated DNS lookup durations: time spent resolving domain names | |||
domain_lookup_count | integer | The number of aggregated DNS lookups | |||
connect_duration | seconds | The sum of all aggregated durations to establish the TCP connection: time spent establishing a socket connection from the browser to the web server | |||
connect_count | integer | The number of aggregated TCP connections established | |||
secure_connection_duration | seconds | The sum of all aggregated durations to establish the TLS connection in seconds: time spent establishing a secure socket connection from the browser to the web server | |||
secure_connection_count | integer | The number of aggregated TLS connections established | |||
request_duration | seconds | The sum of all aggregated durations between the request start and request end events: time spent waiting for the first byte of the document response | |||
request_count | integer | The number of aggregated request events | |||
response_duration | seconds | The sum of all aggregated durations between the response start and response end events: time spent downloading the document response | |||
response_count | integer | The number of aggregated response events | |||
dom_processing_duration | seconds | The sum of all aggregated durations between the DOM interactive and the DOM complete events: time taken by the browser to process and build the DOM | |||
dom_processing_count | integer | The number of aggregated DOM processing events | |||
dom_content_loaded_duration | seconds | The sum of all aggregated DOM content loaded events durations: time spent loading the DOM (included in DOM processing) | |||
dom_content_loaded_count | integer | The number of aggregated DOM content loaded events | |||
load_event_duration | seconds | The sum of all aggregated document load event durations Also referred to as an onload event. As a final step in every page load, the browser will fire an onload event which can trigger any additional functions or logic waiting for this event. | |||
load_event_count | integer | The number of aggregated document load events | |||
transfer_bytes | bytes | The sum of all aggregated HTTP response sizes | |||
transfer_count | integer | The number of aggregated HTTP responses | |||
adapter_type | enum | The type of the adapter the connection was using when the navigation was performed. | |||
vpn_status | enum | The status of the vpn when the navigation was performed. | |||
appex.errors | Bucketized event | devices, users, binaries, application, key_page | url | string | URL navigated to when the error occurred |
label | string | The error message. Examples: 404, 503, NET_ABORTED… The most common error messages are detailed, with possible root causes and fixes, in the official documentation. | |||
number_of_errors | integer | The number of aggregated errors | |||
adapter_type | enum | The type of the adapter the connection was using when the error occurred. | |||
vpn_status | enum | The status of the vpn when the error occurred. | |||
appex.transactions | Bucketized event | users, devices, binaries, application, key_page, transaction | status | transaction_status | Status of the transaction
|
duration | seconds | The sum of the duration of all aggregated transactions. For an individual transaction, it corresponds to the time elapsed between the start and the end of the transaction. | |||
number_of_transactions | integer | The number of aggregated transactions | |||
adapter_type | enum | The type of the adapter the connection was using when the transaction was performed. | |||
vpn_status | enum | The status of the vpn when the transaction was performed. | |||
appex.usages | Bucketized event | users, devices, binaries, application, key_page | duration | seconds | The sum of all aggregated usage durations. It corresponds to the time elapsed while a tab running the application was in focus. It includes the page load time. |
number_of_usage | integer | The number of all aggregated usages | |||
remote_action.executions | Punctual event | devices, remote_actions | time | datetime | Time of the execution |
request_id | string | ||||
status | enum | failed/successful | |||
trigger_method | enum | ||||
purpose | enum | ||||
inputs | string | ||||
status_details | string | ||||
outputs | string | ||||
number_of_executions | long | ||||
execution.events | Bucketized event | devices, users, binaries | start_time | datetime | Start time of the bucket |
end_time | datetime | End time of the bucket | |||
duration | double | Duration of the bucket | |||
execution_duration | double | Duration of the process | |||
cpu_time | double | Sum of the CPU time of all the underlying processes | |||
logical_processors | integer | Number of logical processors on the device | |||
memory_average | bytes | Average memory used by all processes running in parallel | |||
freezes_number | integer | Number of execution freezes | |||
focus_time | double | Amount of time any windows of an executable was in focus | |||
page_faults_number | integer | Accumulated number of page faults | |||
number_of_crashes | integer | Accumulated number of process crashes | |||
number_of_started_processes | integer | Accumulated number of processes started | |||
number_of_stopped_processes | integer | Accumulated number of stopped processes | |||
execution.starts | Punctual event | devices, users, binaries | time | datetime | Time of the execution |
binary_path | string | Normalized binary path | |||
duration | double | Total process start duration | |||
cardinality | integer | Accumulated number of processes started | |||
execution.crashes | Punctual event | devices, users, binaries | time | datetime | Time of the crash |
binary_path | string | Normalized binary path | |||
crash_on_start | bool | True if the process crashes after only a few seconds | |||
cardinality | integer | Accumulated number of processes started | |||
campaign.responses | Punctual event | users, campaigns | time | datetime | Time of the response |
request_id | string | ||||
status | enum | Delayed/Notified/Postponed/Declined/Opened/Partially/Fully | |||
answers | string | ||||
diagnostic.alerts | Punctual event | alert_config | time | datetime | Time of the alert |
uid | string | Alert event uuid | |||
context_hash | string | MD5 hash of the context json | |||
status | enum | Latest alert event status | |||
trigger_time | datetime | The time of the error of the alert | |||
recovery_time | datetime | The time of the recovery of the alert | |||
trigger_value | double | The value of the metric bypassing the threshold | |||
recovery_value | double | The value of the recovery metric | |||
context | string | Alert context in json format | |||
is_auto_recovery | bool | If the alert was automatically recovered | |||
is_grouped | bool | If the alert event is a grouping alert | |||
number_of_alerts | long | Count of alerts when data was aggregated, always 1 for 1 minute resolution | |||
device_performance.boots | Punctual event | devices | time | datetime | Time of boot |
type | enum | Type of boot | |||
duration | double | Duration of boot | |||
device_performance.crashes | Punctual event | devices | time | datetime | Time of crash |
label | string | Indicates the error label for system crashes | |||
error_code | string | Indicates the error code for system crashes | |||
device_performance.hard_resets | Punctual event | devices | time | datetime | Time of reset |
session.logins | Punctual event | devices, users | time | datetime | Time of login |
session_uid | string | Session UID | |||
time_until_desktop_visible | integer | Indicates the time between the user logging on and the desktop being shown in seconds | |||
time_until_desktop_ready | integer | Indicates the time between the user logging on and the device being ready to use, in seconds. Desktops and laptops are considered fully functional once the CPU usage drops below 15% and the disk usage drops below 80%, and servers once the CPU usage of all processes belonging to the corresponding user drops below 15%. | |||
session.logouts | Punctual event | devices, users | time | datetime | Time of logout |
session_uid | string | Session UID | |||
session.performances | Bucketized event | devices, users | start_time | datetime | Start time of the bucket |
end_time | datetime | End time of the bucket | |||
bucket_duration | long | Duration of the bucket in seconds | |||
session_uid | string | Session UID | |||
session_id | long | Session ID of the user. On macOS, it captures the pid of the session leading process | |||
protocol | enum | Indicates the protocol used to connect to the session. The possible values are: • Citrix - ICA • VMware - Blast • VMware - PCOIP • RDP • Local session • Amazon PCOIP" | |||
user_interaction | long | Duration of the user interaction in seconds | |||
connectivity.performances | Bucketized event | devices | start_time | datetime | Start time of the bucket |
end_time | datetime | End time of the bucket | |||
bucket_duration | long | Duration of the bucket in seconds | |||
wifi.ssid | string | SSID of the wifi network | |||
wifi.bssid | string | BSSID of the connected access point | |||
wifi.physical_layer_protocol | enum | 802.11 protocols used | |||
wifi.band | enum | Wifi band used | |||
wifi.channel_id | integer | Wifi channel used | |||
wifi.channel_width | integer | Frequency band width for the wifi channel being used. (bigger, better, higher theoretical transmission rate) | |||
wifi.average_signal_strength | integer | Average wifi signal strength or RSSI. Unit is in [dBm], the higher (closer to 0), the better | |||
wifi.p5_signal_strength | integer | 5th percentile of the RSSI. During a 15-minute period, the rssi was 95% of the time equal or larger than the receive value. | |||
wifi.average_transmission_rate | integer | Average transmission rate for the wifi adapter in [Mbit/sec], higher is better | |||
wifi.average_receive_rate | integer | Average receive rate for the wifi adapter in [Mbit/sec], higher is better. Not always available. | |||
primary_physical_adapter.type | enum | Type of network adapter | |||
primary_physical_adapter.local_ips | string | Local IP of the endpoint for the primary physical network adapter | |||
primary_physical_adapter.gateway_ips | string | Gateway IP of the endpoint for the primary physical network adapter | |||
primary_physical_adapter.dns_list | string | List of IP addresses of the DNS set for the VPN |