// @(#)root/monalisa:$Name:  $:$Id: TMonaLisa.cxx,v 1.2 2005/12/14 11:35:48 rdm Exp $
// Author: Andreas Peters   5/10/2005

/*************************************************************************
 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TMonaLisa                                                            //
//                                                                      //
// Class defining interface to MonaLisa Monitoring Services in ROOT.    //
// The TMonaLisa object is used to send monitoring information to a     //
// MonaLisa server using the MonaLisa ApMon package (libapmoncpp.so/UDP //
// packets). The MonaLisa ApMon library for C++ can be downloaded at    //
// http://monalisa.cacr.caltech.edu/monalisa__Download__ApMon.html,     //
// current version:                                                     //
// http://monalisa.cacr.caltech.edu/download/apmon/ApMon_c-2.0.6.tar.gz //
//                                                                      //
// The ROOT implementation is primary optimized for process/job         //
// monitoring, although all other generic MonaLisa ApMon functionality  //
// can be exploited through the ApMon class directly                    //
// (gMonaLisa->GetApMon()).                                             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TMonaLisa.h"
#include "TSystem.h"
#include "TGrid.h"
#include "Riostream.h"

TMonaLisa *gMonaLisa = 0;


ClassImp(TMonaLisa)

//______________________________________________________________________________
 TMonaLisa::TMonaLisa(const char *monid, const char *montag,
                     const char *monserver)
{
   // Creates a TMonaLisa object to send monitoring information to a
   // MonaLisa server using the MonaLisa ApMon package (libapmoncpp.so/UDP
   // packets). The MonaLisa ApMon library for C++ can be downloaded at
   // http://monalisa.cacr.caltech.edu/monalisa__Download__ApMon.html,
   // current version:
   // http://monalisa.cacr.caltech.edu/download/apmon/ApMon_cpp-2.0.6.tar.gz
   //
   // The ROOT implementation is primary optimized for process/job monitoring,
   // although all other generic MonaLisa ApMon functionality can be exploited
   // through the ApMon class directly (gMonaLisa->GetApMon()).
   //
   // Monitoring information in MonaLisa is structured in the following tree
   // structure:
   // <farmname>
   //    |
   //    ---> <nodename1>
   //              |
   //              ---> <key1> - <value1>
   //              ---> <key2> - <value2>
   //    ---> <nodename2>
   //              |
   //              ---> <key3> - <value3>
   //              ---> <key4> - <value4>
   //
   // The parameter monid is equivalent to the MonaLisa node name, for the
   // case of process monitoring it can be just an identifier to classify
   // the type of jobs e.g. "PROOF_PROCESSING".
   // If monid is not specified, TMonaLisa tries to set it in this order
   // from environement variables:
   // - PROOF_JOB_ID
   // - GRID_JOB_ID
   // - LCG_JOB_ID
   // - ALIEN_MASTERJOB_ID
   // - ALIEN_PROC_ID
   //
   // The parameter montag is equivalent to the MonaLisa farm name, for the
   // case of process monitoring it can be a process identifier e.g. a PROOF
   // session ID.
   //
   // The parameter monserver specifies the server to whom to send the
   // monitoring UDP packets. If not specified, the hostname (the port is
   // a default one) is specified in the environment variable APMON_CONFIG.
   //
   // To use TMonaLisa, libMonaLisa.so has to be loaded.
   //
   // According to the fact, that the deepness of the MonaLisa naming scheme
   // is only 3 (<farm><node><value>), a special naming scheme is used for
   // process monitoring. There is a high-level method to send progress
   // information of Tree analysis (# of events, datasize).
   // To distinguish individual nodes running the processing, part of the
   // information is kept in the <value> parameter of ML.
   // <value> is named as:
   //    <site-name>:<host-name>:<pid>:<valuetag>
   // <site-name> is taken from an environment variable in the following order:
   // - PROOF_SITE
   // - GRID_SITE
   // - ALIEN_SITE
   // - default 'none'
   // <host-name> is taken from gSystem->Hostname()
   // <pid> is the process ID of the ROOT process
   //
   // Example of use for Process Monitoring:
   //   new TMonaLisa("BATCH_ANALYSIS","AnalysisLoop-00001","lxplus050.cern.ch");
   // Once when you create an analysis task, execute
   //   gMonaLisa->SendInfoUser("myname");
   //   gMonaLisa->SendInfoDescription("My first Higgs analysis");
   //   gMonaLisa->SendInfoTime();
   //   gMonaLisa->SendInfoStatus("Submitted");
   //
   // On each node executing a subtask, you can set the status of this subtask:
   //   gMonaLisa->SendProcessingStatus("Started");
   // During the processing of your analysis you can send progress updates:
   //   gMonaLisa->SendProcessProgress(100,1000000); <= 100 events, 1MB processed
   //   ....
   //   gMonaLisa-SendProcessingStatus("Finished");
   //   delete gMonaLisa; gMonaLisa=0;
   //
   // Example of use for any Generic Monitoring information:
   //   TList *valuelist = new TList();
   //   valuelist->SetOwner(kTRUE);
   //   // append a text object
   //   TMonaLisaText *valtext = new TMonaLisaText("decaychannel","K->eeg");
   //   valuelist->Add(valtext);
   //   // append a double value
   //   TMonaLisaValue* valdouble = new TMonaLisaValue("n-gamma",5);
   //   valuelist->Add(valdouble);
   //   Bool_t success = SendParameters(valuelist);
   //   delete valuelist;

   SetName(montag);
   SetTitle(montag);

   fVerbose = kFALSE;           // no verbosity as default

   char *apmon_config[1] =
      { ((monserver == 0) ? getenv("APMON_CONFIG") : (char *) monserver) };
   if (apmon_config[0] == 0) {
      Error("TMonaLisa",
            "Disabling apmon monitoring since env variable APMON_CONFIG was not found and the monitoring server is not specified in the constructor!");
      fInitialized = kFALSE;
      return;
   }

   try {
      fApmon = new ApMon(1, apmon_config);
      fApmon->setConfRecheck(false);
      fApmon->setJobMonitoring(false);
      //((ApMon*)fApmon)->setSysMonitoring(false);
      //((ApMon*)fApmon)->setGenMonitoring(false);
   } catch (runtime_error &e) {
      Error("TMonaLisa", "Error initializing ApMon: %s", e.what());
      Error("TMonaLisa", "Disabling apmon.");
      fInitialized = kFALSE;
      return;
   }

   if (monid == 0) {
      if (getenv("PROOF_JOB_ID"))
         fJobId = getenv("PROOF_JOB_ID");
      else if (getenv("GRID_JOB_ID"))
         fJobId = getenv("GRID_JOB_ID");
      else if (getenv("LCG_JOB_ID"))
         fJobId = getenv("LCG_JOB_ID");
      else if (getenv("ALIEN_MASTERJOBID"))
         fJobId = getenv("ALIEN_MASTERJOBID");
      else if (getenv("ALIEN_PROC_ID"))
         fJobId = getenv("ALIEN_PROC_ID");
      else
         fJobId = "-no-job-id";
   } else {
      fJobId = (char *) monid;
   }

   fHostname = gSystem->HostName();
   fPid = gSystem->GetPid();

   if (fVerbose)
      Info("Initialized for ML Server <%s> - setting JobID <%s>\n",
           apmon_config[0], fJobId);

   fInitialized = kTRUE;

   gMonaLisa = this;
}

//______________________________________________________________________________
 TMonaLisa::~TMonaLisa()
{
   // Cleanup.

}

//______________________________________________________________________________
 Bool_t TMonaLisa::SendInfoStatus(const char *status)
{
   // Sends a <status> text to MonaLisa following the process scheme:
   //    <monid> --> <jobid> --> 'status' = <status>
   // Used to set a global status for a groupjob, e.g.
   // a master-job or the general status of PROOF processing.

   if (!fInitialized) {
      Error("SendInfoStatus", "Monitoring is not properly initialized!");
      return kFALSE;
   }

   Bool_t success = kFALSE;

   TList *valuelist = new TList();
   valuelist->SetOwner(kTRUE);

   // create a monitor text object
   TMonaLisaText *valtext = new TMonaLisaText("status", status);
   valuelist->Add(valtext);

   // send it to monalisa
   success = SendParameters(valuelist);

   delete valuelist;
   return success;
}

//______________________________________________________________________________
 Bool_t TMonaLisa::SendInfoUser(const char *user)
{
   // Sends the <user> text to MonaLisa following the process scheme:
   //    <monid> --> <jobid> --> 'user' = <user>

   if (!fInitialized) {
      Error("TMonaLisa",
            "Monitoring initialization has failed - you can't send to MonaLisa!");
      return kFALSE;
   }

   Bool_t success = kFALSE;

   TList *valuelist = new TList();
   valuelist->SetOwner(kTRUE);

   const char *localuser;
   if (user) {
      localuser = user;
   } else {
      if (gGrid) {
         localuser = gGrid->GetUser();
      } else {
         localuser = "unknown";
      }
   }

   // create a monitor text object
   TMonaLisaText *valtext = new TMonaLisaText("user", localuser);
   valuelist->Add(valtext);

   // send it to monalisa
   success = SendParameters(valuelist);

   delete valuelist;
   return success;
}

//______________________________________________________________________________
 Bool_t TMonaLisa::SendInfoDescription(const char *jobtag)
{
   // Sends the description <jobtag> following the processing scheme:
   //    <monid> --> <jobid> --> 'jobname' = <jobtag>

   if (!fInitialized) {
      Error("SendInfoDescription",
            "Monitoring is not properly initialized!");
      return kFALSE;
   }

   Bool_t success = kFALSE;

   TList *valuelist = new TList();
   valuelist->SetOwner(kTRUE);

   // create a monitor text object
   TMonaLisaText *valtext = new TMonaLisaText("jobname", jobtag);
   valuelist->Add(valtext);

   // send it to monalisag
   success = SendParameters(valuelist);

   delete valuelist;
   return success;
}

//______________________________________________________________________________
 Bool_t TMonaLisa::SendInfoTime()
{
   // Sends the current time to MonaLisa following the processing scheme
   //    <monid> --> <jobid> --> 'time' = >unixtimestamp<

   if (!fInitialized) {
      Error("SendInfoTime", "Monitoring is not properly initialized!");
      return kFALSE;
   }

   Bool_t success = kFALSE;

   TList *valuelist = new TList();
   valuelist->SetOwner(kTRUE);

   TString valtime = (Int_t) time(0);

   // create a monitor text object
   TMonaLisaText *valtext = new TMonaLisaText("time", valtime);
   valuelist->Add(valtext);

   // send it to monalisa
   success = SendParameters(valuelist);

   delete valuelist;
   return success;
}

//______________________________________________________________________________
 Bool_t TMonaLisa::SendProcessingStatus(const char *status)
{
   // Send the procesing status 'status' to MonaLisa following the
   // processing scheme:
   //    <monid> --> <jobid> --> '<site>:<host>:<pid>:status' = <status>
   // Used, to set the processing status of individual subtaks e.g. the
   // status of a batch (sub-)job or the status of a PROOF slave
   // participating in query <jobid>

   if (!fInitialized) {
      Error("TMonaLisa",
            "Monitoring initialization has failed - you can't send to MonaLisa!");
      return kFALSE;
   }

   Bool_t success = kFALSE;

   TString mltag;
   // set the site
   if (getenv("PROOF_SITE"))
      mltag = getenv("PROOF_SITE");
   else if (getenv("GRID_SITE"))
      mltag = getenv("GRID_SITE");
   else if (getenv("ALIEN_SITE"))
      mltag = getenv("ALIEN_SITE");
   else
      mltag = "none:";

   mltag += ":";

   // set the host + pid
   mltag += fHostname;
   mltag += ":";
   mltag += fPid;
   mltag += ":status";

   TList *valuelist = new TList();
   valuelist->SetOwner(kTRUE);

   // create a monitor text object
   TMonaLisaText *valtext = new TMonaLisaText(mltag.Data(), status);
   valuelist->Add(valtext);

   // send it to monalisa
   success = SendParameters(valuelist);

   delete valuelist;
   return success;
}

//______________________________________________________________________________
 Bool_t TMonaLisa::SendProcessingProgress(Double_t nevent, Double_t nbytes)
{
   // Send the procesing progress to MonaLisa.

   if (!fInitialized) {
      Error("SendProcessingProgress",
            "Monitoring is not properly initialized!");
      return kFALSE;
   }

   Bool_t success = kFALSE;

   TString mltag;
   // set the site
   if (getenv("PROOF_SITE"))
      mltag = getenv("PROOF_SITE");
   else if (getenv("GRID_SITE"))
      mltag = getenv("GRID_SITE");
   else if (getenv("ALIEN_SITE"))
      mltag = getenv("ALIEN_SITE");
   else
      mltag = "none:";

   mltag += ":";

   // set the host + pid
   mltag += fHostname;
   mltag += ":";
   mltag += fPid;
   mltag += ":";
   TString eventtag;
   TString bytetag;
   eventtag = mltag;
   bytetag = mltag;
   eventtag += "entries";
   bytetag += "datasize";

   TList *valuelist = new TList();
   valuelist->SetOwner(kTRUE);

   // create a monitor text object
   TMonaLisaValue *valevent = new TMonaLisaValue(eventtag.Data(), nevent);
   TMonaLisaValue *valbyte = new TMonaLisaValue(bytetag.Data(), nbytes);
   valuelist->Add(valevent);
   valuelist->Add(valbyte);

   // send it to monalisaTMonaLisaText* valtext = new TMonaLisaText
   success = SendParameters(valuelist);

   delete valuelist;
   return success;
}

//______________________________________________________________________________
 Bool_t TMonaLisa::SendParameters(TList *valuelist)
{
   // Send the parameters to MonaLisa.

   if (!fInitialized) {
      Error("SendParameters", "Monitoring is not properly initialized!");
      return kFALSE;
   }

   if (!valuelist) {
      Error("SendParameters", "No values in the value list!");
      return kFALSE;
   }

   TIter nextvalue(valuelist);

   TMonaLisaValue *objval;
   TMonaLisaText *objtext;
   TObject *monobj;

   Int_t apmon_nparams = valuelist->GetSize();
   char **apmon_params;
   Int_t *apmon_types;
   char **apmon_values;

   if (apmon_nparams) {

      apmon_params = (char **) malloc(apmon_nparams * sizeof(char *));
      apmon_values = (char **) malloc(apmon_nparams * sizeof(char *));
      apmon_types = (int *) malloc(apmon_nparams * sizeof(int));

      Int_t looper = 0;
      while ((monobj = nextvalue())) {
         if (!strcmp(monobj->ClassName(), "TMonaLisaValue")) {
            objval = (TMonaLisaValue *) monobj;

            if (fVerbose)
               Info("SendParameters", "Adding Tag %s with val %f\n",
                    objval->GetName(), objval->GetValue());

            apmon_params[looper] = (char *) objval->GetName();
            apmon_types[looper] = XDR_REAL64;
            apmon_values[looper] = (char *) (objval->GetValuePtr());
            looper++;
         }
         if (!strcmp(monobj->ClassName(), "TMonaLisaText")) {
            objtext = (TMonaLisaText *) monobj;

            if (fVerbose)
               Info("SendParameters", "Adding Tag %s with Text %s\n",
                    objtext->GetName(), objtext->GetText());

            apmon_params[looper] = (char *) objtext->GetName();
            apmon_types[looper] = XDR_STRING;
            apmon_values[looper] = (char *) (objtext->GetText());
            looper++;
         }
      }

      if (fVerbose)
         Info("SendParameters", "n: %d name: %s identifier %s ...,",
              apmon_nparams, GetName(), fJobId);

      ((ApMon *) fApmon)->sendParameters((char *) GetName(), fJobId,
                                         apmon_nparams, apmon_params,
                                         apmon_types, apmon_values);
      free(apmon_params);
      free(apmon_values);
      free(apmon_types);
   }
   return kTRUE;
}

//______________________________________________________________________________
 void TMonaLisa::SetLogLevel(const char *loglevel)
{
   // Set MonaLisa log level.

   ((ApMon *) fApmon)->setLogLevel((char *) loglevel);
}

//______________________________________________________________________________
 void TMonaLisa::Print(Option_t *) const
{
   // Print info about MonaLisa object.

   cout << "MonGroup (Farm) : " << fName << endl;
   cout << "MonTag   (Node) : " << fJobId << endl;
   cout << "HostName        : " << fHostname << endl;
   cout << "Pid             : " << fPid << endl;
   cout << "Inititialized   : " << fInitialized << endl;
   cout << "Verbose         : " << fVerbose << endl;

}


ROOT page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.