Author Topic: With SparxKeyStoreService missing a way to see/read number of users  (Read 938 times)

steen.jensen@sll.se

  • EA Novice
  • *
  • Posts: 5
  • Karma: +0/-0
    • View Profile
The management interface of SparxKeyStoreServices just show what user have a key at that moment.
We have 15 Floating keys, but I have no way to check how many users was using Sparx last week, or what was the peek usage last week or month, so I can order more keys in advance, to be litle proaktiv :)

Boron

  • EA User
  • **
  • Posts: 70
  • Karma: +5/-0
    • View Profile
Re: With SparxKeyStoreService missing a way to see/read number of users
« Reply #1 on: December 06, 2016, 02:06:29 am »
I wrote a parser for the logfiles of the keystore service myself.
It uses the Qt library.
The output is a *.csv file that can then be used in Excel for any imaginable evaluation.

Unfortunately we cannot attach files to forum posts.
It is just one *.cpp file. I would have shared with you :(.

RudiCz

  • EA Novice
  • *
  • Posts: 11
  • Karma: +1/-0
    • View Profile
Re: With SparxKeyStoreService missing a way to see/read number of users
« Reply #2 on: December 06, 2016, 07:11:11 pm »
In our environment exists a File keystoreService.config (in C:\Program Files (x86)\Sparx Systems\Keystore\Service). With LOG_LEVEL=INFO EA creates a File with all CheckIns, CheckOuts and available keys

Graham_Moir

  • EA User
  • **
  • Posts: 677
  • Karma: +4/-6
    • View Profile
Re: With SparxKeyStoreService missing a way to see/read number of users
« Reply #3 on: January 10, 2017, 08:44:07 pm »
I wrote a parser for the logfiles of the keystore service myself.
It uses the Qt library.
The output is a *.csv file that can then be used in Excel for any imaginable evaluation.

Unfortunately we cannot attach files to forum posts.
It is just one *.cpp file. I would have shared with you :(.

Could you put this on the community site?    http://community.sparxsystems.com/

Boron

  • EA User
  • **
  • Posts: 70
  • Karma: +5/-0
    • View Profile
Re: With SparxKeyStoreService missing a way to see/read number of users
« Reply #4 on: January 10, 2017, 10:21:14 pm »
Another site to register :(.
Just had the idea to put the source code directly in a post.
No complaints about the code :). It works for me.
Code: [Select]
#include <QDir>
#include <QFile>
#include <QTimer>
#include <QStringList>
#include <QCoreApplication>
#include <QTextStream>

static bool checkIfValidArguments(QStringList arguments);
static void printSyntax(const QStringList arguments);
static void parseLogFile();
static void printErrorMessage(QString message);

static QFile logFile;
static QFile reportFile;
static QTextStream qout(stdout);

int main( int argc, char** argv)
{
   int returnValue = EXIT_SUCCESS;

   QCoreApplication app(argc, argv); //renamed the a to app
   QStringList arguments = app.arguments();

   if( checkIfValidArguments(arguments))
   {
      parseLogFile();
   }
   else
   {
      // wrong usage of command line arguments     
      printSyntax(arguments);
      returnValue = EXIT_FAILURE;
   }

   QTimer::singleShot(0, &app, SLOT(quit())); //stop after 0 seconds
   app.exec();

   return returnValue; //and we run the application
}

/******************************************************************************/
static bool checkIfValidArguments(QStringList arguments)
{
   bool returnValue = true;

   int whereLogFileArgument;
   int whereLogFileName;

   int whereReportFileArgument;
   int whereReportFileName;

   if(arguments.size() < 5)
   {
      // too less arguments
      printErrorMessage( "Too few arguments given." );
      returnValue = false;
   }
   else
   {
      /*******************************/
      // Check for log file
      whereLogFileArgument = arguments.indexOf("-l");
      if(whereLogFileArgument > 0)
      {
         whereLogFileName = whereLogFileArgument + 1;   // expect log file name right behind "-l" argument
         if(  QFile::exists(arguments.at(whereLogFileName)) // if argument is an existing file
           && !QDir().cd(arguments.at(whereLogFileName)))   // and if argument is not a directory
         {
            logFile.setFileName( arguments.at(whereLogFileName) );
         }
         else
         {
            // LogFileName is not valid (file cannot be found)
            printErrorMessage( QString("Given logFile cannot be found: ").append(arguments.at(whereLogFileName)) );
            returnValue = false;
         }
      }
      else
      {
         // no "-l" argument found
         printErrorMessage( "No -l argument given" );
         returnValue = false;
      }

      /*******************************/
      // Check for report file
      whereReportFileArgument = arguments.indexOf("-r");
      if(whereReportFileArgument > 0)
      {
         whereReportFileName = whereReportFileArgument + 1;   // expect report file name right behind "-r" argument
         reportFile.setFileName( arguments.at(whereReportFileName) );
      }
      else
      {
         // no "-r" argument found
         printErrorMessage( "No -r argument given" );
         returnValue = false;
      }

   }

   return returnValue;
}

/******************************************************************************/
static void printSyntax(const QStringList arguments)
{
   qout << "Usage: " << arguments.at(0) << " -l <logFile> -r <reportFile>" << endl;
   qout << "   logFile     Path to the logfile created by the Sparx KeystoreService" << endl;
   qout << "   reportFile  Path to the report file" << endl;
   qout << "               The report file is written in csv format (*.csv extension is encouraged)" << endl;
   qout << "               If the given file name already exists the file will be overwritten" << endl;
   qout << "Example: " << arguments.at(0) << " -l C:\\Sparx\\ssksLog-1.log -r C:\\LicenseReport.csv" << endl;
}

/******************************************************************************/
static void printErrorMessage(QString message)
{
   qout << "Error: " << message << endl;
}

/******************************************************************************/
static void parseLogFile()
{
   QStringList splittedLine;
   QTextStream* inStream;
   QTextStream* outStream;
   bool errorOccured = false;

   /***********/
   // Open log file
   FILE* inFile;
   QString copyFileName("CopyOf_");
   logFile.copy(copyFileName.append(QFileInfo(logFile.fileName()).fileName()));
   QFile copyFile(copyFileName);
   if( fopen_s(&inFile, copyFile.fileName().toLatin1(), "r") == 0 )
   {
      inStream = new QTextStream(inFile, QIODevice::ReadOnly);
      inStream->setAutoDetectUnicode(true);
   }
   else
   {
      errorOccured = true;
      printErrorMessage( "Log file could not be opened." );
   }

   /***********/
   // Open report file
   FILE* outFile;
   if( fopen_s(&outFile, reportFile.fileName().toLatin1(), "w") == 0 )
   {
      outStream = new QTextStream(outFile, QIODevice::ReadWrite);
   }
   else
   {
      errorOccured = true;
      printErrorMessage( "Report file could not be written." );
   }

   /***********/
   if( !errorOccured )
   {
      QString line;
  *outStream << "Date ; Time ; Edition; Available ; Expired ; Checked Out ; Checkouts ; Reasserts ; Failues ;" << endl;
      do
      {
         if( line.contains("[REPORT]: [AUDIT]"))
         {
            line.remove("[REPORT]: [AUDIT]");
            line = line.simplified();
//            qout << line << endl;
            splittedLine = line.split("|");

            QString dateTime = splittedLine[0];
            splittedLine.removeAt(0);
            QStringList dateTimeList = dateTime.split(" ");

QString edition;
for (int i = 2; i < dateTimeList.size(); i++)
{
edition.append(dateTimeList[i]);
edition.append(" ");
}

// Edition
splittedLine.prepend(edition);
// Time
            splittedLine.prepend(dateTimeList.at(1));
// Date
            splittedLine.prepend(dateTimeList.at(0));
            //for( int i=0; i<splittedLine.size(); i++ )
            //{
            //   splittedLine[i] = splittedLine[i].simplified();
            //}

            // Date
            *outStream << splittedLine[0] << ";";
            // Time
            *outStream << splittedLine[1].remove(splittedLine[1].lastIndexOf(":"), 3) << ";";
// Edition
*outStream << splittedLine[2] << ";";
// Available
*outStream << splittedLine[3].remove("Available:") << ";";
// Expired
            *outStream << splittedLine[4].remove("Expired:") << ";";
            // Checked-out
            *outStream << splittedLine[5].remove("Checked Out:") << ";";
            // Checkouts
            *outStream << splittedLine[6].remove("Checkouts:") << ";";
            // Reasserts
            *outStream << splittedLine[7].remove("Reasserts:") << ";";
            // Failures
            *outStream << splittedLine[8].remove("Failures:") << ";";

            *outStream << endl;
         }
         line = inStream->readLine();
      } while (!line.isNull());
   }

   // delete temporary file
   fclose(inFile);
   fclose(outFile);
   copyFile.remove();

   delete inStream;
   delete outStream;
}