Skip to content

Commit 29648cd

Browse files
edwinsmithfacebook-github-bot
authored andcommitted
event logging for various interesting things in ext_facts
Summary: I want to start collecting telemetry on all the weird corner cases and failure modes that can happen with Facts. This is a start. Rare events bypass PerfSampleRate when it's nonzero but still skip logging when it is zero. Refactored more of the hhvm_sandbox_events logging code to a central location runtime/base/sandbox-events.{cpp,h} since we need to call it from outside FactsLogger. Reviewed By: nt591 Differential Revision: D52580966 fbshipit-source-id: 941187d990a0eb4071045d31378fe64f93e2fb8f
1 parent 67bbae3 commit 29648cd

File tree

7 files changed

+141
-30
lines changed

7 files changed

+141
-30
lines changed

hphp/runtime/base/autoload-handler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "hphp/runtime/base/container-functions.h"
2929
#include "hphp/runtime/base/runtime-option.h"
3030
#include "hphp/runtime/base/repo-autoload-map.h"
31+
#include "hphp/runtime/base/sandbox-events.h"
3132
#include "hphp/runtime/base/unit-cache.h"
3233
#include "hphp/runtime/vm/repo-global-data.h"
3334
#include "hphp/runtime/vm/unit.h"
@@ -89,6 +90,9 @@ FactsStore* getFactsForRequest() {
8990
return map;
9091
} catch (const std::exception& e) {
9192
auto repoRoot = repoOptions->dir();
93+
rareSboxEvent("autoload-handler",
94+
folly::sformat("getFactsForRequest: {}", e.what()),
95+
repoRoot.native());
9296
Logger::FError(
9397
"Failed to update native autoloader, not natively autoloading {}. {}\n",
9498
repoRoot.native(),

hphp/runtime/base/sandbox-events.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| HipHop for PHP |
4+
+----------------------------------------------------------------------+
5+
| Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6+
+----------------------------------------------------------------------+
7+
| This source file is subject to version 3.01 of the PHP license, |
8+
| that is bundled with this package in the file LICENSE, and is |
9+
| available through the world-wide-web at the following url: |
10+
| http://www.php.net/license/3_01.txt |
11+
| If you did not receive a copy of the PHP license and are unable to |
12+
| obtain it through the world-wide-web, please send a note to |
13+
| license@php.net so we can mail you a copy immediately. |
14+
+----------------------------------------------------------------------+
15+
*/
16+
#include "hphp/runtime/base/sandbox-events.h"
17+
#include "hphp/runtime/base/runtime-option.h"
18+
19+
namespace HPHP {
20+
21+
void logSboxEvent(uint32_t sample_rate, std::string_view source,
22+
std::string_view event, std::string_view key, uint64_t duration_us) {
23+
if (!getenv("INSIDE_RE_WORKER")) {
24+
StructuredLogEntry ent;
25+
ent.force_init = true;
26+
ent.setProcessUuid("hhvm_uuid");
27+
ent.setInt("sample_rate", sample_rate);
28+
ent.setStr("source", source);
29+
ent.setStr("event", event);
30+
ent.setStr("key", key);
31+
ent.setInt("duration_us", duration_us);
32+
StructuredLog::log("hhvm_sandbox_events", ent);
33+
}
34+
}
35+
36+
void rareSboxEvent(std::string_view source, std::string_view event,
37+
std::string_view key) {
38+
if (RuntimeOption::AutoloadPerfSampleRate != 0) {
39+
logSboxEvent(1, source, event, key, 0);
40+
}
41+
}
42+
43+
}

hphp/runtime/base/sandbox-events.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| HipHop for PHP |
4+
+----------------------------------------------------------------------+
5+
| Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6+
+----------------------------------------------------------------------+
7+
| This source file is subject to version 3.01 of the PHP license, |
8+
| that is bundled with this package in the file LICENSE, and is |
9+
| available through the world-wide-web at the following url: |
10+
| http://www.php.net/license/3_01.txt |
11+
| If you did not receive a copy of the PHP license and are unable to |
12+
| obtain it through the world-wide-web, please send a note to |
13+
| license@php.net so we can mail you a copy immediately. |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#pragma once
18+
#include <chrono>
19+
#include <string_view>
20+
#include "hphp/util/struct-log.h"
21+
22+
namespace HPHP {
23+
24+
void logSboxEvent(uint32_t sampleRate, std::string_view source,
25+
std::string_view event, std::string_view key,
26+
uint64_t duration_us);
27+
28+
void rareSboxEvent(std::string_view source, std::string_view event,
29+
std::string_view key);
30+
31+
template <typename F>
32+
auto timeSboxEvent(
33+
uint32_t sampleRate, std::string_view source,
34+
std::string_view event, std::string_view key, F&& func) {
35+
using namespace std::chrono_literals;
36+
auto t0 = std::chrono::steady_clock::now();
37+
SCOPE_EXIT {
38+
if (StructuredLog::coinflip(sampleRate)) {
39+
auto tf = std::chrono::steady_clock::now();
40+
auto elapsed =
41+
std::chrono::duration<double, std::chrono::microseconds::period>{
42+
tf - t0};
43+
logSboxEvent(sampleRate, source, event, key, elapsed.count());
44+
}
45+
};
46+
return func();
47+
}
48+
49+
}

hphp/runtime/ext/facts/ext_facts.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
#include "hphp/runtime/base/autoload-map.h"
4141
#include "hphp/runtime/base/builtin-functions.h"
4242
#include "hphp/runtime/base/config.h"
43-
#include "hphp/runtime/base/init-fini-node.h"
43+
#include "hphp/runtime/base/sandbox-events.h"
4444
#include "hphp/runtime/base/static-string-table.h"
4545
#include "hphp/runtime/base/string-data.h"
4646
#include "hphp/runtime/base/tv-type.h"
@@ -391,6 +391,7 @@ FactsStore* SqliteAutoloadMapFactory::getForOptions(
391391
return {std::move(mk)};
392392
} catch (const RepoOptionsParseExc& e) {
393393
XLOG(ERR) << e.what();
394+
rareSboxEvent("ext_facts", "RepoOptionsParseExc", e.what());
394395
return std::nullopt;
395396
}
396397
}();
@@ -421,6 +422,8 @@ FactsStore* SqliteAutoloadMapFactory::getForOptions(
421422
};
422423

423424
if (mapKey->m_dbKey.m_mode == SQLite::OpenMode::ReadOnly) {
425+
rareSboxEvent(
426+
"ext_facts", "getForOptions opening trusted store", mapKey->toString());
424427
XLOGF(
425428
DBG0,
426429
"Loading {} from trusted Autoload DB at {}",
@@ -445,6 +448,8 @@ FactsStore* SqliteAutoloadMapFactory::getForOptions(
445448
// Prefetch a FactsDB if we don't have one, while guarded by m_mutex
446449
prefetchDb(mapKey->m_root, mapKey->m_dbKey);
447450

451+
rareSboxEvent(
452+
"ext_facts", "getForOptions opening mutable store", mapKey->toString());
448453
return m_stores
449454
.insert(
450455
{*mapKey,
@@ -480,8 +485,11 @@ void SqliteAutoloadMapFactory::garbageCollectUnusedAutoloadMaps(
480485
XLOG(INFO) << "Evicting SqliteAutoloadMap: " << mapKey.toString();
481486
auto it = m_stores.find(mapKey);
482487
if (it != m_stores.end()) {
488+
rareSboxEvent("ext_facts", __func__, mapKey.toString());
483489
maps.push_back(std::move(it->second));
484490
m_stores.erase(it);
491+
} else {
492+
rareSboxEvent("ext_facts", "evict unknown mapkey", mapKey.toString());
485493
}
486494
m_lastUsed.erase(mapKey);
487495
}
@@ -579,6 +587,7 @@ Variant HHVM_FUNCTION(facts_db_path, const String& rootStr) {
579587
}();
580588
if (!root) {
581589
XLOG(ERR) << "Error resolving " << rootStr.slice();
590+
rareSboxEvent("ext_facts", "facts_db_path bad root", rootStr.slice());
582591
return Variant{Variant::NullInit{}};
583592
}
584593
assertx(root->is_absolute());
@@ -591,6 +600,10 @@ Variant HHVM_FUNCTION(facts_db_path, const String& rootStr) {
591600
return Variant{
592601
Facts::SqliteAutoloadMapKey::get(repoOptions).m_dbKey.m_path.native()};
593602
} catch (const Facts::RepoOptionsParseExc& e) {
603+
rareSboxEvent(
604+
"ext_facts",
605+
folly::sformat("facts_db_path {}", rootStr.slice()),
606+
e.what());
594607
throw_invalid_operation_exception(makeStaticString(e.what()));
595608
}
596609
}

hphp/runtime/ext/facts/facts-store.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "hphp/runtime/base/array-init.h"
3434
#include "hphp/runtime/base/array-iterator.h"
3535
#include "hphp/runtime/base/request-injection-data.h"
36+
#include "hphp/runtime/base/sandbox-events.h"
3637
#include "hphp/runtime/base/type-array.h"
3738
#include "hphp/runtime/base/type-string.h"
3839
#include "hphp/runtime/base/type-variant.h"
@@ -713,9 +714,15 @@ struct FactsStoreImpl final
713714
delta.m_files.size());
714715
auto sharedThis = weakThis.lock();
715716
if (!sharedThis) {
717+
rareSboxEvent("facts-store", "subscribe weakThis==null", "");
716718
return;
717719
}
718-
sharedThis->update();
720+
timeSboxEvent(
721+
RO::AutoloadPerfSampleRate,
722+
"facts-store",
723+
"subscribe update",
724+
"",
725+
[&] { sharedThis->update(); });
719726
});
720727
}
721728

@@ -743,6 +750,8 @@ struct FactsStoreImpl final
743750
INFO,
744751
"Suppression file found at {}, not updating native Facts.",
745752
suppressionFilePath.native());
753+
rareSboxEvent(
754+
"facts-store", "update supressed", suppressionFilePath.native());
746755
return {};
747756
}
748757
}
@@ -774,6 +783,7 @@ struct FactsStoreImpl final
774783
"Exception while querying watcher: {}",
775784
delta.exception().what());
776785
XLOG(ERR) << msg;
786+
rareSboxEvent("facts-store", "update watcher exception", msg);
777787
throw UpdateExc{msg};
778788
}
779789
return updateWithDelta(std::move(delta.value()));
@@ -788,8 +798,7 @@ struct FactsStoreImpl final
788798
auto lastWatchmanQueryStart = m_lastWatchmanQueryStart.load();
789799
if (UNLIKELY(lastWatchmanQueryStart < updateStart)) {
790800
auto currentTime = std::chrono::steady_clock::now();
791-
XLOGF(
792-
ERR,
801+
auto msg = folly::sformat(
793802
"Stale update. Last Watchman query was {}ms ago, but update was only {}ms ago.",
794803
std::chrono::duration_cast<
795804
std::chrono::duration<double, std::milli>>(
@@ -799,15 +808,25 @@ struct FactsStoreImpl final
799808
std::chrono::duration<double, std::milli>>(
800809
currentTime - updateStart)
801810
.count());
811+
XLOG(ERR, msg);
812+
rareSboxEvent("facts-store", msg, "");
802813
}
803814
assertx(updateStart < lastWatchmanQueryStart);
815+
auto queryMicros = std::chrono::duration_cast<std::chrono::duration<
816+
double,
817+
std::chrono::microseconds::period>>(
818+
lastWatchmanQueryStart - updateStart)
819+
.count();
820+
logSboxEvent(
821+
RO::AutoloadPerfSampleRate,
822+
"facts-store",
823+
"watchman query",
824+
m_root.native(),
825+
queryMicros);
804826
XLOGF(
805-
INFO,
827+
DBG0,
806828
"update waited {}ms for a Watchman query to return.",
807-
std::chrono::duration_cast<
808-
std::chrono::duration<double, std::milli>>(
809-
lastWatchmanQueryStart - updateStart)
810-
.count());
829+
queryMicros / 1000);
811830
return res;
812831
})
813832
.semi();

