Revision 06810b29

View differences:

configure
377 377
  # SunOS, and we haven't implemented it.)
378 378
  if sys.platform.startswith('sunos'):
379 379
    o['variables']['node_use_dtrace'] = b(not options.without_dtrace)
380
  elif sys.platform.startswith('linux'):
381
    o['variables']['node_use_dtrace'] = 'false'
382
    o['variables']['node_use_systemtap'] = b(not options.without_dtrace)
380 383
  elif b(options.with_dtrace) == 'true':
381
    raise Exception('DTrace is currently only supported on SunOS systems.')
384
    raise Exception(
385
       'DTrace is currently only supported on SunOS or Linux systems.')
382 386
  else:
383 387
    o['variables']['node_use_dtrace'] = 'false'
384 388

  
node.gyp
9 9
    'node_shared_v8%': 'false',
10 10
    'node_shared_zlib%': 'false',
11 11
    'node_use_openssl%': 'true',
12
    'node_use_systemtap%': 'false',
12 13
    'node_shared_openssl%': 'false',
13 14
    'library_files': [
14 15
      'src/node.js',
......
146 147
        }, {
147 148
          'defines': [ 'HAVE_OPENSSL=0' ]
148 149
        }],
149

  
150 150
        [ 'node_use_dtrace=="true"', {
151 151
          'defines': [ 'HAVE_DTRACE=1' ],
152 152
          'dependencies': [ 'node_dtrace_header' ],
......
168 168
            }
169 169
          ] ],
170 170
        } ],
171
        [ 'node_use_systemtap=="true"', {
172
          'defines': [ 'HAVE_SYSTEMTAP=1', 'STAP_SDT_V1=1' ],
173
          'dependencies': [ 'node_systemtap_header' ],
174
          'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)' ],
175
          'sources': [
176
            'src/node_dtrace.cc',
177
            '<(SHARED_INTERMEDIATE_DIR)/node_systemtap.h',
178
          ],
179
        } ],
