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
[] = {
62 * Dummy class to get some code to run before main().
66 static Module
name2mod(folly::StringPiece name
) {
67 for (int i
= 0; i
< NumModules
; i
++) {
68 if (name
== tokNames
[i
]) {
77 /* Parse the environment for flags. */
78 const char *envName
= "TRACE";
79 const char *env
= getenv(envName
);
81 EnsureInitFile(getenv("HPHP_TRACE_FILE"));
82 InitFromSpec(env
, levels
);
84 // If TRACE env var is not set, nothing should be traced...
85 // but if it does, use stderr.
90 static void EnsureInitFile(const char* file
) {
91 if (out
&& out
!= stderr
) return;
92 if (!file
) file
= "/tmp/hphp.log";
93 out
= fopen(file
, "w");
95 fprintf(stderr
, "could not create log file (%s); using stderr\n", file
);
100 static void InitFromSpec(std::string spec
, int* levels
) {
101 std::vector
<folly::StringPiece
> pieces
;
102 folly::split(",", spec
, pieces
);
103 for (auto piece
: pieces
) {
104 folly::StringPiece moduleName
;
107 if (!folly::split(":", piece
, moduleName
, level
)) {
111 } catch (const std::exception
& re
) {
113 folly::format("Ignoring invalid TRACE component: {}\n", piece
);
117 int mod
= name2mod(moduleName
);
118 if (mod
>= 0) levels
[mod
] = level
;
120 static auto const groups
= {
126 for (auto g
: groups
) {
128 levels
[Trace::statgroups
] = std::max(levels
[Trace::statgroups
], 1);
140 const char* moduleName(Module mod
) {
141 return tokNames
[mod
];
145 if (!moduleEnabledRelease(Trace::traceAsync
)) {
151 void ensureInit(std::string outFile
) {
152 Init::EnsureInitFile(outFile
.c_str());
155 void setTraceThread(const std::string
& traceSpec
) {
156 for (auto& level
: tl_levels
) level
= 0;
157 Init::InitFromSpec(traceSpec
, tl_levels
);
160 void vtrace(const char *fmt
, va_list ap
) {
161 static pthread_mutex_t mtx
= PTHREAD_MUTEX_INITIALIZER
;
162 static bool hphp_trace_ringbuffer
= getenv("HPHP_TRACE_RINGBUFFER");
163 if (hphp_trace_ringbuffer
) {
164 vtraceRingbuffer(fmt
, ap
);
166 ONTRACE(1, pthread_mutex_lock(&mtx
));
167 ONTRACE(1, fprintf(out
, "t%#08x: ",
168 int((int64_t)pthread_self() & 0xFFFFFFFF)));
169 vfprintf(out
, fmt
, ap
);
170 ONTRACE(1, pthread_mutex_unlock(&mtx
));
175 void trace(const char *fmt
, ...) {
183 void traceRelease(const char* fmt
, ...) {
190 void traceRingBufferRelease(const char *fmt
, ...) {
193 vtraceRingbuffer(fmt
, ap
);
198 void trace(const std::string
& s
) {
199 trace("%s", s
.c_str());
203 void traceRelease(const std::string
& s
) {
204 traceRelease("%s", s
.c_str());
208 std::string
prettyNode(const char* name
, const std::string
& s
) {
210 return string("(") + string(name
) + string(" ") +