2 +----------------------------------------------------------------------+
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 +----------------------------------------------------------------------+
17 // We can't do this on MSVC, it's all debug or all release.
20 * Forcibly define USE_TRACE, so we get the debug trace.h interface included
21 * here. This allows mixed compilation, where some units were compiled
22 * DEBUG and others compiled RELEASE, to successfully link.
28 #include "hphp/util/trace.h"
37 #include <folly/portability/PThread.h>
39 #include "hphp/util/ringbuffer.h"
43 TRACE_SET_MOD(tprefix
);
47 int levels
[NumModules
];
48 __thread
int tl_levels
[NumModules
];
49 __thread
int indentDepth
= 0;
51 static FILE* out
{nullptr};
53 static const char *tokNames
[] = {
61 const char* kPIDPlaceholder
= "%{pid}";
64 * Dummy class to get some code to run before main().
68 static Module
name2mod(folly::StringPiece name
) {
69 for (int i
= 0; i
< NumModules
; i
++) {
70 if (name
== tokNames
[i
]) {
79 /* Parse the environment for flags. */
80 const char *envName
= "TRACE";
81 const char *env
= getenv(envName
);
83 EnsureInitFile(getenv("HPHP_TRACE_FILE"));
84 InitFromSpec(env
, levels
);
86 // If TRACE env var is not set, nothing should be traced...
87 // but if it does, use stderr.
92 static void EnsureInitFile(const char* file
) {
93 if (out
&& out
!= stderr
) return;
95 auto const filename
= [&] () -> std::string
{
96 if (!file
) return "/tmp/hphp.log";
97 std::string result
{file
};
99 if ((idx
= result
.find(kPIDPlaceholder
)) != std::string::npos
) {
100 result
.replace(idx
, strlen(kPIDPlaceholder
), std::to_string(getpid()));
105 out
= fopen(filename
.c_str(),
106 getenv("HPHP_TRACE_APPEND") ? "a" : "w");
110 "could not create log file (%s); using stderr\n",
117 static void InitFromSpec(folly::StringPiece spec
, int* levels
) {
118 std::vector
<folly::StringPiece
> pieces
;
119 folly::split(",", spec
, pieces
);
120 for (auto piece
: pieces
) {
121 folly::StringPiece moduleName
;
124 if (!folly::split(":", piece
, moduleName
, level
)) {
128 } catch (const std::exception
& re
) {
130 folly::format("Ignoring invalid TRACE component: {}\n", piece
);
134 int mod
= name2mod(moduleName
);
135 if (mod
>= 0) levels
[mod
] = level
;
137 static auto const groups
= {
143 for (auto g
: groups
) {
145 levels
[Trace::statgroups
] = std::max(levels
[Trace::statgroups
], 1);
157 const char* moduleName(Module mod
) {
158 return tokNames
[mod
];
162 if (!moduleEnabledRelease(Trace::traceAsync
)) {
168 void ensureInit(std::string outFile
) {
169 Init::EnsureInitFile(outFile
.c_str());
172 void setTraceThread(folly::StringPiece traceSpec
) {
173 for (auto& level
: tl_levels
) level
= 0;
174 Init::InitFromSpec(traceSpec
, tl_levels
);
177 CompactVector
<BumpRelease
> bumpSpec(folly::StringPiece traceSpec
) {
178 std::array
<int, NumModules
> modules
{};
180 Init::InitFromSpec(traceSpec
, modules
.data());
181 CompactVector
<BumpRelease
> result
;
182 for (int i
= 0; i
< NumModules
; i
++) {
184 result
.emplace_back(static_cast<Module
>(i
), -modules
[i
]);
190 void vtrace(const char *fmt
, va_list ap
) {
191 static pthread_mutex_t mtx
= PTHREAD_MUTEX_INITIALIZER
;
192 static bool hphp_trace_ringbuffer
= getenv("HPHP_TRACE_RINGBUFFER");
193 if (hphp_trace_ringbuffer
) {
194 vtraceRingbuffer(fmt
, ap
);
196 ONTRACE(1, pthread_mutex_lock(&mtx
));
197 ONTRACE(1, fprintf(out
, "t%#08x: ",
198 int((int64_t)pthread_self() & 0xFFFFFFFF)));
199 vfprintf(out
, fmt
, ap
);
200 ONTRACE(1, pthread_mutex_unlock(&mtx
));
205 void trace(const char *fmt
, ...) {
213 void traceRelease(const char* fmt
, ...) {
220 void traceRingBufferRelease(const char *fmt
, ...) {
223 vtraceRingbuffer(fmt
, ap
);
228 void trace(const std::string
& s
) {
229 trace("%s", s
.c_str());
233 void traceRelease(const std::string
& s
) {
234 traceRelease("%s", s
.c_str());
238 std::string
prettyNode(const char* name
, const std::string
& s
) {
240 return string("(") + string(name
) + string(" ") +