Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
094e715f5d |
No files matched your search
@@ -48,7 +48,7 @@ There is no copy to keep in sync, no hook to write and nothing to maintain. That
|
|||||||
### Things worth knowing
|
### Things worth knowing
|
||||||
|
|
||||||
- Where the librefs are defined depends on your platform. On Viya, in the compute context's `autoexec.sas` (or `[DC Drive Path]/services/settings.sas`); on SAS 9, as metadata libraries or in the Data Controller Settings stored process; on SASjs Server, in `services/public/settings.sas`. The one requirement is that each library has a unique libref.
|
- Where the librefs are defined depends on your platform. On Viya, in the compute context's `autoexec.sas` (or `[DC Drive Path]/services/settings.sas`); on SAS 9, as metadata libraries or in the Data Controller Settings stored process; on SASjs Server, in `services/public/settings.sas`. The one requirement is that each library has a unique libref.
|
||||||
- `mp_lockanytable` keys on `libref.dataset`, so the two menus do not serialise against each other. That has consequences beyond a collision - see *The concurrency caveat* below.
|
- `mp_lockanytable` keys on `libref.dataset`, so the two menus do not serialise against each other. That has consequences beyond a collision - see [the concurrency caveat](#the-concurrency-caveat) below.
|
||||||
- The audit trail and approval queue record which libref a change came through, so `ORDERS_EU.ORDERS` and `ORDERS_US.ORDERS` stay distinguishable in history. For most people that is a feature - you can see which report a change originated from.
|
- The audit trail and approval queue record which libref a change came through, so `ORDERS_EU.ORDERS` and `ORDERS_US.ORDERS` stay distinguishable in history. For most people that is a feature - you can see which report a change originated from.
|
||||||
|
|
||||||
### The concurrency caveat
|
### The concurrency caveat
|
||||||
|
|||||||
@@ -1,158 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Support Diagnostics: browser_info and browser_url_vars'
|
|
||||||
description: Data Controller sends two input tables with the startup service and with every service that runs customer code - the browser context and the page URL parameters. A support ticket can be answered from the job log, and a hook can read them.
|
|
||||||
date: '2026-09-27 09:00:00'
|
|
||||||
author: 'Data Controller'
|
|
||||||
authorLink: https://www.linkedin.com/showcase/data-controller-for-sas
|
|
||||||
tags:
|
|
||||||
- Announcements
|
|
||||||
previewImg: './support-diagnostics.jpeg'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Support Diagnostics: browser_info and browser_url_vars
|
|
||||||
|
|
||||||
A support ticket usually starts with a round of questions. Which browser? Which timezone? Which build? What was in the URL? Data Controller now answers them itself. The frontend sends two input tables - `browser_info` and `browser_url_vars` - with the startup service and with every service that runs customer-provided code, so the context of a session is in the job log before anyone asks for it, and a hook script can read it.
|
|
||||||
|
|
||||||
This ships with the next Data Controller release.
|
|
||||||
|
|
||||||
## The two tables
|
|
||||||
|
|
||||||
Both are ordinary input tables on the request: the adapter turns each array in the payload into a table in the service's WORK library, so they arrive as `work.browser_info` and `work.browser_url_vars`.
|
|
||||||
|
|
||||||
### browser_info
|
|
||||||
|
|
||||||
A single row, describing the client that made the request:
|
|
||||||
|
|
||||||
| Column | What it holds |
|
|
||||||
|---|---|
|
|
||||||
| `url` | The URL of the Data Controller page itself (the iframe), not the document embedding it - so an embedded editor is distinguishable from a standalone one. |
|
|
||||||
| `referrer` | The embedding document, from `document.referrer`. For an embedded report this is the report URL. |
|
|
||||||
| `timezone` | The browser's IANA timezone, 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 `appinfo()` reports it. |
|
|
||||||
| `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. |
|
|
||||||
| `user_agent` | The raw `navigator.userAgent` string. |
|
|
||||||
|
|
||||||
### browser_url_vars
|
|
||||||
|
|
||||||
One row per URL parameter:
|
|
||||||
|
|
||||||
| Column | What it holds |
|
|
||||||
|---|---|
|
|
||||||
| `name` | The parameter name. |
|
|
||||||
| `value` | The parameter value. |
|
|
||||||
|
|
||||||
Parameters are read from both the search string and the hash query string, because Angular routes carry them after the `#`. Where the same name appears in both, the search string wins. The table is sent only when the page URL has at least one parameter.
|
|
||||||
|
|
||||||
## Which services receive them
|
|
||||||
|
|
||||||
| Service | When |
|
|
||||||
|---|---|
|
|
||||||
| `public/startupservice` | Once per session, so every job log carries the session context |
|
|
||||||
| `editors/getdata` | The PRE_EDIT_HOOK |
|
|
||||||
| `editors/stagedata` | The POST_EDIT_HOOK, through the loader |
|
|
||||||
| `editors/restore` | The POST_EDIT_HOOK, through the loader |
|
|
||||||
| `editors/getdynamiccolvals` | The dynamic cell dropdown programs |
|
|
||||||
| `auditors/postdata` | The PRE_APPROVE_HOOK and POST_APPROVE_HOOK |
|
|
||||||
| `editors/loadfile` | The POST_EDIT_HOOK - see the caveat below |
|
|
||||||
|
|
||||||
Those are the services that run customer code. The viewer's `viewlibs`, `viewtables` and `viewdata`, the metadata services and `usernav` receive neither table, so the high-frequency calls stay lean.
|
|
||||||
|
|
||||||
## Reading them in a hook
|
|
||||||
|
|
||||||
A hook script 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` - and a hook can read 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;
|
|
||||||
```
|
|
||||||
|
|
||||||
Or branch on what the user's browser reports:
|
|
||||||
|
|
||||||
```sas
|
|
||||||
data _null_;
|
|
||||||
set work.browser_info;
|
|
||||||
call symputx('dc_timezone', timezone);
|
|
||||||
call symputx('dc_locale', locale);
|
|
||||||
run;
|
|
||||||
```
|
|
||||||
|
|
||||||
Note the `exist()` guard. 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` would fail the job. Guard first, then read.
|
|
||||||
|
|
||||||
## In the job log
|
|
||||||
|
|
||||||
Turn debug on and the session initialisation writes both tables to the log, so a ticket can be diagnosed without a second round of questions:
|
|
||||||
|
|
||||||
```
|
|
||||||
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=... adapter_version=... browser=Chrome browser_version=...
|
|
||||||
platform=Linux user_agent=...
|
|
||||||
```
|
|
||||||
|
|
||||||
The debug value depends on the path - `&_debug=131` on the Compute API and SAS 9, `&_debug=128` on the Viya web (JES) path with `runAsTask` enabled, which is what the frontend sends there. Either way, switching debug on in the app is enough.
|
|
||||||
|
|
||||||
## Worth knowing
|
|
||||||
|
|
||||||
- The values are supplied by the client. Treat them as diagnostics hints, never as a security boundary.
|
|
||||||
- `editors/loadfile` is reached through the adapter's multipart file upload, which carries no input tables, so in normal use that service - and the hook it runs - does not receive them. It is on the list for completeness.
|
|
||||||
- Nothing else pays for the tables: they travel only with the services above.
|
|
||||||
|
|
||||||
Full detail, including the column definitions and the log output, is in the [troubleshooting documentation](https://docs.datacontroller.io/dci-troubleshooting/).
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Source LinkedIn post:
|
|
||||||
|
|
||||||
A support ticket starts with questions. Which browser? Which timezone? Which build? What was in the URL?
|
|
||||||
|
|
||||||
Data Controller now answers them itself.
|
|
||||||
|
|
||||||
Two tables travel with the startup service, and with every service that runs your own code:
|
|
||||||
|
|
||||||
→ browser_info - one row: browser and version, platform, timezone and UTC offset, locale, the DC and adapter builds, the page URL and the referrer
|
|
||||||
|
|
||||||
→ browser_url_vars - one row per URL parameter, name and value, read straight into a macro variable
|
|
||||||
|
|
||||||
Both land in the job log when debug is on, so a ticket can be diagnosed from the log instead of a round trip. Both are readable from a hook script - %include shares the service's WORK library, so a hook can branch on the user's timezone, or pick up a parameter from the URL.
|
|
||||||
|
|
||||||
They are client supplied values: diagnostics hints, not a security boundary. Guard with %sysfunc(exist()) - a service called directly, or an older frontend, sends nothing.
|
|
||||||
|
|
||||||
✅ Full detail in the Data Controller documentation - link in the comments.
|
|
||||||
|
|
||||||
#sas #sasviya #datagovernance #datacapture #sasjs
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- Image prompt:
|
|
||||||
Generate a 16:9 landscape illustration for a B2B data-governance blog cover, 1200x627.
|
|
||||||
|
|
||||||
Style: flat vector illustration, dark slate background (#314351) with a faint evenly spaced dot grid, brand green accent (#90c445), lighter slate panels (#2e4252), soft diffused shadows, subtle depth.
|
|
||||||
|
|
||||||
Scene: two rounded panels side by side, each with a header bar in brand green and four rows of rounded cells. The left panel carries short uniform value blocks (the browser context); the right panel carries name-and-value pairs, drawn as a narrow block beside a wider one (the URL parameters), with a single row in the left panel highlighted in green. Between and below the panels a thin vertical connector line runs down to a wide, flat log strip of alternating short green rules on a lighter slate panel, suggesting the tables being written to a job log.
|
|
||||||
|
|
||||||
Minimal text, no letters, no numbers, no logos, no watermark. Keep the subject inside the central square so a 1:1 crop is safe; the outer left and right thirds may be croppable background only.
|
|
||||||
|
|
||||||
Output: save as ./support-diagnostics.jpeg at 1200x627 (matching the other feed covers, and doubling as the LinkedIn share card). Do not also embed the image in the markdown body.
|
|
||||||
-->
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 53 KiB |
@@ -1,74 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Data Controller for SAS® - Who Is It For?'
|
|
||||||
description: Five roles, five questions - what Data Controller for SAS® answers for administrators, auditors, managers, data owners and purchasers.
|
|
||||||
date: '2026-09-26 09:00:00'
|
|
||||||
author: 'Data Controller'
|
|
||||||
authorLink: https://www.linkedin.com/showcase/data-controller-for-sas
|
|
||||||
tags:
|
|
||||||
- Announcements
|
|
||||||
previewImg: './who-is-data-controller-for.jpeg'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Data Controller for SAS® - Who Is It For?
|
|
||||||
|
|
||||||
Data Controller for SAS® gives business users a safe way to add, modify and delete data in SAS tables and databases, without handing them write access to production. That one capability answers a different question for each role that touches the data - so here is the short version, role by role.
|
|
||||||
|
|
||||||
## Data Administrators
|
|
||||||
|
|
||||||
Would you grant self-serve data updates in SAS if there was no risk to the data model? That is the trade Data Controller offers. End users never get direct write access to the target tables - every change is staged, validated at the point of entry, and applied by the service itself. Data Controller changes data, not structure, so your data model stays as it is.
|
|
||||||
|
|
||||||
## Data Auditors
|
|
||||||
|
|
||||||
Do you need to know who made a particular data change, what that change was, when it was made, and who signed it off? Every submission carries a full audit trail, and any associated Excel file is retained alongside it, so the source of a change can be reviewed long after it was loaded.
|
|
||||||
|
|
||||||
## Data Managers
|
|
||||||
|
|
||||||
Do you want to load, modify or delete production data without writing repetitive code, saving sensitive data to shared filesystems, building and deploying jobs, or crafting long-winded change requests? Adding a new editable table is configuration rather than development - the grid is generated from the target table's metadata, and the load type (composite or retained keys, SCD2, bitemporal) is picked from a list.
|
|
||||||
|
|
||||||
## Data Owners
|
|
||||||
|
|
||||||
Do you like to review data changes before they are applied? Approvers see the diff - new, changed and deleted rows - and nothing lands until it is signed off. Email alerts can tell you when data is changed or about to change, and a completed load can trigger a SAS job downstream. If the wrong change gets approved anyway, the table can be rolled back to a previous state - and the rollback is itself a new, reviewable change, so the audit trail keeps both the mistake and the correction.
|
|
||||||
|
|
||||||
## Purchasers
|
|
||||||
|
|
||||||
How about a business friendly, no lock-in software licence? The price list is public, every package includes unlimited users, and a perpetual licence is available. The Community package is free, so evaluating Data Controller costs nothing but the installation.
|
|
||||||
|
|
||||||
## What it is, in one line
|
|
||||||
|
|
||||||
Data Controller for SAS® is a robust solution for secure data uploads into any SAS-connected database, with full audit trail and approval mechanism. Configuration is quick, installation is easy, and everything runs on your own SAS platform with no external calls.
|
|
||||||
|
|
||||||
Multiple load types are supported (composite and retained keys, SCD2, bitemporal, format catalogs), data can be validated at the point of entry, and Excel end-user computing files can be dragged straight into SAS. Data Rollback, Data Catalog and Data Viewer come as standard.
|
|
||||||
|
|
||||||
Data Control.
|
|
||||||
|
|
||||||
Want to see it working on your own data? [Book a Discovery Call](/contact).
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Source LinkedIn post:
|
|
||||||
|
|
||||||
Data Administrators → would you grant self-serve data updates in SAS, if there was no risk to the data model?
|
|
||||||
|
|
||||||
Data Auditors → do you require oversight of who made a particular data change, what that change was, when it was made, and who signed it off? And to review the original excel, if used as a source?
|
|
||||||
|
|
||||||
Data Managers → do you prefer to load / modify / delete production data WITHOUT writing repetitive code, saving sensitive data to shared filesystems, building & deploying jobs, or crafting long-winded change requests?
|
|
||||||
|
|
||||||
Data Owners → do you like to review data changes before they are applied? How about receiving email alerts or the ability to set up job triggers after tables are updated?
|
|
||||||
|
|
||||||
Purchasers → how about a business friendly, no lock-in software licence?
|
|
||||||
|
|
||||||
Data Controller for SAS® is a robust solution for secure data uploads into any SAS-connected database, with full audit trail and approval mechanism.
|
|
||||||
|
|
||||||
Installation is easy and configuration is quick ⚡ Multiple load types supported (composite / retained keys, SCD2, Bitemporal, Format catalogs). Perform data validation at point of entry. Drag & drop Excel EUCs straight into SAS.
|
|
||||||
|
|
||||||
Data Rollback, Data Catalog, Data Viewer.
|
|
||||||
|
|
||||||
Data Control. ✅
|
|
||||||
|
|
||||||
#sas #sasviya #sasusers #datagovernance
|
|
||||||
|
|
||||||
https://lnkd.in/dunqWhnt
|
|
||||||
|
|
||||||
Image prompt:
|
|
||||||
|
|
||||||
Flat vector illustration, dark slate blue background (#314351), wide 1.91:1 banner (1200 x 627). Five simplified human figures stand in a shallow arc across the centre, each rendered in flat corporate style with minimal facial detail: an administrator beside a padlock, an auditor with a magnifying glass over a document, a manager holding a spreadsheet with an upward arrow, a data owner holding an approval tick, and a purchaser holding a price tag. Behind them, a translucent dashboard panel shows a data grid with one row highlighted as a pending change, and a small diff of new, changed and deleted rows. Thin connecting lines link each figure to the panel, suggesting that every role sees the same controlled workflow. Bright green accent (#90c445) used sparingly on the approval tick, the highlighted row and the connecting lines. Subtle depth with soft shadows, crisp edges. No text, no words, no letters, no logos, no watermarks. Keep the figures and the panel inside the central square so the image is safe to crop to 1:1 - the outer left and right thirds are background only.
|
|
||||||
-->
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 138 KiB |
Reference in new issue
Block a user