Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report all files to UDP statistics collector #34873

Closed
nsmith- opened this issue Aug 13, 2021 · 46 comments · Fixed by #35074 or #35505
Closed

Report all files to UDP statistics collector #34873

nsmith- opened this issue Aug 13, 2021 · 46 comments · Fixed by #35074 or #35505

Comments

@nsmith-
Copy link
Contributor

nsmith- commented Aug 13, 2021

For several years now, any cmsRun process at a site with

<source-config>
    <statistics-destination name="cms-udpmon-collector.cern.ch:9331" />
</source-config>

in their site-local-config.xml would send a small UDP packet on every primary file close, reporting the LFN and some summary statistics. The code responsible is found at
https://github.com/cms-sw/cmssw/blob/master/Utilities/StorageFactory/src/StatisticsSenderService.cc
which registers an event watcher:

// edm::ActivityRegistry &ar
ar.watchPreCloseFile(this, &StatisticsSenderService::filePreCloseEvent);

However, empirically this event seems to only fire for files opened through InputSource, and if you search for postCloseFileSignal_, only

InputSource::FileCloseSentry::FileCloseSentry(InputSource const& source, std::string const& lfn, bool usedFallback)
: post_(source.actReg()->postCloseFileSignal_), lfn_(lfn), usedFallback_(usedFallback) {
source.actReg()->preCloseFileSignal_(lfn, usedFallback);
}

shows up. It seems that the mixing module uses a different class chain EmbeddedRootSource : VectorInputSource for file handling. Can we add a postCloseFileSignal_ to this as well?

@cmsbuild
Copy link
Contributor

A new Issue was created by @nsmith- Nicholas Smith.

@Dr15Jones, @perrotta, @dpiparo, @makortel, @smuzaffar, @qliphy can you please review it and eventually sign/assign? Thanks.

cms-bot commands are listed here

@makortel
Copy link
Contributor

assign core

@cmsbuild
Copy link
Contributor

New categories assigned: core

@Dr15Jones,@smuzaffar,@makortel you have been requested to review this Pull request/Issue and eventually sign? Thanks

@makortel
Copy link
Contributor

@nsmith- How urgently would this information be needed?

@nsmith-
Copy link
Contributor Author

nsmith- commented Aug 16, 2021

For now it supplies only additional, monitoring information. So, within a few months would be OK

@makortel
Copy link
Contributor

@nsmith- The reporting of close closures in EmbeddedRootSource is now implemented in #35074. Is it sufficient to add this feature in 12_1_X, or would you need it in some earlier release cycles as well?

@nsmith-
Copy link
Contributor Author

nsmith- commented Sep 7, 2021

I would appreciate if we can backport this to some of the production releases, e.g. 10.6.

@makortel
Copy link
Contributor

makortel commented Sep 7, 2021

@nsmith- I just made a backport to 10_6_X in #35180. If any other release cycle is needed, please ask.

@nsmith-
Copy link
Contributor Author

nsmith- commented Sep 7, 2021

10_6_X covers the digi step for UL so that should be OK for now

@makortel
Copy link
Contributor

makortel commented Sep 9, 2021

So it turns out (thanks @Dr15Jones) that #35074 (and #35180) are causing ASAN failure