171 180
        [ 'node_use_etw=="true"', {
172 181
          'defines': [ 'HAVE_ETW=1' ],
173 182
          'dependencies': [ 'node_etw' ],
......
285 294
          # action?
286 295

  
287 296
          'conditions': [
288
            [ 'node_use_dtrace=="true" or node_use_etw=="true"', {
297
            [ 'node_use_dtrace=="true"'
298
              ' or node_use_etw=="true"'
299
              ' or node_use_systemtap=="true"',
300
            {
289 301
              'action': [
290 302
                'python',
291 303
                'tools/js2c.py',
......
323 335
      ]
324 336
    },
325 337
    {
338
      'target_name': 'node_systemtap_header',
339
      'type': 'none',
340
      'conditions': [
341
        [ 'node_use_systemtap=="true"', {
342
          'actions': [
343
            {
344
              'action_name': 'node_systemtap_header',
345
              'inputs': [ 'src/node_systemtap.d' ],
346
              'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/node_systemtap.h' ],
347
              'action': [ 'dtrace', '-h', '-C', '-s', '<@(_inputs)',
348
                '-o', '<@(_outputs)' ]
349
            }
350
          ]
351
        } ]
352
      ]
353
    },
354
    {
326 355
      'target_name': 'node_dtrace_provider',
327 356
      'type': 'none',
328 357
      'conditions': [
src/node.cc
27 27
#include "uv.h"
28 28

  
29 29
#include "v8-debug.h"
30
#if defined HAVE_DTRACE || defined HAVE_ETW
30
#if defined HAVE_DTRACE || defined HAVE_ETW || defined HAVE_SYSTEMTAP
31 31
# include "node_dtrace.h"
32 32
#endif
33 33

  
......
72 72
#if HAVE_OPENSSL
73 73
# include "node_crypto.h"
74 74
#endif
75
#if HAVE_SYSTEMTAP
76
#include "node_systemtap.h"
77
#endif
75 78
#include "node_script.h"
76 79
#include "v8_typed_array.h"
77 80

  
......
2307 2310
  Local<Object> global = v8::Context::GetCurrent()->Global();
2308 2311
  Local<Value> args[1] = { Local<Value>::New(process_l) };
2309 2312

  
2310
#if defined HAVE_DTRACE || defined HAVE_ETW
2313
#if defined HAVE_DTRACE || defined HAVE_ETW || defined HAVE_SYSTEMTAP
2311 2314
  InitDTrace(global);
2312 2315
#endif
2313 2316

  
src/node_dtrace.cc
19 19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21 21

  
22
#include "node_dtrace.h"
23
#include <string.h>
24 22

  
25 23
#ifdef HAVE_DTRACE
24
#include "node_dtrace.h"
25
#include <string.h>
26 26
#include "node_provider.h"
27 27
#elif HAVE_ETW
28
#include "node_dtrace.h"
29
#include <string.h>
28 30
#include "node_win32_etw_provider.h"
29 31
#include "node_win32_etw_provider-inl.h"
32
#elif HAVE_SYSTEMTAP
33
#include <string.h>
34
#include <node.h>
35
#include <v8.h>
36
#include <sys/sdt.h>
37
#include "node_systemtap.h"
38
#include "node_dtrace.h"
30 39
#else
31 40
#define NODE_HTTP_SERVER_REQUEST(arg0, arg1)
32 41
#define NODE_HTTP_SERVER_REQUEST_ENABLED() (0)
......
118 127

  
119 128

  
120 129
Handle<Value> DTRACE_NET_SERVER_CONNECTION(const Arguments& args) {
130
#ifndef HAVE_SYSTEMTAP
121 131
  if (!NODE_NET_SERVER_CONNECTION_ENABLED())
122 132
    return Undefined();
133
#endif
123 134

  
124 135
  HandleScope scope;
125 136

  
126 137
  SLURP_CONNECTION(args[0], conn);
138
#ifdef HAVE_SYSTEMTAP
139
  NODE_NET_SERVER_CONNECTION(conn.fd, conn.remote, conn.port, \
140
                             conn.buffered);
141
#else
127 142
  NODE_NET_SERVER_CONNECTION(&conn);
143
#endif
128 144

  
129 145
  return Undefined();
130 146
}
131 147

  
132 148
Handle<Value> DTRACE_NET_STREAM_END(const Arguments& args) {
149
#ifndef HAVE_SYSTEMTAP
133 150
  if (!NODE_NET_STREAM_END_ENABLED())
134 151
    return Undefined();
152
#endif
135 153

  
136 154
  HandleScope scope;
137 155

  
138 156
  SLURP_CONNECTION(args[0], conn);
157
#ifdef HAVE_SYSTEMTAP
158
  NODE_NET_STREAM_END(conn.fd, conn.remote, conn.port, conn.buffered);
159
#else
139 160
  NODE_NET_STREAM_END(&conn);
161
#endif
140 162

  
141 163
  return Undefined();
142 164
}
143 165

  
144 166
Handle<Value> DTRACE_NET_SOCKET_READ(const Arguments& args) {
167
#ifndef HAVE_SYSTEMTAP
145 168
  if (!NODE_NET_SOCKET_READ_ENABLED())
146 169
    return Undefined();
170
#endif
147 171

  
148 172
  HandleScope scope;
149
  int nbytes;
150 173

  
151 174
  SLURP_CONNECTION(args[0], conn);
152 175

  
176
#ifdef HAVE_SYSTEMTAP
177
  NODE_NET_SOCKET_READ(conn.fd, conn.remote, conn.port, conn.buffered);
178
#else
153 179
  if (!args[1]->IsNumber()) {
154 180
    return (ThrowException(Exception::Error(String::New("expected " 
155 181
      "argument 1 to be number of bytes"))));
156 182
  }
157

  
158
  nbytes = args[1]->Int32Value();
159

  
183
  int nbytes = args[1]->Int32Value();
160 184
  NODE_NET_SOCKET_READ(&conn, nbytes);
185
#endif
161 186

  
162 187
  return Undefined();
163 188
}
164 189

  
165 190
Handle<Value> DTRACE_NET_SOCKET_WRITE(const Arguments& args) {
191
#ifndef HAVE_SYSTEMTAP
166 192
  if (!NODE_NET_SOCKET_WRITE_ENABLED())
167 193
    return Undefined();
194
#endif
168 195

  
169 196
  HandleScope scope;
170
  int nbytes;
171 197

  
172 198
  SLURP_CONNECTION(args[0], conn);
173 199

  
200
#ifdef HAVE_SYSTEMTAP
201
  NODE_NET_SOCKET_WRITE(conn.fd, conn.remote, conn.port, conn.buffered);
202
#else
174 203
  if (!args[1]->IsNumber()) {
175 204
    return (ThrowException(Exception::Error(String::New("expected " 
176 205
      "argument 1 to be number of bytes"))));
177 206
  }
178

  
179
  nbytes = args[1]->Int32Value();
180

  
207
  int nbytes = args[1]->Int32Value();
181 208
  NODE_NET_SOCKET_WRITE(&conn, nbytes);
209
#endif
182 210

  
183 211
  return Undefined();
184 212
}
......
186 214
Handle<Value> DTRACE_HTTP_SERVER_REQUEST(const Arguments& args) {
187 215
  node_dtrace_http_server_request_t req;
188 216

  
217
#ifndef HAVE_SYSTEMTAP
189 218
  if (!NODE_HTTP_SERVER_REQUEST_ENABLED())
190 219
    return Undefined();
220
#endif
191 221

  
192 222
  HandleScope scope;
193 223

  
......
213 243

  
214 244
  SLURP_CONNECTION(args[1], conn);
215 245

  
246
#ifdef HAVE_SYSTEMTAP
247
  NODE_HTTP_SERVER_REQUEST(&req, conn.fd, conn.remote, conn.port, \
248
                           conn.buffered);
249
#else
216 250
  NODE_HTTP_SERVER_REQUEST(&req, &conn);
251
#endif
217 252
  return Undefined();
218 253
}
219 254

  
220 255
Handle<Value> DTRACE_HTTP_SERVER_RESPONSE(const Arguments& args) {
256
#ifndef HAVE_SYSTEMTAP
221 257
  if (!NODE_HTTP_SERVER_RESPONSE_ENABLED())
222 258
    return Undefined();
259
#endif
223 260

  
224 261
  HandleScope scope;
225 262

  
226 263
  SLURP_CONNECTION(args[0], conn);
264
#ifdef HAVE_SYSTEMTAP
265
  NODE_HTTP_SERVER_RESPONSE(conn.fd, conn.remote, conn.port, conn.buffered);
266
#else
227 267
  NODE_HTTP_SERVER_RESPONSE(&conn);
268
#endif
228 269

  
229 270
  return Undefined();
230 271
}
......
233 274
  node_dtrace_http_client_request_t req;
234 275
  char *header;
235 276

  
277
#ifndef HAVE_SYSTEMTAP
236 278
  if (!NODE_HTTP_CLIENT_REQUEST_ENABLED())
237 279
    return Undefined();
280
#endif
238 281

  
239 282
  HandleScope scope;
240 283

  
......
263 306
  *header = '\0';
264 307

  
265 308
  SLURP_CONNECTION_HTTP_CLIENT(args[1], conn);
309
#ifdef HAVE_SYSTEMTAP
310
  NODE_HTTP_CLIENT_REQUEST(&req, conn.fd, conn.remote, conn.port, \
311
                           conn.buffered);
312
#else
266 313
  NODE_HTTP_CLIENT_REQUEST(&req, &conn);
314
#endif
267 315
  return Undefined();
268 316
}
269 317

  
270 318
Handle<Value> DTRACE_HTTP_CLIENT_RESPONSE(const Arguments& args) {
319
#ifndef HAVE_SYSTEMTAP
271 320
  if (!NODE_HTTP_CLIENT_RESPONSE_ENABLED())
272 321
    return Undefined();
273

  
322
#endif
274 323
  HandleScope scope;
275 324

  
276 325
  SLURP_CONNECTION_HTTP_CLIENT_RESPONSE(args[0], args[1], conn);
326
#ifdef HAVE_SYSTEMTAP
327
  NODE_HTTP_CLIENT_RESPONSE(conn.fd, conn.remote, conn.port, conn.buffered);
328
#else
277 329
  NODE_HTTP_CLIENT_RESPONSE(&conn);
330
#endif
278 331

  
279 332
  return Undefined();
280 333
}
281 334

  
282
#define NODE_PROBE(name) #name, name
335
#define NODE_PROBE(name) #name, name, Persistent<FunctionTemplate>()
283 336

  
284 337
static int dtrace_gc_start(GCType type, GCCallbackFlags flags) {
338
#ifdef HAVE_SYSTEMTAP
339
  NODE_GC_START();
340
#else
285 341
  NODE_GC_START(type, flags);
342
#endif
286 343
  /*
287 344
   * We avoid the tail-call elimination of the USDT probe (which screws up
288 345
   * args) by forcing a return of 0.
......
291 348
}
292 349

  
293 350
static int dtrace_gc_done(GCType type, GCCallbackFlags flags) {
351
#ifdef HAVE_SYSTEMTAP
352
  NODE_GC_DONE();
353
#else
294 354
  NODE_GC_DONE(type, flags);
355
#endif
295 356
  return 0;
296 357
}
297 358

  
......
308 369
    { NODE_PROBE(DTRACE_HTTP_SERVER_REQUEST) },
309 370
    { NODE_PROBE(DTRACE_HTTP_SERVER_RESPONSE) },
310 371
    { NODE_PROBE(DTRACE_HTTP_CLIENT_REQUEST) },
311
    { NODE_PROBE(DTRACE_HTTP_CLIENT_RESPONSE) },
312
    { NULL }
372
    { NODE_PROBE(DTRACE_HTTP_CLIENT_RESPONSE) }
313 373
  };
314 374

  
315
  for (int i = 0; tab[i].name != NULL; i++) {
375
  for (unsigned int i = 0; i < ARRAY_SIZE(tab); i++) {
316 376
    tab[i].templ = Persistent<FunctionTemplate>::New(
317 377
        FunctionTemplate::New(tab[i].func));
318 378
    target->Set(String::NewSymbol(tab[i].name), tab[i].templ->GetFunction());
......
322 382
  init_etw();
323 383
#endif
324 384

  
325
#if defined HAVE_DTRACE || defined HAVE_ETW
385
#if defined HAVE_DTRACE || defined HAVE_ETW || defined HAVE_SYSTEMTAP
326 386
  v8::V8::AddGCPrologueCallback((GCPrologueCallback)dtrace_gc_start);
327 387
  v8::V8::AddGCEpilogueCallback((GCEpilogueCallback)dtrace_gc_done);
328 388
#endif
src/node_systemtap.d
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21

  
22
// Hints:
23
// This .d defines compiled in probes
24
//     probes are handles (untyped pointers)
25
//     v8 forward declared objs (dtrace_connection_t) are defined
26
//     in node_dtrace.cc which builds an InitDtrace object which
27
//     gets populated with the probes
28
//     The probes gather the following:
29
//     PROBE_REQUEST(req, fd, remote, port, buffered)
30
//     PROBE_OTHER(fd, remote, port, buffered)
31
// other notes:
32
//     using any PROBE_ENABLED() macros in dtrace.cc sdt broke it
33
//     can only pass strings/ints/primitives not dtrace_connection_t
34
//          conn or other structs
35
//     verify probe existence by using
36
//          $ stap -l 'process("out/Release/node").mark("*")'
37
// TODO: write .stp scripts (node.stp, node_v8ustack.stp + ???)
38

  
39

  
40
provider node {
41
    probe http__client__request(string, int, string, int, int);
42
    probe http__client__response(int, string, int, int);
43
    probe http__server__request(string, int, string, int, int);
44
    probe http__server__response(int, string, int, int);
45
    probe net__server__connection(int, string, int, int);
46
    probe net__socket__read(int, string, int, int);
47
    probe net__socket__write(int, string, int, int);
48
    probe net__stream__end(int, string, int, int);
49
    probe gc__done();
50
    probe gc__start();
51
};

Also available in: Unified diff