<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://community.appian.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Determining User Last Login Date</title><link>https://community.appian.com/discussions/f/administration/23829/determining-user-last-login-date</link><description>Hi, 
 I am managing an Appian app across multiple environments and need to monitor licensing usage. I need to be able to identify users who have not logged in the past 90 days and need to do this analysis by user group. However, I cannot find any &amp;#39;Last</description><dc:language>en-US</dc:language><generator>Telligent Community 12</generator><item><title>RE: Determining User Last Login Date</title><link>https://community.appian.com/thread/153306?ContentTypeID=1</link><pubDate>Thu, 29 Jan 2026 12:17:54 GMT</pubDate><guid isPermaLink="false">d3a83456-d57b-489c-a84c-4e8267bb592a:54fe5e68-7324-480f-8004-070f358da4e2</guid><dc:creator>germand519</dc:creator><description>&lt;p&gt;You have to retrive data from the 3 nodes and&amp;nbsp;union them later&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;/* Logs nodo 1 */
  local!filesToRetrieveNode1: a!forEach(
    items: local!datesToRetrieve,
    expression: concat(
      &amp;quot;app-jboss-1/login-audit.csv.&amp;quot;,
      fv!item
    )
  ),
  local!validFilesToRetrieveNode1: a!forEach(
    items: local!filesToRetrieveNode1,
    expression: if(
      todate(
        index(
          getloginfo(logPath: fv!item),
          &amp;quot;lastModified&amp;quot;,
          {}
        )
      ) &amp;gt; date(2000, 1, 1),
      fv!item,
      {}
    )
  ),
  /* Logs Nodo 2*/
  local!filesToRetrieveNode2: a!forEach(
    items: local!datesToRetrieve,
    expression: concat(
      &amp;quot;app-jboss-2/login-audit.csv.&amp;quot;,
      fv!item
    )
  ),
  local!validFilesToRetrieveNode2: a!forEach(
    items: local!filesToRetrieveNode2,
    expression: if(
      todate(
        index(
          getloginfo(logPath: fv!item),
          &amp;quot;lastModified&amp;quot;,
          {}
        )
      ) &amp;gt; date(2000, 1, 1),
      fv!item,
      {}
    )
  ),
  /* Logs Nodo 3*/
  local!filesToRetrieveNode3: a!forEach(
    items: local!datesToRetrieve,
    expression: concat(
      &amp;quot;app-jboss-3/login-audit.csv.&amp;quot;,
      fv!item
    )
  ),
  local!validFilesToRetrieveNode3: a!forEach(
    items: local!filesToRetrieveNode3,
    expression: if(
      todate(
        index(
          getloginfo(logPath: fv!item),
          &amp;quot;lastModified&amp;quot;,
          {}
        )
      ) &amp;gt; date(2000, 1, 1),
      fv!item,
      {}
    )
  ),
  local!validFilesToRetrieveAllNodes: union(
    &amp;quot;app-jboss-1/login-audit.csv.&amp;quot;,
    local!validFilesToRetrieveNode1,
    &amp;quot;app-jboss-2/login-audit.csv.&amp;quot;,
    local!validFilesToRetrieveNode2,
    &amp;quot;app-jboss-3/login-audit.csv.&amp;quot;,
    local!validFilesToRetrieveNode3
  ),&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Determining User Last Login Date</title><link>https://community.appian.com/thread/149722?ContentTypeID=1</link><pubDate>Tue, 08 Jul 2025 19:50:30 GMT</pubDate><guid isPermaLink="false">d3a83456-d57b-489c-a84c-4e8267bb592a:49c53167-242d-4e36-b646-81ecc137c064</guid><dc:creator>michaelnyefda</dc:creator><description>&lt;p&gt;&amp;nbsp;&lt;a href="/members/mariuscristianl0001"&gt;marius-cristian001&lt;/a&gt;&amp;nbsp;I figured out the problem. This code block above does not properly cast dates so when it interprets June 30th, it views it as the 6th day of the 30th month, which leads to a casting error and causes the day to be dropped as shown in your screenshot&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;You no longer have this issue if you update it to:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;a!localVariables(&lt;br /&gt; local!loginAuditDaysToRetrieve: 40,&lt;br /&gt; local!numberOfDaysToRetrieve: 1 + enumerate(local!loginAuditDaysToRetrieve),&lt;br /&gt; local!datesToRetrieve: a!forEach(&lt;br /&gt; items: local!numberOfDaysToRetrieve,&lt;br /&gt; expression: text(&lt;br /&gt; todate(local(now())) - fv!index,&lt;br /&gt; &amp;quot;yyyy-mm-dd&amp;quot;&lt;br /&gt; )&lt;br /&gt; ),&lt;br /&gt; local!filesToRetrieve: a!forEach(&lt;br /&gt; items: local!datesToRetrieve,&lt;br /&gt; expression: concat(&lt;br /&gt; &amp;quot;login-audit.csv.&amp;quot;,&lt;br /&gt; fv!item&lt;br /&gt; )&lt;br /&gt; ),&lt;br /&gt; local!validFilesToRetrieve: a!forEach(&lt;br /&gt; items: local!filesToRetrieve,&lt;br /&gt; expression: if(&lt;br /&gt; todate(&lt;br /&gt; index(&lt;br /&gt; getloginfo(&lt;br /&gt; logPath: fv!item&lt;br /&gt; ),&lt;br /&gt; &amp;quot;lastModified&amp;quot;,&lt;br /&gt; {}&lt;br /&gt; )&lt;br /&gt; ) &amp;gt; date(2000,1,1),&lt;br /&gt; fv!item,&lt;br /&gt; {}&lt;br /&gt; )&lt;br /&gt; ),&lt;br /&gt; local!loginAuditAsText: reject(&lt;br /&gt; fn!isnull,&lt;br /&gt; a!flatten(&lt;br /&gt; a!forEach(&lt;br /&gt; items: local!validFilesToRetrieve,&lt;br /&gt; expression: a!localVariables(&lt;br /&gt; local!loginAuditFromCsv: readcsvlog(&lt;br /&gt; csvPath: fv!item&lt;br /&gt; ),&lt;br /&gt; local!headers: index(&lt;br /&gt; local!loginAuditFromCsv,&lt;br /&gt; &amp;quot;headers&amp;quot;,&lt;br /&gt; {}&lt;br /&gt; ),&lt;br /&gt; local!rows: index(&lt;br /&gt; local!loginAuditFromCsv,&lt;br /&gt; &amp;quot;rows&amp;quot;,&lt;br /&gt; {}&lt;br /&gt; ),&lt;br /&gt; {&lt;br /&gt; joinarray(local!headers,&amp;quot;,&amp;quot;),&lt;br /&gt; local!rows&lt;br /&gt; }&lt;br /&gt; )&lt;br /&gt; )&lt;br /&gt; )&lt;br /&gt; ),&lt;br /&gt; local!loginAudit: a!forEach(&lt;br /&gt; items: local!loginAuditAsText,&lt;br /&gt; expression: a!localVariables(&lt;br /&gt; local!loginAuditArray: split(fv!item, &amp;quot;,&amp;quot;),&lt;br /&gt; local!rawLoggedIn: index(&lt;br /&gt; local!loginAuditArray,&lt;br /&gt; 1,&lt;br /&gt; {}&lt;br /&gt; ),&lt;br /&gt; local!rawLoggedInSplit: split(&lt;br /&gt; local!rawLoggedIn,&lt;br /&gt; &amp;quot; &amp;quot;&lt;br /&gt; ),&lt;br /&gt; local!rawLoggedInDate: index(&lt;br /&gt; local!rawLoggedInSplit,&lt;br /&gt; 1,&lt;br /&gt; {}&lt;br /&gt; ),&lt;br /&gt; local!convertedLoggedInDate: &lt;br /&gt; joinarray(&lt;br /&gt; reverse(&lt;br /&gt; split(&lt;br /&gt; local!rawLoggedInDate,&lt;br /&gt; &amp;quot;-&amp;quot;&lt;br /&gt; )&lt;br /&gt; ),&lt;br /&gt; &amp;quot;/&amp;quot;&lt;br /&gt; ),&lt;br /&gt; local!rawLoggedInTime: split(&lt;br /&gt; index(&lt;br /&gt; local!rawLoggedInSplit,&lt;br /&gt; 2,&lt;br /&gt; {}&lt;br /&gt; ),&lt;br /&gt; &amp;quot;:&amp;quot;&lt;br /&gt; ),&lt;br /&gt; local!convertedLoggedInTime: time(&lt;br /&gt; index(&lt;br /&gt; local!rawLoggedInTime,&lt;br /&gt; 1,&lt;br /&gt; {}&lt;br /&gt; ),&lt;br /&gt; index(&lt;br /&gt; local!rawLoggedInTime,&lt;br /&gt; 2,&lt;br /&gt; {}&lt;br /&gt; ),&lt;br /&gt; index(&lt;br /&gt; local!rawLoggedInTime,&lt;br /&gt; 3,&lt;br /&gt; {}&lt;br /&gt; )&lt;br /&gt; ),&lt;br /&gt; local!finalLoggedIn: rule!APPN_reverseMonthAndDayOfDate(local!convertedLoggedInDate) + local!convertedLoggedInTime,&lt;br /&gt; {&lt;br /&gt; username: index(&lt;br /&gt; local!loginAuditArray,&lt;br /&gt; 2,&lt;br /&gt; {}&lt;br /&gt; ),&lt;br /&gt; loggedIn: local!finalLoggedIn,&lt;br /&gt; loggedInDate: local!convertedLoggedInDate,&lt;br /&gt; loggedInTime: local!convertedLoggedInTime,&lt;br /&gt; outcome: index(&lt;br /&gt; local!loginAuditArray,&lt;br /&gt; 3,&lt;br /&gt; {}&lt;br /&gt; )&lt;br /&gt; }&lt;br /&gt; )&lt;br /&gt; ),&lt;br /&gt; reject(&lt;br /&gt; fn!isnull,&lt;br /&gt; union(&lt;br /&gt; local!loginAudit,&lt;br /&gt; local!loginAudit&lt;br /&gt; )&lt;br /&gt; )&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;where&amp;nbsp;APPN_reverseMonthAndDayOfDate has the expression:&lt;/p&gt;