==51632==ERROR: AddressSanitizer: attempting double-free on 0x60d0004c03a0 in thread T0:
    #0 0x2b1d84988da7 in operator delete(void*) ../../../../libsanitizer/asan/asan_new_delete.cpp:160
    #1 0x2b1d8837ff11 in __gnu_cxx::new_allocator<char>::deallocate(char*, unsigned long) /data/cmsbld/jenkins/workspace/auto-builds/CMSSW_12_0_0_pre3-slc7_amd64_gcc10/build/CMSSW_12_0_0_pre3-build/BUILD/slc7_amd64_gcc10/external/gcc/10.3.0/gcc-10.3.0/obj/x86_64-unknown-linux-gnu/libstdc++-v3/include/ext/new_allocator.h:133
    #2 0x2b1d8837ff11 in std::allocator_traits<std::allocator<char> >::deallocate(std::allocator<char>&, char*, unsigned long) /data/cmsbld/jenkins/workspace/auto-builds/CMSSW_12_0_0_pre3-slc7_amd64_gcc10/build/CMSSW_12_0_0_pre3-build/BUILD/slc7_amd64_gcc10/external/gcc/10.3.0/gcc-10.3.0/obj/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/alloc_traits.h:492
    #3 0x2b1d8837ff11 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_destroy(unsigned long) /data/cmsbld/jenkins/workspace/auto-builds/CMSSW_12_0_0_pre3-slc7_amd64_gcc10/build/CMSSW_12_0_0_pre3-build/BUILD/slc7_amd64_gcc10/external/gcc/10.3.0/gcc-10.3.0/obj/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/basic_string.h:237
    #4 0x2b1d8837ff11 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_dispose() /data/cmsbld/jenkins/workspace/auto-builds/CMSSW_12_0_0_pre3-slc7_amd64_gcc10/build/CMSSW_12_0_0_pre3-build/BUILD/slc7_amd64_gcc10/external/gcc/10.3.0/gcc-10.3.0/obj/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/basic_string.h:232
    #5 0x2b1d8837ff11 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /data/cmsbld/jenkins/workspace/auto-builds/CMSSW_12_0_0_pre3-slc7_amd64_gcc10/build/CMSSW_12_0_0_pre3-build/BUILD/slc7_amd64_gcc10/external/gcc/10.3.0/gcc-10.3.0/obj/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:266
    #6 0x2b1d8f8a2889 in edm::storage::StatisticsSenderService::filePreCloseEvent(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/libUtilitiesStorageFactory.so+0x3e889)
    #7 0x2b1d9934e45b in edm::RootEmbeddedFileSequence::closeFile_() (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/pluginIOPoolInput.so+0xd645b)
    #8 0x2b1d993f474f in edm::RootInputFileSequence::initTheFile(bool, bool, edm::InputSource*, char const*, edm::InputType) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/pluginIOPoolInput.so+0x17c74f)
    #9 0x2b1d993475b4 in edm::RootEmbeddedFileSequence::readOneRandom(edm::EventPrincipal&, unsigned long&, CLHEP::HepRandomEngine*, edm::EventID const*, bool) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/pluginIOPoolInput.so+0xcf5b4)
    #10 0x2b1ddce4ba4c in unsigned long edm::VectorInputSource::loopOverEvents<edm::RecordEventID<std::_Bind<bool (edm::PreMixingModule::*(std::reference_wrapper<edm::PreMixingModule>, std::_Placeholder<1>, int, std::_Placeholder<2>, std::reference_wrapper<edm::EventSetup const>, edm::ModuleCallingContext const*, edm::PreMixingModule::AdjustPileupDistribution const*))(edm::EventPrincipal const&, int, int, edm::EventSetup const&, edm::ModuleCallingContext const*, edm::PreMixingModule::AdjustPileupDistribution const*)> > >(edm::EventPrincipal&, unsigned long&, unsigned long, edm::RecordEventID<std::_Bind<bool (edm::PreMixingModule::*(std::reference_wrapper<edm::PreMixingModule>, std::_Placeholder<1>, int, std::_Placeholder<2>, std::reference_wrapper<edm::EventSetup const>, edm::ModuleCallingContext const*, edm::PreMixingModule::AdjustPileupDistribution const*))(edm::EventPrincipal const&, int, int, edm::EventSetup const&, edm::ModuleCallingContext const*, edm::PreMixingModule::AdjustPileupDistribution const*)> >, CLHEP::HepRandomEngine*, edm::EventID const*, bool) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/pluginSimGeneralPreMixingModulePlugins.so+0x57a4c)
    #11 0x2b1ddce4c6b0 in void edm::PileUp::readPileUp<std::_Bind<bool (edm::PreMixingModule::*(std::reference_wrapper<edm::PreMixingModule>, std::_Placeholder<1>, int, std::_Placeholder<2>, std::reference_wrapper<edm::EventSetup const>, edm::ModuleCallingContext const*, edm::PreMixingModule::AdjustPileupDistribution const*))(edm::EventPrincipal const&, int, int, edm::EventSetup const&, edm::ModuleCallingContext const*, edm::PreMixingModule::AdjustPileupDistribution const*)> >(edm::EventID const&, std::vector<edm::SecondaryEventIDAndFileInfo, std::allocator<edm::SecondaryEventIDAndFileInfo> >&, std::_Bind<bool (edm::PreMixingModule::*(std::reference_wrapper<edm::PreMixingModule>, std::_Placeholder<1>, int, std::_Placeholder<2>, std::reference_wrapper<edm::EventSetup const>, edm::ModuleCallingContext const*, edm::PreMixingModule::AdjustPileupDistribution const*))(edm::EventPrincipal const&, int, int, edm::EventSetup const&, edm::ModuleCallingContext const*, edm::PreMixingModule::AdjustPileupDistribution const*)>, int, edm::StreamID const&) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/pluginSimGeneralPreMixingModulePlugins.so+0x586b0)
    #12 0x2b1ddce32c83 in edm::PreMixingModule::doPileUp(edm::Event&, edm::EventSetup const&) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/pluginSimGeneralPreMixingModulePlugins.so+0x3ec83)
    #13 0x2b1ddc413d08 in edm::BMixingModule::produce(edm::Event&, edm::EventSetup const&) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/libMixingBase.so+0x4cd08)
    #14 0x2b1d85baedde in edm::stream::EDProducerAdaptorBase::doEvent(edm::EventTransitionInfo const&, edm::ActivityRegistry*, edm::ModuleCallingContext const*) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/libFWCoreFramework.so+0x909dde)
    #15 0x2b1d85b1b492 in edm::WorkerT<edm::stream::EDProducerAdaptorBase>::implDo(edm::EventTransitionInfo const&, edm::ModuleCallingContext const*) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/libFWCoreFramework.so+0x876492)
    #16 0x2b1d85809564 in decltype ({parm#1}()) edm::convertException::wrap<edm::Worker::runModule<edm::OccurrenceTraits<edm::EventPrincipal, (edm::BranchActionType)1> >(edm::OccurrenceTraits<edm::EventPrincipal, (edm::BranchActionType)1>::TransitionInfoType const&, edm::StreamID, edm::ParentContext const&, edm::OccurrenceTraits<edm::EventPrincipal, (edm::BranchActionType)1>::Context const*)::{lambda()#1}>(edm::Worker::runModule<edm::OccurrenceTraits<edm::EventPrincipal, (edm::BranchActionType)1> >(edm::OccurrenceTraits<edm::EventPrincipal, (edm::BranchActionType)1>::TransitionInfoType const&, edm::StreamID, edm::ParentContext const&, edm::OccurrenceTraits<edm::EventPrincipal, (edm::BranchActionType)1>::Context const*)::{lambda()#1}) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/libFWCoreFramework.so+0x564564)
    #17 0x2b1d85809daa in std::__exception_ptr::exception_ptr edm::Worker::runModuleAfterAsyncPrefetch<edm::OccurrenceTraits<edm::EventPrincipal, (edm::BranchActionType)1> >(std::__exception_ptr::exception_ptr const*, edm::OccurrenceTraits<edm::EventPrincipal, (edm::BranchActionType)1>::TransitionInfoType const&, edm::StreamID, edm::ParentContext const&, edm::OccurrenceTraits<edm::EventPrincipal, (edm::BranchActionType)1>::Context const*) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/libFWCoreFramework.so+0x564daa)
    #18 0x2b1d85815806 in edm::Worker::RunModuleTask<edm::OccurrenceTraits<edm::EventPrincipal, (edm::BranchActionType)1> >::execute() (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/libFWCoreFramework.so+0x570806)
    #19 0x2b1d8650b231 in tbb::detail::d1::function_task<edm::WaitingTaskList::announce()::{lambda()#1}>::execute(tbb::detail::d1::execution_data&) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/libFWCoreConcurrency.so+0x11231)
    #20 0x2b1d87b467fe in tbb::detail::d1::task* tbb::detail::r1::task_dispatcher::local_wait_for_all<false, tbb::detail::r1::external_waiter>(tbb::detail::d1::task*, tbb::detail::r1::external_waiter&) /data/cmsbld/jenkins/workspace/build-any-ib/w/BUILD/slc7_amd64_gcc10/external/tbb/v2021.3.0-2fe36bef039e4e6ef0dfc9f6fbb735c9/tbb-v2021.3.0/src/tbb/task_dispatcher.h:321
    #21 0x2b1d87b467fe in tbb::detail::d1::task* tbb::detail::r1::task_dispatcher::local_wait_for_all<tbb::detail::r1::external_waiter>(tbb::detail::d1::task*, tbb::detail::r1::external_waiter&) /data/cmsbld/jenkins/workspace/build-any-ib/w/BUILD/slc7_amd64_gcc10/external/tbb/v2021.3.0-2fe36bef039e4e6ef0dfc9f6fbb735c9/tbb-v2021.3.0/src/tbb/task_dispatcher.h:462
    #22 0x2b1d87b467fe in tbb::detail::r1::task_dispatcher::execute_and_wait(tbb::detail::d1::task*, tbb::detail::d1::wait_context&, tbb::detail::d1::task_group_context&) /data/cmsbld/jenkins/workspace/build-any-ib/w/BUILD/slc7_amd64_gcc10/external/tbb/v2021.3.0-2fe36bef039e4e6ef0dfc9f6fbb735c9/tbb-v2021.3.0/src/tbb/task_dispatcher.cpp:168
    #23 0x2b1d8555553b in edm::EventProcessor::processLumis(std::shared_ptr<void> const&) (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/libFWCoreFramework.so+0x2b053b)
    #24 0x2b1d85585002 in edm::EventProcessor::runToCompletion() (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/lib/slc7_amd64_gcc10/libFWCoreFramework.so+0x2e0002)
    #25 0x40e961 in tbb::detail::d1::task_arena_function<main::{lambda()#1}::operator()() const::{lambda()#1}, void>::operator()() const (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/bin/slc7_amd64_gcc10/cmsRun+0x40e961)
    #26 0x2b1d87b2ef8e in tbb::detail::r1::task_arena_impl::execute(tbb::detail::d1::task_arena_base&, tbb::detail::d1::delegate_base&) /data/cmsbld/jenkins/workspace/build-any-ib/w/BUILD/slc7_amd64_gcc10/external/tbb/v2021.3.0-2fe36bef039e4e6ef0dfc9f6fbb735c9/tbb-v2021.3.0/src/tbb/arena.cpp:696
    #27 0x411e56 in main::{lambda()#1}::operator()() const (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/bin/slc7_amd64_gcc10/cmsRun+0x411e56)
    #28 0x40c605 in main (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/bin/slc7_amd64_gcc10/cmsRun+0x40c605)
    #29 0x2b1d88975554 in __libc_start_main (/lib64/libc.so.6+0x22554)
    #30 0x40c948  (/cvmfs/cms-ib.cern.ch/nweek-02697/slc7_amd64_gcc10/cms/cmssw/CMSSW_12_1_ASAN_X_2021-09-08-2300/bin/slc7_amd64_gcc10/cmsRun+0x40c948)

