docs(troubleshooting): document the browser_info / browser_url_vars support diagnostics #9
@@ -141,3 +141,96 @@ Then recycle any existing compute sessions - hot sessions keep the old setting u
|
||||
The app version is bundled into the frontend during the release, and is visible by clicking your username in the top right.
|
||||
|
||||
You can also determine the app version (and SASjs Version, and build time) by opening browser Development Tools and running `appinfo()` in the console.
|
||||
|
||||
## Support Diagnostics
|
||||
|
||||
The frontend sends two input tables with the startup service and with the services that execute customer-provided code - the [hook scripts](macros.md) (pre/post edit and approve hooks) and the dynamic cell dropdown programs. They are available in those services as `work.browser_info` and `work.browser_url_vars`, so a support ticket can be diagnosed from the job log without asking the user follow-up questions, and a hook can adapt to its context. Other services do not receive them.
|
||||
|
||||
The services that receive the tables are: `public/startupservice`, `editors/getdata`, `editors/getdynamiccolvals`, `editors/stagedata`, `editors/loadfile`, `editors/restore` and `auditors/postdata`.
|
||||
|
||||
`editors/loadfile` is the exception in practice: the app reaches it through the adapter's file-upload call (multipart), which carries no input tables, so the service - and the post edit hook it runs - does not receive them in normal use. It is on the list for completeness, and would receive them if the service were ever invoked through the ordinary request path.
|
||||
|
||||
### browser_info
|
||||
|
||||
A single-row table with these columns:
|
||||
|
||||
| Column | Description |
|
||||
|---|---|
|
||||
| `url` | The URL of the Data Controller page itself (the iframe), not the document embedding it. When the editor is embedded in a report, the embedding URL is visible here. |
|
||||
| `referrer` | The embedding document, from `document.referrer`. For an embedded report this is the report URL, so the embedding report can be told apart from the editor URL. |
|
||||
| `timezone` | The browser's IANA timezone name, e.g. `Europe/Berlin`. |
|
||||
| `tz_offset` | The browser's UTC offset in minutes, as `Date.getTimezoneOffset()` returns it (positive west of UTC, so `Europe/Berlin` in summer is -120). |
|
||||
| `locale` | The browser locale, e.g. `en-GB`. |
|
||||
| `dc_version` | The Data Controller build, as shown by `appinfo()`. |
|
||||
| `adapter_version` | The `@sasjs/adapter` version the client was built with. |
|
||||
| `browser` | The browser family, parsed from the user agent. |
|
||||
| `browser_version` | The browser version. |
|
||||
| `platform` | The operating system, parsed from the user agent. |
|
||||
| `user_agent` | The raw `navigator.userAgent` string. |
|
||||
|
||||
### browser_url_vars
|
||||
|
||||
The page URL parameters as one row per parameter, so a SAS program can read a parameter by name rather than parse the `url` string:
|
||||
|
||||
| Column | Description |
|
||||
|---|---|
|
||||
| `name` | The URL parameter name. |
|
||||
| `value` | The URL parameter value. |
|
||||
|
||||
Parameters from both the search string and the hash query string (Angular routes carry them after the `#`) are included; on a name collision the search string value wins. The table is sent only when the page URL has at least one parameter.
|
||||
|
||||
The values in both tables are supplied by the client, so treat them as diagnostics hints rather than a security boundary.
|
||||
|
||||
To see the tables, run any of the services above with debug on. The debug value depends on the path: `&_debug=131` on the Compute API and SAS 9, or `&_debug=128` on the Viya web (JES) path with `runAsTask` enabled - which is what the frontend sends there, so turning debug on in the app is enough. Either value makes the session initialisation write the tables to the job log:
|
||||
|
||||
```
|
||||
NOTE: MPEINIT: work.browser_url_vars:
|
||||
name=embed value=va
|
||||
NOTE: MPEINIT: work.browser_info:
|
||||
url=... referrer=... timezone=Europe/Berlin tz_offset=-120 locale=en-GB
|
||||
dc_version=7.15.0 adapter_version=4.19.0 browser=Chrome browser_version=120.0
|
||||
platform=Linux user_agent=...
|
||||
```
|
||||
|
||||
A service called directly (for instance from a URL, or by a script), or by an older frontend, has no `work.browser_info` - the log then records that fact instead.
|
||||
|
||||
### Reading the tables from a hook
|
||||
|
||||
A [hook script](macros.md) is `%include`d into the running service, so it shares the service's WORK library and can read the tables directly. Take an embedded editor opened at:
|
||||
|
||||
```
|
||||
https://datacontroller.io/#/editor/SASHELP.CLASS?labels=true&embed=va
|
||||
```
|
||||
|
||||
`browser_url_vars` then holds a row per parameter - `labels=true` and `embed=va` - so a hook can pick up either by name:
|
||||
|
||||
```sas
|
||||
%let labels=N;
|
||||
%let embed=N;
|
||||
|
||||
%if %sysfunc(exist(work.browser_url_vars)) %then %do;
|
||||
proc sql noprint;
|
||||
select value into :labels
|
||||
from work.browser_url_vars
|
||||
where name = 'labels';
|
||||
select value into :embed
|
||||
from work.browser_url_vars
|
||||
where name = 'embed';
|
||||
quit;
|
||||
%end;
|
||||
```
|
||||
|
||||
To branch on what the client reports:
|
||||
|
||||
```sas
|
||||
%if %sysfunc(exist(work.browser_info)) %then %do;
|
||||
data _null_;
|
||||
set work.browser_info;
|
||||
call symputx('dc_timezone', timezone);
|
||||
call symputx('dc_locale', locale);
|
||||
run;
|
||||
%end;
|
||||
```
|
||||
|
||||
!!! warning
|
||||
Guard with `%sysfunc(exist())` before reading. A service called directly, or by a frontend older than this feature, has no `work.browser_info` at all, so an unguarded `set` or `select` fails the job.
|
||||
Reference in New Issue
Block a user