&lt;p&gt;joinarray(&lt;br /&gt; index(&lt;br /&gt; split(&lt;br /&gt; ri!date,&lt;br /&gt; &amp;quot;/&amp;quot;&lt;br /&gt; ), &lt;br /&gt; {2,1,3},&lt;br /&gt; {}&lt;br /&gt; ),&lt;br /&gt; &amp;quot;/&amp;quot;&lt;br /&gt;)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Determining User Last Login Date</title><link>https://community.appian.com/thread/149589?ContentTypeID=1</link><pubDate>Thu, 03 Jul 2025 19:32:53 GMT</pubDate><guid isPermaLink="false">d3a83456-d57b-489c-a84c-4e8267bb592a:b38e2242-9b1f-4956-8a46-4d77cf95bd51</guid><dc:creator>sridhart4969</dc:creator><description>&lt;p&gt;On Prod we have 3 servers.&lt;br /&gt;&lt;br /&gt;suite/shared-logs/app-jboss-1/&lt;br /&gt;suite/shared-logs/app-jboss-2/&lt;br /&gt;suite/shared-logs/app-jboss-3/&lt;br /&gt;&lt;br /&gt;How to pass csvPath to above server paths.&lt;br /&gt;&lt;br /&gt;readcsvlog function says&amp;nbsp;&lt;strong class="StrongText---richtext_strong"&gt;csvPath&lt;/strong&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;Text&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Path to the csv log file (relative to the /logs directory)&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Determining User Last Login Date</title><link>https://community.appian.com/thread/92357?ContentTypeID=1</link><pubDate>Thu, 17 Mar 2022 09:26:04 GMT</pubDate><guid isPermaLink="false">d3a83456-d57b-489c-a84c-4e8267bb592a:83624672-a4f3-49d6-8109-e3ed86d8be46</guid><dc:creator>ajhick</dc:creator><description>&lt;p&gt;I&amp;#39;m not having this issue. If you&amp;#39;re using the same local variable names as me can you check your raw output from one of the valid files to retrieve? See the below code and look in the &amp;quot;rows&amp;quot; index at the left hand side (before the first comma) to check the format of the dates that are in your login audit files.&lt;/p&gt;
&lt;p&gt;Preferably make it so you can look at one of the entries where it&amp;#39;s only giving the time!&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;a!localVariables(
  local!numberOfDaysToRetrieve: 1 + enumerate(90),
  local!datesToRetrieve: a!forEach(
    items: local!numberOfDaysToRetrieve,
    expression: text(
      todate(local(now())) - fv!index,
      &amp;quot;yyyy-mm-dd&amp;quot;
    )
  ),
  local!filesToRetrieve: a!forEach(
    items: local!datesToRetrieve,
    expression: concat(
      &amp;quot;login-audit.csv.&amp;quot;,
      fv!item
    )
  ),
  local!validFilesToRetrieve: a!forEach(
    items: local!filesToRetrieve,
    expression: if(
      todate(
        index(
          getloginfo(
            logPath: fv!item
          ),
          &amp;quot;lastModified&amp;quot;,
          {}
        )
      ) &amp;gt; date(2000,1,1),
      fv!item,
      {}
    )
  )[1], /*Manipulate this index to try and get an instance where only a time is showing*/
  local!loginAuditAsText: reject(
    fn!isnull,
    a!flatten(
      a!forEach(
        items: local!validFilesToRetrieve,
        expression: a!localVariables(
          local!loginAuditFromCsv: readcsvlog(
            csvPath: fv!item
          ),
          local!loginAuditFromCsv
        )
      )
    )
  ),
  local!loginAuditAsText
)&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Determining User Last Login Date</title><link>https://community.appian.com/thread/92334?ContentTypeID=1</link><pubDate>Wed, 16 Mar 2022 15:51:48 GMT</pubDate><guid isPermaLink="false">d3a83456-d57b-489c-a84c-4e8267bb592a:9dc6f745-e28b-4d7d-a85f-8b75aa764e68</guid><dc:creator>Stewart Burchell</dc:creator><description>&lt;p&gt;Have you looked at the raw output in the Expression Rule designer? Just wondering if Appian is rendering the time when the date happens to be today...if the raw data is the same then it must be the Log Reader doing the same...in which case you can infer that the date is today if you only have the time&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Determining User Last Login Date</title><link>https://community.appian.com/thread/92332?ContentTypeID=1</link><pubDate>Wed, 16 Mar 2022 15:41:23 GMT</pubDate><guid isPermaLink="false">d3a83456-d57b-489c-a84c-4e8267bb592a:facce31d-1a7b-4f97-bbfc-527fcbd32e73</guid><dc:creator>marius-cristian001</dc:creator><description>&lt;p&gt;Hi,&lt;br /&gt;&lt;br /&gt;We have installed the Log Reader Plugin and used your code.&lt;br /&gt;In some cases some lines are returned without the entire log date.&lt;/p&gt;
&lt;p&gt;I already checked the entire code but i couldn&amp;#39;t find the root cause for the issue.&lt;/p&gt;
&lt;p&gt;Do you have any suggestion on how to fix this?&lt;br /&gt;&lt;br /&gt;Thank you!&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " src="/resized-image/__size/320x240/__key/communityserver-discussions-components-files/12/logreader-test.JPG" /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Determining User Last Login Date</title><link>https://community.appian.com/thread/91715?ContentTypeID=1</link><pubDate>Tue, 01 Mar 2022 14:39:04 GMT</pubDate><guid isPermaLink="false">d3a83456-d57b-489c-a84c-4e8267bb592a:1e67b4e6-56ae-4462-a77a-69fb44ba3d11</guid><dc:creator>Barthe</dc:creator><description>&lt;p&gt;Thank you ajhick, I will take a look at your code. Thanks for sharing!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Determining User Last Login Date</title><link>https://community.appian.com/thread/91607?ContentTypeID=1</link><pubDate>Fri, 25 Feb 2022 22:21:15 GMT</pubDate><guid isPermaLink="false">d3a83456-d57b-489c-a84c-4e8267bb592a:b509badc-d39f-4767-b48d-2b5f99f93ad1</guid><dc:creator>ajhick</dc:creator><description>&lt;p&gt;Hi Barthe,&lt;/p&gt;
&lt;p&gt;The below code does required the Log Reader plugin but it produces a list of logins for the login files. I don&amp;#39;t know if this is the best way but this is what I&amp;#39;ve been using. I do a fair amount of transformation on this data but this is the core.&lt;/p&gt;
&lt;p&gt;&lt;a href="/b/appmarket/posts/log-reader"&gt;https://community.appian.com/b/appmarket/posts/log-reader&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;a!localVariables(
  local!loginAuditDaysToRetrieve: 90,
  local!numberOfDaysToRetrieve: 1 + enumerate(local!loginAuditDaysToRetrieve),
  local!datesToRetrieve: a!forEach(
    items: local!numberOfDaysToRetrieve,
    expression: text(
      todate(local(now())) - fv!index,
      &amp;quot;yyyy-mm-dd&amp;quot;
    )
  ),
  local!filesToRetrieve: a!forEach(
    items: local!datesToRetrieve,
    expression: concat(
      &amp;quot;login-audit.csv.&amp;quot;,
      fv!item
    )
  ),
  local!validFilesToRetrieve: a!forEach(
    items: local!filesToRetrieve,
    expression: if(
      todate(
        index(
          getloginfo(
            logPath: fv!item
          ),
          &amp;quot;lastModified&amp;quot;,
          {}
        )
      ) &amp;gt; date(2000,1,1),
      fv!item,
      {}
    )
  ),
  local!loginAuditAsText: reject(
    fn!isnull,
    a!flatten(
      a!forEach(
        items: local!validFilesToRetrieve,
        expression: a!localVariables(
          local!loginAuditFromCsv: readcsvlog(
            csvPath: fv!item
          ),
          local!headers: index(
            local!loginAuditFromCsv,
            &amp;quot;headers&amp;quot;,
            {}
          ),
          local!rows: index(
            local!loginAuditFromCsv,
            &amp;quot;rows&amp;quot;,
            {}
          ),
          {
            joinarray(local!headers,&amp;quot;,&amp;quot;),
            local!rows
          }
        )
      )
    )
  ),
  local!loginAudit: a!forEach(
    items: local!loginAuditAsText,
    expression: a!localVariables(
      local!loginAuditArray: split(fv!item, &amp;quot;,&amp;quot;),
      local!rawLoggedIn: index(
        local!loginAuditArray,
        1,
        {}
      ),
      local!rawLoggedInSplit: split(
        local!rawLoggedIn,
        &amp;quot; &amp;quot;
      ),
      local!rawLoggedInDate: index(
        local!rawLoggedInSplit,
        1,
        {}
      ),
      local!convertedLoggedInDate: joinarray(
        reverse(
          split(
            local!rawLoggedInDate,
            &amp;quot;-&amp;quot;
          )
        ),
        &amp;quot;/&amp;quot;
      ),
      local!rawLoggedInTime: split(
        index(
          local!rawLoggedInSplit,
          2,
          {}
        ),
        &amp;quot;:&amp;quot;
      ),
      local!convertedLoggedInTime: time(
        index(
          local!rawLoggedInTime,
          1,
          {}
        ),
        index(
          local!rawLoggedInTime,
          2,
          {}
        ),
        index(
          local!rawLoggedInTime,
          3,
          {}
        )
      ),
      local!finalLoggedIn: local!convertedLoggedInDate + local!convertedLoggedInTime,
      {
        username: index(
          local!loginAuditArray,
          2,
          {}
        ),
        loggedIn: local!finalLoggedIn,
        outcome: index(
          local!loginAuditArray,
          3,
          {}
        )
      }
    )
  ),
  reject(
    fn!isnull,
    union(
      local!loginAudit,
      local!loginAudit
    )
  )
)&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>