This application is not supported by InterSystems Corporation. Please be notified that you use it at your own responsibility.

What's new in this version

Introduce API /restapi to accept log file lines via POST and /restapi/transfer/tr to obtain display friendly file transfer timestamps for table on CSP


This was started from template of a Multi-model REST API application built with ObjectScript in InterSystems IRIS. iris-sftp-logs API accepts log file lines at this URL: POST localhost:52773/restapi/{log file line}

You need to replace localhost with the ip address if iris-sftp-logs runs on a remote server. Change the port number if you use a different port.

Within sftplog.csp (via User.Helper classmethod TransferTableData) I utilize REST call (GET) to /restapi/transfer/tr/{TransferID} to obtain display friendly time stamps for output in Transfer table.

Set pIris = 0
Set pType = "GET"
Set pUrl = "/restapi/transfer/tr/"_tResult.ID
Set tSC = ..CallRESTapi(pIris,pUrl,.pResponseData,pType)


Make sure you have git and Docker desktop installed.

Installation with ZPM

zpm:USER>install iris-sftp-logs

Installation for development

Clone/git pull the repo into any local directory like it is shown below:

$ git clone

Open the terminal in this directory:

$ cd iris-sftp-logs


$ docker-compose up -d --build

Deploy SFTP server

If you want to deploy an SFTP server in a container, follow these steps:

$ git clone
$ cd sftp-server
$ docker-compose up -d --build

How iris-sftp-logs uses IRIS multi-model data platform

I defined classes for Container, Session, and Transfer objects with mapping to globals. Class User.SFTPLog populates data into User.Container, User.Session, and User.Transfer classes. It can be invoked from terminal or sftplog.csp (see below).

key-value globals

When I encounter a new ContainerID in log file, I store the timestamp when it was first encountered in LogContainer classmethod:

ClassMethod LogContainer(
	pContainerID As %String = "",
	pTimestamp As %String = "") As %Status
	Set tSC = $$$OK
	If (pContainerID = "") Quit tSC
	If $Data(^Container(pContainerID)) Quit tSC
	Set ^Container(pContainerID) = pTimestamp
	Quit tSC

LogSessionOpen classmethod sets data into Session global:

Set ^Session(pContainerID,pTimestamp,tUserIP,tUsername) = pLogText

The Transfer global gets seeded in LogTransferOpen classmethod:

Set d = "^"
Set ^Transfer(pSessionID,pTimestamp) = tFilename_d_tFlags_d_tMode

Setting data value directly into global bypasses data validation such as MAXLEN defined in class definition.


When I update a Transfer with Bytes Read, Bytes Written, and Close Timestamp in LogTransferClose classmethod, I instantiate an object and use %Save method which performs validation:

Set objTransfer = ##class(Transfer).%OpenId(pTransferID,,.tSC)
If $$$ISERR(tSC) {
	Do ..DebugStatus(tSC)
	Quit tSC
Set objTransfer.BytesRead = tBytesRead
Set objTransfer.BytesWritten = tBytesWritten
Set objTransfer.CloseTimestamp = pTimestamp
Set tSC = objTransfer.%Save()


I created OutputTableData classmethod for Session class which gets called from sftplog.csp to display a table with Session data.

ClassMethod OutputTableData(
	pWhere As %String = "",
	pMaxRows = -1) As %Status
	Set tSC = $$$OK
	Set tQuery = "SELECT * FROM SQLUser.Session"
	Set tStatement = ##class(%SQL.Statement).%New()
	Set tSC = tStatement.%Prepare(.tQuery)  // Create a cached query
	If $$$ISERR(tSC) { Quit tSC }
	#dim tResult As %SQL.StatementResult
	Set tResult = tStatement.%Execute()
	IF (tResult.%SQLCODE=0) { /*WRITE !,"Created a query",!*/ }
	ELSEIF (tResult.%SQLCODE=-361) { /*WRITE !,"Query exists: ",tResult.%Message*/ }
	ELSE { /*WRITE !,"CREATE QUERY error: ",tResult.%SQLCODE," ",tResult.%Message*/ QUIT tSC}
 	While tResult.%Next() {
		Write !,"<tr><td>",tResult.ContainerID,"</td>"
		Write !,"<td>",tResult.OpenTimestamp,"</td>"
		Write !,"<td>",tResult.UserIP,"</td>"
		Write !,"<td>",tResult.Username,"</td></tr>"
	Quit tSC

iris-sftp-logs includes a csp page to manage your sftp log files. You can access it at http://localhost:52773/sftplog/sftplog.csp. You need to replace localhost with the ip address if iris-sftp-logs runs on a remote server. Change the port number if you use a different port. Screenshot

The repository includes a sample sftp log file. You can import it into IRIS database. Enter the directory (/irisrun/repo/) and filename (sftp.log), check the Import checkbox, and click Submit. Screenshot

You will see contents of the log file displayed on the bottom of the screen. Screenshot

Once you have imported some sftp logs, you can choose a Session to focus on. Please click the Choose Session radio button and click Submit button. Screenshot

The log file raw contents get replaced by two tables. The first table shows Session data and the second table shows Transfer data. Screenshot

If you click on a row in the Session table, the page displays Session and Transfer data for the selected Session only.

If you want to choose a different Session, please click the Choose Session radio button and click Submit button again.

IPM installation
zpm "install iris-sftp-logs"
5 (1)
ObjectScript quality test
Updated on 22 September 2023
ObjectScript quality report
Developer Environment
Works with
InterSystems IRIS
Last updated