Open Exchange App SystemPerformance Utility (pka pButtons) API (and REST API) [and sample UI]

Primary tabs

While reviewing our documentation for our ^pButtons (in IRIS renamed as ^SystemPerformance) performance monitoring utility, a customer told me: "I understand all of this, but I wish it could be simpler… easier to define profiles, manage them etc.".

After this session I thought it would be a nice exercise to try and provide some easier human interface for this.

The first step in this was to wrap a class-based API to the existing pButtons routine.

I was also able to add some more "features" like showing what profiles are currently running, their time remaining to run, previously running processes and more.

The next step was to add on top of this API, a REST API class.

With this artifact (a pButtons REST API) in hand, one can go ahead and build a modern UI on top of that.

For example -

So I'm sharing with you here a few steps of the way:

Two classes which are the "Basic" API –

As well as the REST API (including some Unit Test classes to test these).

A Swagger JSON for the REST API. To build this I used what was then (back in 2017) a not yet released capability in InterSystems IRIS for REST management. Building on top of the basic Swagger JSON provided by the InterSystems IRIS I added further information.

As well as a simple angular UI (based on this http://websystique.com/angularjs/angularjs-crud-application-using-ngresource/)

A few important notes:

  • Most of the "Basic" API methods use documented and supported entry points to the pButtons/SystemPerformance routine. But some methods access the internal structures managed by the pButtons utility. These are NOT documented or supported and these methods could stop working upon upgrade without notice.
  • This code by any means is not intended as a "best-practice" example for building a REST-based Angular app with InterSystems IRIS. The UI part was just given as an example/"teaser" and a sample starting point [It's not complete for example - the "General section" (e.g. a place-holder for Log folder location management) was not implemented; and the Refresh of the contents doesn't work fully across the board and some other "known issues..."]
  • The initial code for this was written quite some time ago - so:
    • (a) I came back to this now to make sure it runs with IRIS (and had to make some naming changes).
    • (b) The REST API did not use the spec-first approach - I did initially play with the (back then) IRIS-beta's support for generating a Swagger, and now used that to make this into a spec-first approach.
    • (c) This might not use the latest features available today.
    • (d) I added now also support for this running within a Docker container (with the relevant Dockerfile etc.).
    • (e) I also added support for this being installed as a ZPM package.

 

 

 

Replies

Hi Tani!

I'm having the error when open the UI.

Also, it's not clear where I can find the Open API spec endpoint or UI.

Thanks for trying Evgeny,

Regarding the error page you are getting in the UI I believe it's pointing you to the Application Error Log in the System Mgmt. Portal (right? the screenshot above is cut...), so try and look there and let me know what you find.

One place to verify things are generally setup ok for the web side, is to see the Web Application was created and defined correctly (including authentication, pointing to the correct physical folder, etc.).

Let me know what you find.

Regarding the Swagger/Open API spec - you find it in any of these -

1. A json file under the /swagger folder (as mentioned towards the end of the Readme). I used this for easier editing of the spec within VSCode with the relevant plugin.

2. The .spec class /src/zpButtons/REST/spec.cls

3. Using our built-in API Mgmt. REST API, in this case the URL would be, for example:

http://localhost:52773/api/mgmnt/v2/%25SYS/zpButtons.API.REST

With either of these you can take the JSON and view it via the Swagger Editor - https://editor.swagger.io/

Let me know if this is what you meant.

Hi Tani!

About swagger-spec.

According to the Open-API standard your API should expose /_spec end-point, where it exports JSON in Open API format.

I tried to refer to /pbuttons/_spec - and got 404.

To make this happen you need to introduce a GET endpoint /_spec and a method that implements it. Here is an example of the endpoint and the method which could be almost the same for any REST API.

Thanks for this tip Evgeny.

Indeed this /_spec convention pointing to the Swagger spec does seem convenient, I wasn't aware this was part of the Open API Specification (in fact I didn't find this mentioned in the Spec...).

I actually saw the method you mentioned when I was looking at the rest template provided as part of the previous contest, and thought of using it, but eventually since I used the spec-first approach, and this method you mentioned is currently (at least as-is) implemented assuming you use a code-first approach, I opted not to, and to have the same functionality (a REST API end-point providing the Swagger spec) via our already built-in API Mgmt. REST API (which I mentioned above).

I could of course consider adding something similar in the future.

Hi Tani!

In fact /_spec endpoint is not a part of Open API specification. I was wrong.

But this approach to tell where is the Open API specification could be found is quite popular, so InterSystems spec-first /api/mgmnt/ service generates such an endpoint.

That's why we did this for the REST-API template too.

Thanks Evgeny, understood.

So you're saying: "InterSystems spec-first /api/mgmnt/ service generates such an endpoint." - that means that if I used the spec-first approach (which I did, I used ^%REST) I should have this /_spec endpoint? Because that didn't seem to happen...

Regarding the application error.

I installed the package via ZPM:

% docker run --name my-iris -d --publish 9091:51773 --publish 9092:52773 intersystemsdc/irishealth-community:2020.2.0.196.0-zpm

% docker exec -it my-iris iris session IRIS

Node: 18aa9f2b084c, Instance: IRIS

USER>zpm

zpm: USER>docker exec -it my-iris iris session IRIS