https://cmssdt.cern.ch/SDT/cgi-bin/logreader/slc7_amd64_gcc10/CMSSW_12_1_ASAN_X_2021-09-08-2300/pyRelValMatrixLogs/run/250207.0_NuGun_UP15+NuGun_UP15INPUT+DIGIPRMXUP15_PU25+RECOPRMXUP15_PU25+HARVESTUP15_PU25/step2_NuGun_UP15+NuGun_UP15INPUT+DIGIPRMXUP15_PU25+RECOPRMXUP15_PU25+HARVESTUP15_PU25.log#/

On a quick inspection it is rather evident that StatisticsSenderService::filePreCloseEvent() is not thread safe. I made an attempt to quickly make it re-entrant, but I'm afraid the StatisticsSenderService would need a more complete overhaul.
In fact I'm suspecting it could already now report incorrect servers. The server names are used in the fillUDP()

{
std::lock_guard<std::mutex> sentry(m_servermutex);
serverhost = m_serverhost;
serverdomain = m_serverdomain;
}

and they are being set in setCurrentServer()
{
std::lock_guard<std::mutex> sentry(m_servermutex);
m_serverhost = std::move(serverhost);
m_serverdomain = std::move(serverdomain);
}

that is being called from
void RequestManager::updateCurrentServer() {
// NOTE: we use memory_order_relaxed here, meaning that we may actually miss
// a pending update. *However*, since we call this for every read, we'll get it
// eventually.
if (LIKELY(!m_serverToAdvertise.load(std::memory_order_relaxed))) {
return;
}
std::string *hostname_ptr;
if ((hostname_ptr = m_serverToAdvertise.exchange(nullptr))) {
std::unique_ptr<std::string> hostname(hostname_ptr);
edm::Service<edm::storage::StatisticsSenderService> statsService;
if (statsService.isAvailable()) {
statsService->setCurrentServer(*hostname_ptr);
}
}
}

