diff --git a/Control/SGMon/SGAudSvc/CMakeLists.txt b/Control/SGMon/SGAudSvc/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..05221c1806f2124a68d158aa6870629ec4a3e325
--- /dev/null
+++ b/Control/SGMon/SGAudSvc/CMakeLists.txt
@@ -0,0 +1,29 @@
+################################################################################
+# Package: SGAudSvc
+################################################################################
+
+# Declare the package name:
+atlas_subdir( SGAudSvc )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Control/AthenaBaseComps
+                          Control/AthenaKernel
+                          Control/SGMon/SGAudCore
+                          GaudiKernel
+                          PRIVATE
+                          Control/StoreGate )
+
+# Component(s) in the package:
+atlas_add_component( SGAudSvc
+                     src/*.cxx
+                     src/components/*.cxx
+                     LINK_LIBRARIES AthenaBaseComps AthenaKernel SGAudCore GaudiKernel StoreGateLib SGtests )
+
+# Install files from the package:
+atlas_install_headers( SGAudSvc )
+atlas_install_scripts( share/SGout2dot.py )
+
+# Aliases:
+atlas_add_alias( SGout2dot "SGout2dot.py" )
+
diff --git a/Control/SGMon/SGAudSvc/SGAudSvc/SGAudSvc.h b/Control/SGMon/SGAudSvc/SGAudSvc/SGAudSvc.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ca8008517eab0736498eb63125ac0eee9c473fa
--- /dev/null
+++ b/Control/SGMon/SGAudSvc/SGAudSvc/SGAudSvc.h
@@ -0,0 +1,164 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// SGAudSvc.h 
+// Header file for class SGAudSvc
+// Author: Ilija Vukotic <ivukotic@cern.ch>
+/////////////////////////////////////////////////////////////////// 
+#ifndef SGMONITORING_SGAUDSVC_H 
+#define SGMONITORING_SGAUDSVC_H 
+
+// STL includes
+#include <string>
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <fstream>
+
+// HepMC / CLHEP includes
+
+// FrameWork includes
+#include "AthenaBaseComps/AthService.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "GaudiKernel/IIncidentListener.h"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/Algorithm.h"
+#include "AthenaKernel/IClassIDSvc.h"
+
+#include "SGAudCore/ISGAudSvc.h"
+
+// Forward declaration
+class ISvcLocator;
+template <class TYPE> class SvcFactory;
+class IChronoStatSvc;
+class IAlgContextSvc;
+class AlgContextSvc;
+
+class SGAudSvc : virtual public ISGAudSvc,
+		 virtual public IIncidentListener,
+		 public AthService
+{ 
+
+protected:
+    
+  friend class SvcFactory<SGAudSvc>;
+
+
+public: 
+
+  /// Constructor with parameters: 
+  SGAudSvc( const std::string& name, ISvcLocator* pSvcLocator );
+
+  /// Destructor: 
+  virtual ~SGAudSvc(); 
+
+  /// Gaudi Service Implementation
+  //@{
+  StatusCode initialize();
+  StatusCode finalize();
+  virtual StatusCode queryInterface( const InterfaceID& riid, void** ppvInterface );
+  //@}
+
+  static const InterfaceID& interfaceID();
+  
+
+/** incident service handle for EndEvent. Calls monitor. There should be more elegant way to get number of events passed.
+*/
+  void handle( const Incident& incident );
+
+  // do the auditing, called from DataStore.cxx 
+  virtual void SGAudit(const std::string& key, const CLID& id, 
+		       const int& fnc, const int& store_id);
+
+  
+/** 
+* @brief Gets name of curently running algorithm from AlgContextSvc.
+*/
+  bool SGGetCurrentAlg();
+/** 
+* @brief For implementing custom increased granularity auditing of for instance tools.
+*/
+  void setFakeCurrentAlg(const std::string&);
+/** 
+* @brief For implementing custom increased granularity auditing of for instance tools.
+*/
+  void clearFakeCurrentAlg();
+ 
+  private: 
+
+  /// Default constructor: 
+  SGAudSvc();
+
+  void SGAudRETRIEVE(std::string SGobject);
+  void SGAudRECORD(std::string SGobject);
+
+  void getNobj(std::string name);
+  void addRead();
+  void addWrite();
+
+  /// just counts events. called at EndEvent incident
+  void monitor();
+
+  void writeJSON();
+
+  /////////////////////////////////////////////////////////////////// 
+  // Private data: 
+  /////////////////////////////////////////////////////////////////// 
+ private: 
+
+  /// MsgStream for talking with the outside world
+  MsgStream m_msg;
+
+  /// Pointer to the @c AlgContextScv
+  IAlgContextSvc *p_algCtxSvc;
+  IClassIDSvc* m_pCID;
+  
+  /// Name of the output file 
+  std::string m_outFileName, m_allFileName, m_sumFileName;  
+
+  /// Whether to ignore fake current algs
+  bool m_ignoreFakeAlgs;
+
+  /// Whether to use CLID or Data Obj Name in JSON output file
+  bool m_useCLID;
+
+  /// Vector of accessed SG objects names
+  std::vector<std::string> m_vObj;
+  /// Vector of names of algorithms accessing SG
+  std::vector<std::string> m_vAlg;
+  /// map counting Reads of each object by each algorithm.
+  std::map<int,int> m_timesRead;
+  /// map counting Writes of each object by each algorithm.
+  std::map<int,int> m_timesWritten;
+  std::string m_currAlg;
+  std::string m_currObj;
+  std::string m_fakeCurrAlg;
+  int m_nCurrAlg;
+  int m_nCurrObj;
+  int m_nEvents;
+  int m_startEvent;
+
+  // map<"alg_name", set<"cid/key"> >
+  typedef std::map<std::string, std::set<std::string> > DataMap;
+  DataMap m_read;
+  DataMap m_write;
+
+  std::ofstream m_ofa, m_ofs;
+  bool m_inExec;
+}; 
+
+
+/////////////////////////////////////////////////////////////////// 
+/// Inline methods: 
+/////////////////////////////////////////////////////////////////// 
+
+inline const InterfaceID& SGAudSvc::interfaceID() 
+{ 
+   return ISGAudSvc::interfaceID(); 
+}
+
+#endif 
diff --git a/Control/SGMon/SGAudSvc/cmt/requirements b/Control/SGMon/SGAudSvc/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..3b70a3755a41a23b49346591786f9b47c3171861
--- /dev/null
+++ b/Control/SGMon/SGAudSvc/cmt/requirements
@@ -0,0 +1,31 @@
+package SGAudSvc
+
+author  Ilija Vukotic <ivukotic@cern.ch>
+
+use AtlasPolicy 	AtlasPolicy-*
+use AthenaKernel        AthenaKernel-*          Control
+use AthenaBaseComps     AthenaBaseComps-*       Control
+
+## For Gaudi tools, services and objects
+use GaudiInterface 	GaudiInterface-* 	External
+
+## Put here your package dependencies...
+use SGAudCore		SGAudCore-*		Control/SGMon
+
+private
+use StoreGate		StoreGate-*		Control
+
+public
+branches src src/components doc share
+
+
+## make a component library
+library SGAudSvc *.cxx components/*.cxx
+
+apply_pattern component_library
+#apply_pattern declare_joboptions files="*.py"
+apply_pattern declare_python_modules files="*.py"
+
+apply_pattern declare_scripts files="SGout2dot.py"
+
+alias SGout2dot SGout2dot.py
diff --git a/Control/SGMon/SGAudSvc/doc/mainpage.h b/Control/SGMon/SGAudSvc/doc/mainpage.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f5cedb871d1c07a9f8d6edcf261798d51edfc6e
--- /dev/null
+++ b/Control/SGMon/SGAudSvc/doc/mainpage.h
@@ -0,0 +1,32 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+@mainpage  SGAudSvc
+@author ivukotic@cern.ch
+
+@section MyPackageIntro Introduction
+
+This package gives a graphical representation of algorithms accessing StoreGate.
+SGAudSvc instruments retrieve and record functions of StoreGate and from there gets name of object accessed. Upon getting an object name it asks AlgContexSvc for a name of current algorithm. At the end of run, ascii file is produced (default name SGAudSvc.out). 
+This file is further used by SGout2dot.py to produce .dot file.
+To obtain ps file from dot file you may use:'dot -Tps graph1.dot -o graph1.ps'. Still it is nicer to use Graphviz to directly see the plots and if needed edit them by hand. 
+
+Please keep in mind that data are not collected for the first three events.
+
+    
+@ref used_MyPackage
+   
+@ref requirements_MyPackage
+*/
+ 
+/**
+@page used_MyPackage Used Packages
+@htmlinclude used_packages.html
+*/
+
+/**
+@page requirements_MyPackage Requirements
+@include requirements
+*/
diff --git a/Control/SGMon/SGAudSvc/share/SGout2dot.py b/Control/SGMon/SGAudSvc/share/SGout2dot.py
new file mode 100755
index 0000000000000000000000000000000000000000..01537df5262e3b1c12c0b7c43b2a9a4b23b60794
--- /dev/null
+++ b/Control/SGMon/SGAudSvc/share/SGout2dot.py
@@ -0,0 +1,277 @@
+#!/usr/bin/env python
+#TODO : prune standalone alg and objects
+#       remove number of read write
+# remove monitoring, L1, CTP
+# arrow show be single side !
+# @file:    SGout2dot.py
+# @purpose: read a SGAudSvc produced file and make dot file.
+# @author:  Ilija Vukotic <ivukotic@cern.ch>
+# @date:    May 2007
+#
+# @example:
+#
+# checkFile SGAudSvc.out
+
+__version__ = "$Revision: 1.2 $"
+__author__  = "Ilija Vukotic <ivukotic@cern.ch>"
+
+import sys
+import os
+import shutil
+import glob
+
+# some configuration booleans
+debug=True
+debugRemove=False
+drawNReadWrite=False # if draw on each line the number of read and write
+
+
+#Algorithms to be masked. Might need to be tuned
+lRemove=[]
+lRemove+= ["MboyMuonChamberT0"]
+lRemove+= ['Stream','StreamAOD','noKey',"basic_"]
+lRemove+= ["Trig","HLT","EF","L1","Mon","CTP","RoIB","GlobalManager"]
+#lRemove += ['LArRawChannelCollection','TileRawChannelCollection','DetStatusAlg','DetectorStatus','_Data','_Link']
+#lRemove+= ['EventSelector','Input']
+#lRemove+= ['iPatStatistics']
+def chLabel(inpVal):
+	result=inpVal
+	result=result.replace('>','_GT_')
+	result=result.replace('<','_LT_')
+	result=result.replace('::','_')
+	result=result.replace('.','_')
+	result=result.replace('+','_')	
+	return result
+
+
+
+def isNumb(inpVal):
+	result = False
+	try:                                
+		stripped = str(int(inpVal))
+		result=True
+	except:
+		result=False
+	return result
+
+def toRemove(inpVal):
+	result=False
+	if isNumb(inpVal)==True:
+		if debugRemove:
+			print "remove ", inpVal, "is a number"
+		result=True
+	for thing in lRemove:
+		if inpVal.count(thing)>0:
+			if debugRemove:
+				print "remove ", inpVal ,"since it contains", thing
+			result=True
+	return result
+
+nArgs= len (sys.argv)
+outFN="dot.dot"
+inFN=""
+if nArgs==1:
+	print "Usage: SGout2dot.py input_filename [output dot file]"
+	sys.exit()
+if nArgs>1:
+	print "Input file",sys.argv[1]
+	inFN=sys.argv[1]
+if nArgs==3:
+	print "Output file",sys.argv[2]
+	outFN=sys.argv[2]
+try:
+	fi = open (inFN)
+except:
+	print "No such file!"
+	sys.exit()
+	
+fo = open (outFN, 'w' )
+
+lines = fi.readlines()
+fi.close() 
+
+# get number of algs
+line=lines.pop(0)
+words=line.split(' ')
+nAlgs=int(words[1])
+print '%(a)d algorithms found'%{'a':nAlgs}
+
+#read all algs
+#note that algs to be removed cannot be masked before reading the alg <-> obj relation
+algs=[]
+nGoodAlgs=0
+for i in range(nAlgs):
+	line=lines.pop(0).strip('\n')
+	line=line.replace('/','_')
+	algs.append(line)
+	if toRemove(line):
+		print "alg %s to be removed" % line
+	else:
+		nGoodAlgs+=1
+
+print " number of good algs ",nGoodAlgs," bad algs ",nAlgs-nGoodAlgs
+if debug:
+	print algs
+
+# get number of objs
+line=lines.pop(0)
+words=line.split(' ')
+nObjs=int(words[1])
+print '%(a)d objects found'%{'a':nObjs}
+
+# get all object names, and replace possible annoying characters
+#note that objs to be removed cannot be masked before reading the alg <-> obj relation
+objs=[]
+nGoodObjs=0
+for i in range(nObjs):
+	line=lines.pop(0).strip('\n')
+	line=line.replace('/','_')
+	line=line.replace('<','LT')
+	line=line.replace('>','GT')
+	line=line.replace('+','_')
+	objs.append(line)
+	if toRemove(line):
+		print "obj %s to be removed" % line
+	else:
+		nGoodObjs+=1
+
+print " number of good objs ",nGoodObjs," bad objs ",nObjs-nGoodObjs	
+if debug:
+	print objs
+
+fo.write("// %s algorithms and %s objects \n" % (nGoodAlgs,nGoodObjs))
+	
+
+#write out dot file header
+fo.write("digraph SGAudSvc{\nrankdir=LR;\n") # begining and graph stuff
+fo.write("ratio=0.7;\nnodesep=0.05;\n")
+fo.write("subgraph c_0{\nnode[style=filled,color=red];\n") # alg subgraph
+fo.write("label=\"Algs READING\";\ncolor=red;\n")
+
+# get the relations betwen alg and obj
+# TODO number write or read not kept at this point
+objsWrittenByAlg={}  #A->many O (A write O may read it as well)
+objsReadByAlg={}  #many O->A (A read O may do not read it )
+algsWritingObj={}  #many A->O (A write O may read it as well).
+algsReadingObj={} # O->many A (A does not write O)
+for alg in algs:
+	line=lines.pop(0)
+	words=line.strip('\n').split('\t')
+	for obj in objs:
+		rw=words.pop(0).split(':')
+		reads=int(rw[0])
+		writes=int(rw[1])
+		if reads==0 and writes==0:
+			continue
+		if toRemove(obj) or toRemove(alg):
+			continue
+		#print alg,obj,reads, writes
+
+		if writes==0 and reads>0:
+			if not obj in algsReadingObj.keys():
+				algsReadingObj[obj]=[]
+			algsReadingObj[obj]+=[(alg,reads,writes)]
+			if not alg in objsReadByAlg.keys():
+				objsReadByAlg[alg]=[]
+			objsReadByAlg[alg]+=[obj]
+		elif writes>0:
+			if not obj in algsWritingObj.keys():
+				algsWritingObj[obj]=[]
+			algsWritingObj[obj]+=[alg]
+
+			if not alg in objsWrittenByAlg.keys():
+				objsWrittenByAlg[alg]=[]
+			objsWrittenByAlg[alg]+=[(obj,reads,writes)]
+
+
+#write out all algorithms, but only the ones that have at least one connection (and are not masked)
+for alg in algs:
+	if toRemove(alg)==False:
+		if alg in objsWrittenByAlg or alg in objsReadByAlg:
+			towrite='a_%(a)s [label=\"%(a)s\"];\n'%{'a':chLabel(alg),'b':alg}
+			fo.write(towrite)
+		else:
+			print "alg %s masked because not connected" % alg
+			
+fo.write("}\n\nsubgraph c_1{\nnode[style=filled,shape=box];\ncolor=green;label=\"Objects\";\n")
+#write out all objecs
+for obj in objs:
+	if toRemove(obj)==False:
+		if obj in algsWritingObj or obj in algsReadingObj:
+			towrite='o_%(a)s [label=\"%(b)s\"];\n'%{'a':chLabel(obj),'b':obj}
+			fo.write(towrite)
+		else:
+			print "obj %s masked because not connected" % obj			
+fo.write("}\n\n")
+
+
+if debug:
+	print " "
+	print "objsWrittenByAlg:", objsWrittenByAlg
+	print " "
+	print "objsReadByAlg:", objsReadByAlg
+	print " "
+	print "algsWritingObj:", algsWritingObj
+	print " "
+	print "algsReadingObj:", algsReadingObj
+	print " "
+	
+#write the connection a to obj
+for alg in objsWrittenByAlg.keys():
+	for objrec in objsWrittenByAlg[alg]:
+		obj=objrec[0]
+		reads=objrec[1]
+		writes=objrec[2]
+		towrite='a_%(ALG)s -> o_%(OBJ)s [ '%{'ALG':chLabel(alg),'OBJ':chLabel(obj)}
+		if drawNReadWrite:
+			if reads==0:
+				towrite+='label=\"%s\" ' % writes
+			else:
+				# if read in addition to write, write both number of read and write plus double arrow
+				# this happen when an alg writes an object and read it back to modify it
+				towrite+='label=\"w:%(WRITES)s r:%(READS)s\" arrowtail=\"normal\" '%{'WRITES':writes,'READS':reads}				
+		else:
+			if reads>0: # double arrow
+				towrite+='arrowtail=\"normal\" '				
+		towrite+='];\n'
+		fo.write(towrite)
+
+#write the connection obj to alg
+# by definition only read no write
+for obj in algsReadingObj.keys():
+	for algrec in algsReadingObj[obj]:
+		alg=algrec[0]
+		reads=algrec[1]
+		writes=algrec[2]
+
+		towrite='o_%(OBJ)s -> a_%(ALG)s [ '%{'ALG':chLabel(alg),'OBJ':chLabel(obj)}
+		if drawNReadWrite:
+			towrite+='label=\"%s\" ' % reads
+		towrite+='];\n'
+		fo.write(towrite)
+
+## # get the relations betwen alg and obj, and write them out
+## for alg in algs:
+## 	alg=chLabel(alg)
+## 	line=lines.pop(0)
+## 	words=line.strip('\n').split('\t')
+## 	for obj in objs:
+## 		rw=words.pop(0).split(':')
+## 		reads=rw[0]
+## 		writes=rw[1]
+## 		#print alg,obj,reads, writes
+## 		if toRemove(obj)==False and toRemove(alg)==False:
+## 				if int(writes)>0 and int(reads)>0:
+## 					towrite='a_%(ALG)s -> o_%(OBJ)s [label=\"w:%(WRITES)s r:%(READS)s\" '%{'ALG':alg,'OBJ':obj,'WRITES':writes,'READS':reads}
+## 					towrite+='arrowtail=\"normal\"];\n'
+## 					fo.write(towrite)
+## 				else:
+## 					if int(writes)>0:
+## 						towrite='a_%(ALG)s -> o_%(OBJ)s [label=\"%(WRITES)s\"];\n'%{'ALG':alg,'OBJ':obj,'WRITES':writes}
+## 						fo.write(towrite)
+## 					if int(reads)>0:
+## 						towrite='o_%(OBJ)s -> a_%(ALG)s [label=\"%(READS)s\"];\n'%{'ALG':alg,'OBJ':obj,'READS':reads}
+## 						fo.write(towrite)
+
+fo.write("}")
+fo.close()
diff --git a/Control/SGMon/SGAudSvc/share/checkFileSG.py b/Control/SGMon/SGAudSvc/share/checkFileSG.py
new file mode 100755
index 0000000000000000000000000000000000000000..20095fe7ed59edf3ddb6b5fee64ed1c8ae0c9273
--- /dev/null
+++ b/Control/SGMon/SGAudSvc/share/checkFileSG.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python
+
+# @file:    checkFileSG.py
+# @purpose: answers queries on a SGAudSvc produced file
+# @author:  Ilija Vukotic <ivukotic@cern.ch>
+# @date:    October 2007
+#
+# @example:
+#
+# checkFileSG SGAudSvc.out 
+
+__version__ = "$Revision: 1.1 $"
+__author__  = "Ilija Vukotic <ivukotic@cern.ch>"
+
+import sys
+import os
+import shutil
+import glob
+
+lRemove = ['_Data','_Link','noKey','HLTAuto','CBNT_']
+
+def toSkip(inpName):
+	for comp in lRemove:
+		if inpName.count(comp)>0:
+			return True
+	return False
+
+def toRemove(inpVal):
+	result=False
+	if isNumb(inpVal)==True:
+		print "remove ", inpVal, "is a number"
+		result=True
+	for thing in lRemove:
+		if inpVal.count(thing)>0:
+			print "remove ", inpVal ,"since it contains", thing
+			result=True
+	return result
+
+def findMatches(iAlg, iObj, F, Fa, Fo):
+	n=0
+	print "---- algos -----"
+	for alg in iAlg: #----------------> find matching algos
+		if alg.count(F)>0 and not toSkip(alg):
+			Fa.append(alg)
+			print  alg
+			n+=1
+	print '---- objects ----'
+	for obj in iObj: #---------------> find matching objects
+		if obj.count(F)>0 and not toSkip(obj):
+			Fobj.append(obj)
+			print  obj
+			n+=1
+	print '-----------------'
+	return  n
+
+nArgs= len (sys.argv)
+inFN=''
+if nArgs==1:
+	print "Usage: checkFileSG.py input_filename "
+	sys.exit()
+if nArgs>1:
+	print "Input file: ",sys.argv[1]
+	inFN=sys.argv[1]
+try:
+	fi = open (inFN)
+except:
+	print "No such file!"
+	sys.exit()
+	
+
+lines = fi.readlines()
+fi.close() 
+
+#===================================================================
+line=lines.pop(0)
+words=line.split(' ')
+nAlgs=int(words[1])
+print '%(a)d algorithms found'%{'a':nAlgs}
+
+algs=[]
+for i in range(nAlgs):   # -------------------> reading alg names
+	line=lines.pop(0).strip('\n')
+	line=line.replace('/','_')
+	algs.append(line)
+	
+#print algs
+
+line=lines.pop(0)
+words=line.split(' ')
+nObjs=int(words[1])
+print '%(a)d objects found'%{'a':nObjs}
+
+objs=[]
+for i in range(nObjs):   # ----------------> reading object names
+	line=lines.pop(0).strip('\n')
+	line=line.replace('/','_')
+	line=line.replace('<','LT')
+	line=line.replace('>','GT')
+	objs.append(line)
+#==================================================================	
+
+
+Falg=[]; Fobj=[]
+LF=raw_input('Please enter algorithm or SG object name: ')
+
+
+while (findMatches(algs, objs, LF, Falg, Fobj)!=1):   #----------> getting single input
+	LF=raw_input('Please enter algorithm or SG object name. To exit type \'x\' : ')
+	if LF=='x':
+		sys.exit(0)
+	Falg=[];Fobj=[]
+
+
+
+print 'Calculating calls for:',LF,' '
+if len(Falg)>0:
+	#print 'algorithms', Falg
+	ind=algs.index(Falg[0])+1
+	for i in range(ind):
+		line=lines.pop(0)
+		#print line
+	words=line.strip('\n').split('\t')
+	for obj in objs:
+		rw=words.pop(0).split(':')
+		#print rw
+		reads=int(rw[0])
+		writes=int(rw[1])
+		if (reads+writes)>0:
+			print 'Object:',obj, "has been accessed",reads,"times and written",writes,"times."
+		
+else:
+	#print 'objects',Fobj
+	ind=objs.index(Fobj[0])
+	for i in range(len(algs)):
+		line=lines.pop(0)
+		words=line.strip('\n').split('\t')
+		rw=words[ind].split(':')
+		reads=int(rw[0])
+		writes=int(rw[1])
+		if (reads+writes)>0:
+			print 'Algorithm',algs[i],'accessed object',reads,'times and wrote it',writes,'times'
+	
+sys.exit(0)
diff --git a/Control/SGMon/SGAudSvc/src/SGAudSvc.cxx b/Control/SGMon/SGAudSvc/src/SGAudSvc.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..8b2e42758df2043a3255bea508365c23407cf329
--- /dev/null
+++ b/Control/SGMon/SGAudSvc/src/SGAudSvc.cxx
@@ -0,0 +1,523 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// SGAudSvc.cxx 
+// Implementation file for class SGAudSvc
+// Author: Ilija Vukotic<ivukotic@cern.ch>
+/////////////////////////////////////////////////////////////////// 
+
+
+// STL includes
+#include <sstream>
+#include <fstream>
+#include <vector>
+#include <set>
+#include <utility>
+
+// FrameWork includes
+#include "GaudiKernel/Property.h"
+#include "GaudiKernel/SvcFactory.h"
+#include "GaudiKernel/IIncidentSvc.h"
+#include "GaudiKernel/Incident.h"
+#include "GaudiKernel/IAlgContextSvc.h"
+
+// StoreGate includes
+#include "StoreGate/StoreGateSvc.h"
+#include "StoreGate/DataHandle.h"
+
+// SGAudSvc includes
+#include "SGAudSvc/SGAudSvc.h"
+/////////////////////////////////////////////////////////////////// 
+// Public methods: 
+/////////////////////////////////////////////////////////////////// 
+
+/*----------------------------------------------------------------------------*/
+// Constructors
+////////////////
+SGAudSvc::SGAudSvc( const std::string& name, ISvcLocator* pSvcLocator ) : 
+  AthService  ( name,     pSvcLocator ),
+  m_msg       ( msgSvc(),        name ), 
+  p_algCtxSvc(0), m_pCID(0), m_useCLID(true),
+  m_nCurrAlg(0),
+  m_nCurrObj(0),
+  m_nEvents(0), m_startEvent(3), m_inExec(false)
+{
+  //
+  // Property declaration
+  // 
+  declareProperty( "OutFileName", m_outFileName = "SGAudSvc.out",
+		   "Name of the output file to hold SGAudSvc data" );
+
+  declareProperty( "FullFileName", m_allFileName = "",
+		   "Name of the output file to hold the full SG aud data");
+
+  declareProperty( "SummaryFileName", m_sumFileName = "",
+		   "Name of the output file to hold the summary output in json format");
+
+  declareProperty( "IgnoreFakeAlgs", m_ignoreFakeAlgs = false,
+		   "Set to ignore any attempts to override current-alg" );
+
+  declareProperty( "StartEvent", m_startEvent = 3,
+		   "Event number to start recording data" );
+
+  declareProperty( "UseCLID", m_useCLID = true,
+		   "Use CLID or DataObj name in Summary File" );
+}
+
+/*----------------------------------------------------------------------------*/
+// Destructor
+///////////////
+SGAudSvc::~SGAudSvc()
+{ 
+  m_msg << MSG::DEBUG << "Calling destructor" << endreq;
+}
+
+/*----------------------------------------------------------------------------*/
+
+// Athena Algorithm's Hooks
+////////////////////////////
+StatusCode 
+SGAudSvc::initialize() {
+  
+  // initialize MsgStream
+  m_msg.setLevel( m_outputLevel.value() );
+
+  m_msg << MSG::INFO  << "Initializing " << name() << "..."  << endreq;
+  
+  if ( AthService::initialize().isFailure() ) {
+    m_msg << MSG::ERROR  << "Could not intialize base class !!"  << endreq;
+    return StatusCode::FAILURE;
+  }
+
+  static const bool CREATEIF(true);
+  
+  if ( service("AlgContextSvc",p_algCtxSvc,CREATEIF).isFailure() ) {
+    m_msg << MSG::ERROR << "Unable to retrieve the AlgContextSvc" << endreq;
+    return StatusCode::FAILURE;
+  }
+  
+  assert(p_algCtxSvc);
+
+  if ( service("ClassIDSvc",m_pCID,CREATEIF).isFailure() ) {
+    m_msg << MSG::ERROR << "Unable to retrieve the ClassIDSvc" << endmsg;
+    return StatusCode::FAILURE;
+  }
+
+  if (m_allFileName != "") {
+    m_ofa.open(m_allFileName.c_str());
+  }
+
+  if (m_sumFileName != "") {
+    m_ofs.open(m_sumFileName.c_str());
+  }
+  
+  // Set to be listener for end-of-event
+  ServiceHandle<IIncidentSvc> incSvc( "IncidentSvc", this->name() );
+  if ( !incSvc.retrieve().isSuccess() ) {
+    m_msg << MSG::ERROR << "Unable to get the IncidentSvc" << endreq;
+    return StatusCode::FAILURE;
+  }
+  incSvc->addListener( this, IncidentType::BeginRun );
+  incSvc->addListener( this, IncidentType::BeginEvent );
+  incSvc->addListener( this, IncidentType::EndEvent );
+
+  return StatusCode::SUCCESS;
+}
+
+/*----------------------------------------------------------------------------*/
+
+StatusCode 
+SGAudSvc::finalize() {
+
+  m_msg << MSG::INFO << "Finalizing " << name() <<"..."<< endreq;
+  
+  if (m_vAlg.size()==0) {
+    m_msg << MSG::WARNING<<"No data gathered. This might be because you did not run over at least 3 events."<<endreq;
+    return StatusCode::SUCCESS;
+  }
+  
+  m_msg << MSG::INFO<<"Writing output to: "<<m_outFileName<<endreq;
+  std::ofstream f( m_outFileName.c_str() );
+  
+  f << "Algs: " << m_vAlg.size() << std::endl;
+  std::vector<std::string>::iterator i;
+  for (i=m_vAlg.begin();i<m_vAlg.end();i++) {
+          f << (*i) << std::endl;
+  }
+  
+  f << "Obj: "<< m_vObj.size()<<std::endl;
+  for (i=m_vObj.begin();i<m_vObj.end();i++) {
+          f << (*i) << std::endl; 
+  }
+
+  
+  for (unsigned int w=0;w<m_vAlg.size();w++){
+    for(unsigned int q=0;q<m_vObj.size();q++){
+      int oaHash=q*1000 + w;
+      if (m_timesRead.find(oaHash)==m_timesRead.end())
+	f << "0:";
+      else
+	f << m_timesRead.find(oaHash)->second << ":";
+      if (m_timesWritten.find(oaHash)==m_timesWritten.end())
+	f << "0\t";
+      else
+	f << m_timesWritten.find(oaHash)->second << "\t";	
+    }
+    f << std::endl;
+  }
+  
+  f.close();
+
+  if (m_ofa.is_open()) m_ofa.close();
+
+  if (m_ofs.is_open()) {
+
+    writeJSON();
+
+    m_ofs.close();
+  }
+
+
+  return StatusCode::SUCCESS;
+}
+
+/*----------------------------------------------------------------------------*/
+
+// Query the interfaces.
+StatusCode 
+SGAudSvc::queryInterface(const InterfaceID& riid, void** ppvInterface) 
+{
+  if ( ISGAudSvc::interfaceID().versionMatch(riid) ) {
+    *ppvInterface = dynamic_cast<ISGAudSvc*>(this);
+  } else {
+    // Interface is not directly available : try out a base class
+    return AthService::queryInterface(riid, ppvInterface);
+  }
+  addRef();
+  return StatusCode::SUCCESS;
+}
+
+/////////////////////////////////////////////////////////////////// 
+// Const methods: 
+///////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////// 
+// Non-const methods: 
+/////////////////////////////////////////////////////////////////// 
+
+/*----------------------------------------------------------------------------*/
+
+void 
+SGAudSvc::handle( const Incident& inc )
+{
+  if ( m_msg.level() <= MSG::VERBOSE ) {
+    m_msg << MSG::VERBOSE << "Entering handle(): " << endreq
+	  << "  Incidence type: " << inc.type()   << endreq
+	  << "            from: " << inc.source() << endreq;
+  }
+
+  if (inc.type() == IncidentType::BeginEvent) {
+    if (m_ofa.is_open())
+      m_ofa << "---- BEGIN EVENT " << m_nEvents << " ----" << std::endl;
+    m_inExec = true;
+
+  }
+
+  // Performing performance-monitoring for EndEvent incident
+  if ( inc.type() == IncidentType::EndEvent ) {
+    monitor();
+
+    if (m_ofa.is_open()) 
+      m_ofa << "---- END EVENT " << m_nEvents << " ----" << std::endl;
+    m_inExec = false;
+
+  }
+
+  // Performing performance-monitoring for BeginRun incident
+  // at this point everybody has been initialized, we can harvest performance
+  // data for the initialize step.
+  
+  if ( inc.type() == IncidentType::BeginRun ) {
+    monitor();
+  }
+
+  return;
+}
+
+/////////////////////////////////////////////////////////////////// 
+// Protected methods: 
+/////////////////////////////////////////////////////////////////// 
+
+/////////////////////////////////////////////////////////////////// 
+// Const methods: 
+///////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////// 
+// Non-const methods: 
+/////////////////////////////////////////////////////////////////// 
+		
+/*----------------------------------------------------------------------------*/
+
+void 
+SGAudSvc::monitor(){
+  m_nEvents++;
+  return;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void 
+SGAudSvc::SGAudRETRIEVE(std::string SGobject){
+  // if (m_nEvents<3) return;
+  if (SGobject=="") SGobject="noKey";
+  bool isAnumb=true;
+  for (unsigned int i = 0; i < SGobject.length(); i++)        
+    if (!std::isdigit(SGobject[i])){
+      isAnumb=false; 
+      break;   
+    }
+
+  if (!isAnumb){
+    if (m_currObj==SGobject) 
+      addRead();
+    else {
+      getNobj(SGobject);
+      addRead();
+    }
+  }
+  return;	
+}
+
+/*----------------------------------------------------------------------------*/
+
+void 
+SGAudSvc::SGAudRECORD(std::string SGobject){
+  // if (m_nEvents<3) return;
+  if (SGobject=="") SGobject="noKey";  
+  for (unsigned int i = 0; i < SGobject.length(); i++)        
+    if (!std::isdigit(SGobject[i])){
+      //isAnumb=false; 
+      break;   
+    }
+  
+  if (m_currObj==SGobject) 
+    addWrite();
+  else {
+    getNobj(SGobject);
+    addWrite();
+  }
+
+  return;	
+}
+
+/*----------------------------------------------------------------------------*/
+void 
+SGAudSvc::SGAudit(const std::string& key, const CLID& id, 
+		  const int& typ, const int& store_id) {
+
+  // we can sometimes get here really early, before initialization.
+  if (m_pCID == 0) { return; }
+
+  bool a = SGGetCurrentAlg();  
+
+  if (m_nEvents >= m_startEvent && store_id == 0 && a) {
+    if (typ == 0) {
+      SGAudRETRIEVE(key);
+    } else {
+      SGAudRECORD(key);
+    }
+  }
+
+  std::string idname;
+
+  if (m_ofa.is_open() || ( m_ofs.is_open() && ! m_useCLID ) ) {
+      if( ! m_pCID->getTypeNameOfID(id,idname).isSuccess()) {
+	std::ostringstream ost;
+	ost << id;
+	idname = ost.str();
+      }
+  }
+
+  if (m_ofa.is_open()) {
+    m_ofa << ( (typ == 1) ? "RECORD" : "RETRIEVE" ) << " clid: " << id 
+	  << " | ";
+    
+    m_ofa << idname;
+
+    m_ofa << "  key: " << key << "  alg: " << m_currAlg 
+	  << "  store: " << store_id
+	  << std:: endl;
+  }    
+
+  // store stuff for the summary
+
+  if (!m_ofs.is_open()) return;
+  
+  if (m_nEvents < m_startEvent || !m_inExec) return;
+  
+  if (m_currAlg == "----") return;
+    
+  std::string kk;
+  if (m_useCLID) {
+    std::ostringstream ost;
+    ost << id << "/" << key;
+    kk = ost.str();
+  } else {
+    kk = idname + "/" + key;
+  }
+
+  DataMap::iterator itr;
+  if (typ == 0) {
+    itr = m_read.find(m_currAlg);
+    if (itr != m_read.end()) {
+      itr->second.insert(kk);
+    } else {
+      m_read[m_currAlg] = std::set<std::string> ( {kk} );
+    }
+  } else {
+    itr = m_write.find(m_currAlg);
+    if (itr != m_write.end()) {
+      itr->second.insert(kk);
+    } else {
+      m_write[m_currAlg] = std::set<std::string> ( {kk} );
+    }
+  }
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool 
+SGAudSvc::SGGetCurrentAlg(){
+
+  IAlgorithm *asdf = p_algCtxSvc->currentAlg();
+  if (!asdf || m_nEvents==0) { // to skip before first event 
+    m_currAlg="----";
+    m_nCurrAlg=-1;
+    return false;
+  }
+  std::string name = asdf->name();
+  
+  if ( !m_ignoreFakeAlgs && !m_fakeCurrAlg.empty() )
+    name=m_fakeCurrAlg;
+  
+  if (name!=m_currAlg){
+    std::vector<std::string>::iterator i;
+    int index=0;
+    for (i=m_vAlg.begin();i<m_vAlg.end();i++){
+      if (*i==name) {
+	m_nCurrAlg=index;
+	m_currAlg=name;
+	return true;
+      }
+      index++;
+    }
+    m_vAlg.push_back(name);
+    m_nCurrAlg=index;
+    m_currAlg=name;
+    return true;
+  }
+  return true;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void 
+SGAudSvc::getNobj(std::string name){
+  std::vector<std::string>::iterator i;
+  int index=0;
+  for (i=m_vObj.begin();i<m_vObj.end();i++){
+    if (*i==name) {
+      m_nCurrObj=index;
+      m_currObj=name;
+      return;
+    }
+    index++;
+  }  
+  m_vObj.push_back(name);
+  m_nCurrObj=index;
+  m_currObj=name;
+return;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void 
+SGAudSvc::addRead(){
+  int oaHash=m_nCurrObj*1000 + m_nCurrAlg;
+  if (m_timesRead.end()!=m_timesRead.find(oaHash)){
+    m_timesRead.find(oaHash)->second++;
+  } 
+  else{
+    std::pair<int,int> p(oaHash,1);
+    m_timesRead.insert(p);
+  }
+  return;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void 
+SGAudSvc::addWrite(){
+  int oaHash=m_nCurrObj*1000 + m_nCurrAlg;
+  if (m_timesWritten.end()!=m_timesWritten.find(oaHash)){
+    m_timesWritten.find(oaHash)->second++; 
+  }
+  else{
+    std::pair<int,int> p(oaHash,1);
+    m_timesWritten.insert(p);
+  }
+  return;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void 
+SGAudSvc::setFakeCurrentAlg( const std::string& s ) { m_fakeCurrAlg=s; }
+
+/*----------------------------------------------------------------------------*/
+
+void 
+SGAudSvc::clearFakeCurrentAlg() { m_fakeCurrAlg.clear(); }
+
+/*----------------------------------------------------------------------------*/
+
+void
+SGAudSvc::writeJSON() {
+
+  DataMap::const_iterator itr;
+  std::set<std::string>::const_iterator it2;
+  std::vector<std::string>::const_iterator ia;
+  
+  m_ofs << "{ \"algorithms\" : [" << std::endl;
+  for (ia = m_vAlg.begin(); ia != m_vAlg.end(); ++ia) {
+    m_ofs << " {" << std::endl;
+    m_ofs << "  \"name\" : \"" << *ia << "\"," << std::endl;
+    m_ofs << "  \"inputs\" : [";
+    
+    itr = m_read.find(*ia);
+    if (itr != m_read.end()) {
+      for (it2 = itr->second.begin(); it2 != itr->second.end(); ++it2) {
+	if (it2 != itr->second.begin()) m_ofs << ",";
+	m_ofs << "\"" << *it2 << "\"";
+      }
+    }
+    m_ofs << "]," << std::endl;
+    
+    m_ofs << "  \"outputs\" : [";
+    
+    itr = m_write.find(*ia);
+    if (itr != m_write.end()) {
+      for (it2 = itr->second.begin(); it2 != itr->second.end(); ++it2) {
+	if (it2 != itr->second.begin()) m_ofs << ",";
+	m_ofs << "\"" << *it2 << "\"";
+      }
+    }
+    m_ofs << "]," << std::endl;    
+    m_ofs << " }," << std::endl;
+  }
+  m_ofs << " ]" << std::endl << "}" << std::endl;
+
+}
diff --git a/Control/SGMon/SGAudSvc/src/components/SGAudSvc_entries.cxx b/Control/SGMon/SGAudSvc/src/components/SGAudSvc_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..719c6b7d6b39793760226428e3d54a05cf7bdcf9
--- /dev/null
+++ b/Control/SGMon/SGAudSvc/src/components/SGAudSvc_entries.cxx
@@ -0,0 +1,13 @@
+#include "SGAudSvc/SGAudSvc.h"
+//#include "../PerfMonAuditor.h"
+
+#include "GaudiKernel/DeclareFactoryEntries.h"
+  
+DECLARE_SERVICE_FACTORY( SGAudSvc  )
+//DECLARE_AUDITOR_FACTORY( PerfMonAuditor )
+
+DECLARE_FACTORY_ENTRIES( SGAudSvc ) {
+  DECLARE_SERVICE( SGAudSvc )
+//  DECLARE_AUDITOR( PerfMonAuditor )
+
+}
diff --git a/Control/SGMon/SGAudSvc/src/components/SGAudSvc_load.cxx b/Control/SGMon/SGAudSvc/src/components/SGAudSvc_load.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7412b1c6c75fa7f65130fed74ea6f3cff5e4a7e9
--- /dev/null
+++ b/Control/SGMon/SGAudSvc/src/components/SGAudSvc_load.cxx
@@ -0,0 +1,3 @@
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+LOAD_FACTORY_ENTRIES( SGAudSvc )