zpm: USER>install sys-perf-restapi                 

[sys-perf-restapi] Reload START

[sys-perf-restapi] Reload SUCCESS

[sys-perf-restapi] Module object refreshed.

[sys-perf-restapi] Validate START

[sys-perf-restapi] Validate SUCCESS

[sys-perf-restapi] Compile START

[sys-perf-restapi] Compile SUCCESS

[sys-perf-restapi] Activate START

[sys-perf-restapi] Configure START

[sys-perf-restapi] Configure SUCCESS

[sys-perf-restapi] Activate SUCCESS

zpm: USER>

Then opened http://localhost:9092/pbuttonsUI/index.csp
and got this error.

The application error log is empty:

Thanks Evegny.

Well no error info is a little hard to work with...

But (un)fortunately I was able to reproduce this (though earlier on in the process I tested with the test ZPM registry and it seemed to work fine...).

In any case I see (as I mentioned in my previous reply, it was worth looking there) that the UI Web Application was defined with an unauthenticated authentication method, only.

Even though the Module.xml file (link from previous version) defines it with Authentication...

Indeed when I look at the -verbose output of the ZPM install I see different behavior in each of the two CSP Apps being installed.

Even though both define this -

PasswordAuthEnabled="1"
UnauthenticatedEnabled="0"

For the REST app I see this:

Creating Web Application /pbuttons
    AutheEnabled: 32
    AuthenticationMethods:

Which is correct.

But for the 2nd app I see this:

Creating Web Application /pButtonsUI
    AuthenticationMethods:

Note no "AutheEnabled: 32" which it should have.

I edited some of the code within the ZPM class (%ZPM.PackageManager.Developer.Processor.CSPApplication) and saw that indeed the related properties (PasswordAuthEnabled & UnauthenticatedEnabled) where empty...

Playing around and comparing with some other module.xml's I found that perhaps the order of the values make a difference, so I changed:

<CSPApplication
  Url="/pButtonsUI"
  Path="/src/pButtonsAppCSP"
  Directory="{$cspdir}/pButtonsUI"
  PasswordAuthEnabled="1"
  UnauthenticatedEnabled="0"
  ServeFiles="1"
  Recurse="1"
  CookiePath="/pButtonsUI"
/>

to be:

<CSPApplication
  Url="/pButtonsUI"
  ServeFiles="1"
  Recurse="1"
  CookiePath="/pButtonsUI"
  UseCookies="2"
  PasswordAuthEnabled="1"
  UnauthenticatedEnabled="0"
  Path="/src/pButtonsAppCSP"
  Directory="{$cspdir}/pButtonsUI"
/>

And now when I run the zpm install I see thsi:

Creating Web Application /pButtonsUI
    AutheEnabled: 32
    AuthenticationMethods:

As expected.

So I pushed this update to github and hopefully this should work for you now.

In any case -

(a) I would recommend investigating why this was behavior - is this by design that the order of these attributes matter - if not - we should fix it,  and if yes - we should document it.

(b) and regarding documentation - I would recommend to document the actual attributes of this CSPApplication tag. In the current documentation there is a simple reference to the %Installer tags, but in reality though they are similar they are still different in some cases... so we should either indeed adhere to those, or document the ones that Module.xml actually uses.

For example, for relevance to the current discussion - the CSPApplication tag in our docs (referred to by the ZPM Module.xml docs) has an AuthenticationMethods attribute while the Module.xml has a combination of others instead.

Another example - Module.xml has a Path attribute and %Installer does not.

Let me know if this now works, and what you think about what I observed.

Hi Netanel,

I can't reproduce this problem, but I'll look into it in more detail - it's very strange that the order of the attributes matters.

It's possible to use AuthenticationMethods attribute instead of PasswordAuthEnabled="1" UnauthenticatedEnabled="0" - I've added it into module.xml documentation 

Hi Tani!

I fixed the issue with deploy path - see the PR. Could you please republish the module on OEX?

It turned out we don't need "/" after {cspdir}. Will update the templates, thank you!

So, it works for me! 

But, another "issue" I'm facing here that I need to submit "login/pass" two times. One for CSP app, another for REST app called from CSP. Is it a 'groupid' case, or common cookie folder?

Hi Tani!

Though /_spec endpoint can provide more info, indeed we can use the embedded /api/mgmnt/ entry, which is avaialble for your REST API on:

"http://localhost:9092/api/mgmnt/v1/USER/spec/pbuttons" , if you install it in NAMESPACE USER, and run docker with:

docker run --name my-iris -d --publish 9091:51773 --publish 9092:52773 intersystemsdc/irishealth-community:2020.2.0.196.0-zpm

To visualise the API I installed the module "swagger-ui":

USER>zpm

zpm: USER>install swagger-ui

[swagger-ui] Reload START

[swagger-ui] Reload SUCCESS

[swagger-ui] Module object refreshed.

[swagger-ui] Validate START

[swagger-ui] Validate SUCCESS

[swagger-ui] Compile START

[swagger-ui] Compile SUCCESS

[swagger-ui] Activate START

[swagger-ui] Configure START

[swagger-ui] Configure SUCCESS

[swagger-ui] Activate SUCCESS

and got the nice interface to the API on: 

http://localhost:9092/swagger-ui/index.html

All set )