hphp/runtime/ext/facts/log-perf.cpp

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@
1515
*/
1616
#include "hphp/runtime/ext/facts/log-perf.h"
1717
#include <folly/logging/xlog.h>
18+
#include "hphp/runtime/base/autoload-map.h"
19+
#include "hphp/runtime/base/sandbox-events.h"
1820
#include "hphp/runtime/base/type-variant.h"
19-
#include "hphp/util/struct-log.h"
2021

2122
namespace HPHP::Facts {
2223

@@ -47,26 +48,8 @@ auto FactsLogger::logPerf(
4748
std::string_view method,
4849
std::string_view key,
4950
F&& func) const {
50-
using namespace std::chrono_literals;
51-
auto t0 = std::chrono::steady_clock::now();
52-
SCOPE_EXIT {
53-
if (StructuredLog::coinflip(m_sampleRate)) {
54-
auto tf = std::chrono::steady_clock::now();
55-
auto elapsed =
56-
std::chrono::duration<double, std::chrono::microseconds::period>{
57-
tf - t0};
58-
StructuredLogEntry ent;
59-
ent.force_init = true;
60-
ent.setProcessUuid("hhvm_uuid");
61-
ent.setInt("sample_rate", m_sampleRate);
62-
ent.setStr("source", m_impl);
63-
ent.setStr("event", method);
64-
ent.setStr("key", key);
65-
ent.setInt("duration_us", elapsed.count());
66-
StructuredLog::log("hhvm_sandbox_events", ent);
67-
}
68-
};
69-
return func();
51+
return timeSboxEvent(
52+
m_sampleRate, m_impl, method, key, std::forward<F>(func));
7053
}
7154

7255
void FactsLogger::ensureUpdated() {

hphp/test/slow/facts/facts.php.no_remote

Whitespace-only changes.

0 commit comments

Comments
 (0)