But in case pileup files are also being read over xrootd, what guarantees that at the time of primary file close the m_serverhost would still point to the server providing the primary file and not a server for one of the pileup files?

Overhaul of StatisticsSenderService will take some time, so unfortunately for now we need to revert the two PRs. I'll make those shortly.

@nsmith- (or @smuzaffar) Could you reopen this issue?

@nsmith-
Copy link
Contributor Author

nsmith- commented Sep 9, 2021

Is this somehow not a concern for the existing PoolSource usage of StatisticsSenderService? I think even in this case we could have multiple files open thanks to secondary inputs?

@makortel
Copy link
Contributor

makortel commented Sep 9, 2021

All sources do their work serially. It seems to me that the secondary input file closings are not reported to the StatisticsSenderService given that the preFileClose signal is emitted here (via FileCloseSentry)

void RootPrimaryFileSequence::closeFile_() {
// close the currently open file, if any, and delete the RootFile object.
if (rootFile()) {
auto sentry = std::make_unique<InputSource::FileCloseSentry>(input_, lfn(), usedFallback());
rootFile()->close();
if (duplicateChecker_)
duplicateChecker_->inputFileClosed();
rootFile().reset();
}
}

but not here
void RootSecondaryFileSequence::closeFile_() {
// close the currently open file, if any, and delete the RootFile object.
if (rootFile()) {
rootFile()->close();
rootFile().reset();
}
}

