Written by

Senior Cloud Architect at InterSystems
Question Eduard Lebedyuk · Mar 11, 2016

Determine currently used service

I want to determine what service (eg. %Service_Console) is used for current process.

I can probably use some workarounds, i.e.

  • Is %request object present
  • Does $Device  contain |TRM|
  • etc

But is there any centralised way to get current service?

Comments

Timothy Leavitt · Mar 11, 2016

One solution would be to look at the audit database. It's not pretty, but there might not be any other way.

ClassMethod GetLoginService() As %String
{
    New $Namespace
    Zn "%SYS"
    
    Set tService = ""
    
    // Ensure that login events are being audited.
    Set tLoginEvent = ##class(Security.Events).Get("%System","%Login","Login",.tProps)
    If '$Get(tProps("Enabled")) {
        // Querying the audit DB probably won't do any good.
        Quit tService
    }
    
    // Warning: on systems with a lot of activity, this query might take a long time.
    // It might be worth filtering by recent UTCTimeStamp, assuming processes won't be that long-running.
    Set tRes = ##class(%SQL.Statement).%ExecDirect(,
        "select top 1 EventData from %SYS.Audit "_
        "where EventSource = '%System' and EventType = '%Login' and Event = 'Login' and PID = ? "_
        "order by UTCTimeStamp DESC, SystemID DESC, AuditIndex DESC",$Job)
    
    Set tHasResult = tRes.%Next()
    If (tHasResult) {
        Set tData = tRes.%Get("EventData")
        //NOTE: This makes assumptions about the format of EventData.
        //Particularly, that it looks something like:
        /*
        Service name:       %Service_Bindings
        Login roles:        %All
        $I:                 |TCP|1972|15396
        $P:                 |TCP|1972|15396
        */
        //
        Set tFirstLine = $Piece(tData,$c(13,10))
        
        //Presumably "Service name:" might be localized, but %Service_<something> would not be.
        Set:tFirstLine["%Service" tService = "%Service"_$Piece(tFirstLine,"%Service",2)
    }
    Quit tService
}

 

Note: if your application is using Caché security correctly, you'd probably need to define a privileged routine application to allow access to Security.Events and the audit database.

0
Eduard Lebedyuk  Mar 14, 2016 to Alexander Koblov

Hi.

I want to create LOGIN^%ZSTART routine that works only for terminal connections. Here's the code.

0
Eduard Lebedyuk  Mar 14, 2016 to Alexander Koblov

And you need to do this why? I mean what is the end goal?

To show user some menu when they open Terminal?

Yes.

You can specify "Startup Tag^Routine" for this purpose:

Awesome. Didn't knew that it aplied only to terminal devices.

0
Luca Ravazzolo · Mar 17, 2016

The subject made me smile :) "service"
 

Shouldn't we wrap the above method and expose these services via a RESTful "service" API and even encapsulate the inside system Caché ObjectScript API we have with such "service"?

So the above would look something like:

GET /server/system/v1/services

and then of course you'd have all the other methods implemented...

0