// Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. #include "node_counters.h" #include "uv.h" #include namespace node { using namespace v8; static uint64_t counter_gc_start_time; static uint64_t counter_gc_end_time; #define SLURP_OBJECT(obj, member, valp) \ if (!(obj)->IsObject()) { \ return (ThrowException(Exception::Error(String::New("expected " \ "object for " #obj " to contain object member " #member)))); \ } \ *valp = Local::Cast(obj->Get(String::New(#member))); Handle COUNTER_NET_SERVER_CONNECTION(const Arguments& args) { NODE_COUNT_SERVER_CONN_OPEN(); return Undefined(); } Handle COUNTER_NET_SERVER_CONNECTION_CLOSE(const Arguments& args) { NODE_COUNT_SERVER_CONN_CLOSE(); return Undefined(); } Handle COUNTER_HTTP_SERVER_REQUEST(const Arguments& args) { NODE_COUNT_HTTP_SERVER_REQUEST(); return Undefined(); } Handle COUNTER_HTTP_SERVER_RESPONSE(const Arguments& args) { NODE_COUNT_HTTP_SERVER_RESPONSE(); return Undefined(); } Handle COUNTER_HTTP_CLIENT_REQUEST(const Arguments& args) { NODE_COUNT_HTTP_CLIENT_REQUEST(); return Undefined(); } Handle COUNTER_HTTP_CLIENT_RESPONSE(const Arguments& args) { NODE_COUNT_HTTP_CLIENT_RESPONSE(); return Undefined(); } static void counter_gc_start(GCType type, GCCallbackFlags flags) { counter_gc_start_time = NODE_COUNT_GET_GC_RAWTIME(); return; } static void counter_gc_done(GCType type, GCCallbackFlags flags) { uint64_t endgc = NODE_COUNT_GET_GC_RAWTIME(); if (endgc != 0) { uint64_t totalperiod = endgc - counter_gc_end_time; uint64_t gcperiod = endgc - counter_gc_start_time; if (totalperiod > 0) { unsigned int percent = static_cast((gcperiod * 100) / totalperiod); NODE_COUNT_GC_PERCENTTIME(percent); counter_gc_end_time = endgc; } } return; } #define NODE_PROBE(name) #name, name void InitPerfCounters(Handle target) { HandleScope scope; static struct { const char* name; Handle (*func)(const Arguments&); Persistent templ; } tab[] = { { NODE_PROBE(COUNTER_NET_SERVER_CONNECTION) }, { NODE_PROBE(COUNTER_NET_SERVER_CONNECTION_CLOSE) }, { NODE_PROBE(COUNTER_HTTP_SERVER_REQUEST) }, { NODE_PROBE(COUNTER_HTTP_SERVER_RESPONSE) }, { NODE_PROBE(COUNTER_HTTP_CLIENT_REQUEST) }, { NODE_PROBE(COUNTER_HTTP_CLIENT_RESPONSE) } }; for (int i = 0; i < ARRAY_SIZE(tab); i++) { tab[i].templ = Persistent::New( FunctionTemplate::New(tab[i].func)); target->Set(String::NewSymbol(tab[i].name), tab[i].templ->GetFunction()); } // Only Windows performance counters supported // To enable other OS, use conditional compilation here InitPerfCountersWin32(); // init times for GC percent calculation and hook callbacks counter_gc_start_time = NODE_COUNT_GET_GC_RAWTIME(); counter_gc_end_time = counter_gc_start_time; v8::V8::AddGCPrologueCallback(counter_gc_start); v8::V8::AddGCEpilogueCallback(counter_gc_done); } void TermPerfCounters(Handle target) { // Only Windows performance counters supported // To enable other OS, use conditional compilation here TermPerfCountersWin32(); } }