Then, given that the PoolSource operates on one primary file at the time, reporting those without explicit protections against other threads is fine (except my earlier concern that the server may get messed up if secondary files or pileup files are read over xrootd).

@nsmith-
Copy link
Contributor Author

nsmith- commented Sep 9, 2021

Ok, and I guess this brings up another feature request to have secondary input file close be reported as well to StatisticsSenderService :)

@makortel
Copy link
Contributor

makortel commented Sep 9, 2021

Here is another issue in addition to the server name. The size of the reported file is set here

void StatisticsSenderService::setSize(size_t size) { m_size = size; }

(m_size is atomic) and that gets called in TStorageFactoryFile::Initialize
edm::Service<edm::storage::StatisticsSenderService> statsService;
if (statsService.isAvailable()) {
statsService->setSize(storage_->size());
}

that I guess gets called for every ROOT file opened in CMSSW (so also those opened for writing).

@makortel
Copy link
Contributor

makortel commented Sep 9, 2021

@nsmith- Could you reopen the issue?

@nsmith-
Copy link
Contributor Author

nsmith- commented Sep 9, 2021

I don't seem to have permission to do so

@makortel
Copy link
Contributor

makortel commented Sep 9, 2021

Ok :( Maybe because it was closed because of the linked PR being merged. @smuzaffar Could you reopen this issue?

@smuzaffar smuzaffar reopened this Sep 9, 2021
@smuzaffar
Copy link
Contributor

reopened now

@Dr15Jones
Copy link
Contributor

@nsmith- we need further feedback from you to understand what changes could be done to still work with your use case.

@nsmith-
Copy link
Contributor Author

nsmith- commented Sep 28, 2021

I'm a bit puzzled how it is all files, because empirically we never see any pileup files in our monitoring that receives these messages. Is it possibly related to the thread safety issues of the existing implementation?
For the sake of rucio popularity we really only need a record of each file use (i.e. one record per LFN per job), the single and vector read statistics would likely still be interesting for future analyses (actually they are summarized here but without much drilldown support)
Can you clarify a bit what you mean by 'aggregate' here?

@Dr15Jones
Copy link
Contributor

@nsmith-

I'm a bit puzzled how it is all files, because empirically we never see any pileup files in our monitoring that receives these messages. Is it possibly related to the thread safety issues of the existing implementation?

Although only 1 file name is reported, the statistics (e.g. bytes read) are actually the accumulated statistics for ALL ROOT files being used in the job.

@nsmith-
Copy link
Contributor Author

nsmith- commented Sep 28, 2021

And I assume reporting the isolated statistics per file is more challenging?

@Dr15Jones
Copy link
Contributor

And I assume reporting the isolated statistics per file is more challenging?

It would be a near complete rewrite since it is full of singletons/global variables to do the accounting.

@Dr15Jones
Copy link
Contributor

As a historical note, the code in question predates CMSSW and was taken from CERN's original 'SEAL' project which was trying to write a C++ toolkit.

@makortel
Copy link
Contributor

And I assume reporting the isolated statistics per file is more challenging?

It would be a near complete rewrite since it is full of singletons/global variables to do the accounting.

Let me add that while a "near complete rewrite" of the StatisticsSenderService would be straightforward to backport to production release cycles, I'm really hesitant for backports of "near complete rewrite" of the storage codebase (even if it is archaic).

@Dr15Jones
Copy link
Contributor

I think part of the problem is a misinterpretation of the sent information. The info is not a 'per file' message, it is instead a snapshot of the accumulated state of the job at that instant in time. For the UDP message, that state is an arbitrary time. For the statistic sender service it is when the primary file was closed.

It seems now the request is to also send information when secondary/embedded files are closed. That could still send the present 'full job statistics summary' information along.

@nsmith-
Copy link
Contributor Author

nsmith- commented Sep 28, 2021

I see, I didn't realize it was an accumulated statistic over the duration of the job. I guess since there is a unique_id field one can track job progress from these and only analyze the last such record received to not double-count in any analysis of these statistics. In this case, it should be fine to just send messages more often, i.e. when any secondary/embedded file is closed. For file popularity of course these byte statistics do not really matter.

@Dr15Jones
Copy link
Contributor

@bbockelm what was your intent when you added the CondorStatusService and StatisticsSenderService?

@Dr15Jones
Copy link
Contributor

So it looks like the StatisticsSenderService has three pieces of information that would need to be handled differently if we report more than just the primary file. These are file_lfn , server_host , and server_domain .

It seems like we already have a problem. Right now the XrdAdaptor::RequestManager appears to change the server_* information when ever ANY file changes its server. So right now the reports have the lfn to the primary file but might be reporting the server_* for the secondary/embedded file that last changed servers.

@makortel
Copy link
Contributor

makortel commented Oct 1, 2021

@nsmith- #35505 makes the secondary and embedded file closures to cause and UDP packet to be sent. The statistics are reset only on primary file closures (like currently). Can you comment if this is ok for the downstream that interprets the statistics? (the packet has timestamps for the beginning and end of the statistics collection period)

@nsmith-
Copy link
Contributor Author

nsmith- commented Oct 4, 2021

Is there a marker to tell whether the current file is a primary file in the packet? If that's the case then at least it is possible to reconstruct the correct statistics, if I understand correctly.

@Dr15Jones
Copy link
Contributor

Is there a marker to tell whether the current file is a primary file in the packet?

I left the packet info exactly as it had been so as to not cause any problems with code reading those packets. Though I'd think it would be pretty easy to differentiate primary from pileup given pileup LNFs tend to have 'MinimumBias' in their name.

If you want something else done, please let us know. This information is not used in anyway by the framework so you can basically say what you want.

@nsmith-
Copy link
Contributor Author

nsmith- commented Oct 4, 2021

For pileup I agree, but if we also now catch secondary inputs (which, granted, do not ever get used in production jobs.. at least not yet) then it may be more difficult. It should be harmless to add a new field to the json, but I'll ping @vkuznet to confirm, since iirc he wrote the server daemon that parses these packets and injects them into the MONIT infrastructure.

@Dr15Jones
Copy link
Contributor

@nsmith- @vkuznet we are still waiting for a response about our questions.

@vkuznet
Copy link
Contributor

vkuznet commented Oct 11, 2021

@nsmith- , yes, the new UDP server I wrote just reads incoming UDP packets, these packets contain JSON, and if JSON has invalid data or data-type the server drops it, and therefore we loose this information in our accounting. Each valid JSON is injected into MONIT infrastructure, while all invalid JSON are dropped.

@Dr15Jones
Copy link
Contributor

@vkuznet the question is, do you need to keep the same content of the JSON, or can it be modified (.e.g. adding info about if this is the primary file)?

@vkuznet
Copy link
Contributor

vkuznet commented Oct 11, 2021

Since JSON is fed into MONIT infrastructure it is desired to have the same schema. But since we push data into ElasticSearch DB which is schemaless it is possible to change the schema. I suggest that we discuss and settle on a schema of the document. For clarity, here is current schema (I took a single document from ES):

{
      "site_name": "T2_ES_CIEMAT",
      "user_dn": "/DC=ch/DC=cern/OU=Organic Units/OU=Users/CN=amaltaro/CN=718748/CN=Alan Malta Rodrigues/CN=1623138246/CN=1922216409/CN=2104111278/CN=1595834568",
      "client_host": "gaew0199",
      "client_domain": "ciemat.es",
      "server_host": "gaeds014",
      "server_domain": "ciemat.es",
      "unique_id": "78537596-5E7E-0C42-8DAE-B041909DE5D4-0",
      "file_lfn": "/store/mc/RunIISummer20UL17MiniAOD/ST_t-channel_antitop_4f_hdampup_InclusiveDecays_TuneCP5_13TeV-powheg-madspin-pythia8/MINIAODSIM/106X_mc2017_realistic_v6-v3/270000/5CC220C2-111D-7144-A91F-4A3EAFAE5FF4.root",
      "file_size": 6502578,
      "read_single_sigma": 19570.1,
      "read_single_average": 1917.9,
      "read_vector_average": 17335800,
      "read_vector_sigma": 15408700,
      "read_vector_count_average": 16.5444,
      "read_vector_count_sigma": 18.5605,
      "read_bytes": 1569091504,
      "read_bytes_at_close": 1569091504,
      "read_single_operations": 4625,
      "read_single_bytes": 8870294,
      "read_vector_operations": 90,
      "read_vector_bytes": 1560221210,
      "start_time": 1633969170,
      "end_time": 1633971565
    }

If you'll add new key-value pairs it would be easier to accommodate them in ES and monitoring infrastructure (in MONIT dashboards), but if you'll change data-types or drop attributes this will lead to conflicts which should be resolved. And, we advise to keep flat JSON, i.e. keep only key-value pairs, since it simplify indexing and visualization queries.

@nsmith-
Copy link
Contributor Author

nsmith- commented Oct 13, 2021

In this case we just propose to add a new key is_primary: bool (or whatever name sounds good) to the record. While on the subject, one thing we've noticed is the field fallback is either True or not present (null). Would be nice to populate the record with false when fallback is not used to open the file.

@vkuznet
Copy link
Contributor

vkuznet commented Oct 13, 2021

the most important thing is that you should validate your JSON. We often see that people confuse python dicts with valid JSON, and even here we're discussing C++ code which generates JSON, it is possible to supply not valid data-type which may cause issues (a typical error we saw many times, a number (int/float) is supplied as a string in JSON). Said that, if you define an attribute with some data-type you should ensure that generated JSON is fully compatible with that data-type.

@Dr15Jones
Copy link
Contributor

@nsmith- from the code change I'm making, it is actually easy to say if this is a primary file, a 'secondary' file (I.e. the parent file when using the two file solution) or if this is from a 'secondary source' (i.e. from a pileup file or some other module usign the EmbeddedSource objects). Do you still only want is_primary: bool or would you want something more inclusive like file_usage: string with specified names , e.g. primary, secondary, embedded?

@nsmith-
Copy link
Contributor Author

nsmith- commented Oct 18, 2021

Specified names sound even better!

@nsmith-
Copy link
Contributor Author

nsmith- commented Oct 18, 2021

One question, so if I understand the read_bytes and related fields are only an accumulator for the entire job and get reset each time a new primary file is opened? What is read_bytes_at_close for?

@Dr15Jones
Copy link
Contributor

One question, so if I understand the read_bytes and related fields are only an accumulator for the entire job and get reset each time a new primary file is opened? What is read_bytes_at_close for?

I don't know. This was not code written by the framework team. We just 'inheritted' it. From the implementation

os << "\"read_bytes\":" << (read_vector_bytes + read_single_bytes - m_read_vector_bytes - m_read_single_bytes)
<< ", ";
os << "\"read_bytes_at_close\":"
<< (read_vector_bytes + read_single_bytes - m_read_vector_bytes - m_read_single_bytes) << ", ";

read_bytes and read_bytes_at_close are identical. Going all the way back to the very first commit of that file by Brian, those two values have always been identical.

@vkuznet
Copy link
Contributor

vkuznet commented Oct 20, 2021

@nsmith- I double checked with MONIT team and there would be no problem if we'll add additional attributes to the existing schema. Therefore, you may add as many as you want. and I checked udp collector server, and it is transparent to the JSON itself, i.e. it does not care about its content. Therefore, I would assume that once you'll add one or more attributes they will simply pop-up in ES and we will only need to adjust our dashboards to use them as filters or attributes for any plots.

@nsmith-
Copy link
Contributor Author

nsmith- commented Oct 21, 2021

Thanks Valentin, this is great news! In fact I think this gives us licence to completely redesign the reporting if we so choose (and perhaps continue to send the existing data, just add a new packet with modified data)
Chris, given what you were saying about global variables and when things are updated, do you think server_domain is trustworthy for the current records? Also in view of our multi-source algorithm, is it likely the server domain is only one of many?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants