RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 /* logger_logger_js.cc 00002 Jeremy Barnes, 20 May 2011 00003 Copyright (c) 2011 Datacratic. All rights reserved. 00004 00005 */ 00006 00007 #include "logger.h" 00008 #include "soa/types/periodic_utils.h" 00009 #include "remote_output.h" 00010 #include "remote_input.h" 00011 #include "file_output.h" 00012 #include "publish_output.h" 00013 #include "v8.h" 00014 #include "node.h" 00015 #include "soa/js/js_value.h" 00016 #include "soa/js/js_utils.h" 00017 #include "soa/js/js_wrapped.h" 00018 #include "soa/js/js_call.h" 00019 #include "soa/js/js_registry.h" 00020 #include "jml/arch/timers.h" 00021 #include "jml/utils/guard.h" 00022 #include "soa/sigslot/slot.h" 00023 #include "jml/utils/guard.h" 00024 #include "soa/sigslot/slot_js.h" 00025 #include <boost/static_assert.hpp> 00026 #include "soa/js/js_call.h" 00027 00028 using namespace std; 00029 using namespace v8; 00030 using namespace node; 00031 00032 00033 namespace Datacratic { 00034 namespace JS { 00035 00036 extern Registry registry; 00037 00038 extern const char * const loggerModule; 00039 00040 const char * const loggerModule = "logger"; 00041 00042 // Node.js initialization function; called to set up the LOGGER object 00043 extern "C" void 00044 init(Handle<v8::Object> target) 00045 { 00046 Datacratic::JS::registry.init(target, loggerModule); 00047 } 00048 00049 00050 /*****************************************************************************/ 00051 /* LOG OUTPUT JS */ 00052 /*****************************************************************************/ 00053 00054 const char * LogOutputName = "LogOutput"; 00055 00056 struct LogOutputJS 00057 : public JSWrapped2<LogOutput, LogOutputJS, LogOutputName, 00058 loggerModule, true> { 00059 00060 LogOutputJS() 00061 { 00062 } 00063 00064 static Handle<v8::Value> 00065 New(const Arguments & args) 00066 { 00067 try { 00068 throw ML::Exception("can't construct a LogOutputJS"); 00069 return args.This(); 00070 } HANDLE_JS_EXCEPTIONS; 00071 } 00072 00073 static void Initialize() 00074 { 00075 Persistent<FunctionTemplate> t = Register(New); 00076 00077 // Instance methods 00078 NODE_SET_PROTOTYPE_METHOD(t, "logMessage", logMessage); 00079 NODE_SET_PROTOTYPE_METHOD(t, "close", close); 00080 NODE_SET_PROTOTYPE_METHOD(t, "stats", stats); 00081 NODE_SET_PROTOTYPE_METHOD(t, "clearStats", clearStats); 00082 } 00083 00084 static Handle<v8::Value> 00085 logMessage(const Arguments & args) 00086 { 00087 try { 00088 if (args[0]->IsArray()) { 00089 vector<string> values = getArg(args, 0, "values"); 00090 ostringstream ss; 00091 std::copy(values.begin() + 1, values.end(), 00092 std::ostream_iterator<string>(ss, "\t")); 00093 getShared(args) 00094 ->logMessage(values.at(0), ss.str()); 00095 } 00096 else if (args[1]->IsArray()) { 00097 string channel = getArg(args, 0, "channel"); 00098 vector<string> values = getArg(args, 1, "message"); 00099 ostringstream ss; 00100 std::copy(values.begin(), values.end(), 00101 std::ostream_iterator<string>(ss, "\t")); 00102 getShared(args) 00103 ->logMessage(channel, ss.str()); 00104 } 00105 else { 00106 getShared(args) 00107 ->logMessage(getArg(args, 0, "channel"), 00108 getArg(args, 1, "message")); 00109 } 00110 return args.This(); 00111 } HANDLE_JS_EXCEPTIONS; 00112 } 00113 00114 static Handle<v8::Value> 00115 close(const Arguments & args) 00116 { 00117 try { 00118 cerr << "doing output close" << endl; 00119 getShared(args)->close(); 00120 return args.This(); 00121 } HANDLE_JS_EXCEPTIONS; 00122 } 00123 00124 static Handle<v8::Value> 00125 stats(const Arguments & args) 00126 { 00127 try { 00128 return JS::toJS(getShared(args)->stats()); 00129 } HANDLE_JS_EXCEPTIONS; 00130 } 00131 00132 static Handle<v8::Value> 00133 clearStats(const Arguments & args) 00134 { 00135 try { 00136 getShared(args)->clearStats(); 00137 return args.This(); 00138 } HANDLE_JS_EXCEPTIONS; 00139 } 00140 }; 00141 00142 std::shared_ptr<LogOutput> 00143 from_js(const JSValue & value, std::shared_ptr<LogOutput> *) 00144 { 00145 return LogOutputJS::fromJS(value); 00146 } 00147 00148 LogOutput * 00149 from_js(const JSValue & value, LogOutput **) 00150 { 00151 return LogOutputJS::fromJS(value).get(); 00152 } 00153 00154 00155 /*****************************************************************************/ 00156 /* JS OUTPUT */ 00157 /*****************************************************************************/ 00158 00159 class JSOutputJS; 00160 00163 struct JSOutput : public LogOutput { 00164 00165 JSOutput() 00166 : wrapper(0) 00167 { 00168 } 00169 00170 virtual ~JSOutput() 00171 { 00172 } 00173 00174 SlotT<void (std::string, std::string)> logMessageSlot; 00175 JSOutputJS * wrapper; 00176 00177 virtual void logMessage(const std::string & channel, 00178 const std::string & message) 00179 { 00180 //cerr << "logMessage JS " << channel << endl; 00181 00182 auto cb = [=] () { 00183 this->logMessageSlot.call(channel, message); 00184 }; 00185 callInJsContext(cb); 00186 } 00187 00188 SlotT<void ()> closeSlot; 00189 00190 virtual void close() 00191 { 00192 if (closeSlot.isEmpty()) return; 00193 //cerr << "logMessage JS " << channel << endl; 00194 00195 auto cb = [=] () { 00196 this->closeSlot.call(); 00197 }; 00198 callInJsContext(cb); 00199 } 00200 }; 00201 00202 RegisterJsOps<void (std::string, std::string)> reg_logMessage; 00203 RegisterJsOps<void (std::string)> reg_fileOpen; 00204 RegisterJsOps<void (std::string, std::size_t)> reg_fileWrite; 00205 00206 00207 /*****************************************************************************/ 00208 /* JS OUTPUT JS */ 00209 /*****************************************************************************/ 00210 00211 const char * JSOutputName = "JSOutput"; 00212 00213 struct JSOutputJS 00214 : public JSWrapped3<JSOutput, JSOutputJS, LogOutputJS, JSOutputName, 00215 loggerModule, true> { 00216 00217 JSOutputJS(const v8::Handle<v8::Object> & This, 00218 const std::shared_ptr<JSOutput> & output 00219 = std::shared_ptr<JSOutput>()) 00220 { 00221 wrap(This, output); 00222 getShared(This)->wrapper = this; 00223 } 00224 00225 ~JSOutputJS() 00226 { 00227 getShared(js_object_)->wrapper = 0; 00228 } 00229 00230 static Handle<v8::Value> 00231 New(const Arguments & args) 00232 { 00233 try { 00234 new JSOutputJS 00235 (args.This(), 00236 std::shared_ptr<JSOutput> 00237 (new JSOutput())); 00238 00239 return args.This(); 00240 } HANDLE_JS_EXCEPTIONS; 00241 } 00242 00243 static void Initialize() 00244 { 00245 Persistent<FunctionTemplate> t = Register(New); 00246 00247 registerRWProperty(&JSOutput::logMessageSlot, "logMessage"); 00248 registerRWProperty(&JSOutput::closeSlot, "close"); 00249 } 00250 }; 00251 00252 00253 /*****************************************************************************/ 00254 /* FILE OUTPUT JS */ 00255 /*****************************************************************************/ 00256 00257 const char * FileOutputName = "FileOutput"; 00258 00259 struct FileOutputJS 00260 : public JSWrapped3<FileOutput, FileOutputJS, LogOutputJS, FileOutputName, 00261 loggerModule, true> { 00262 00263 FileOutputJS(const v8::Handle<v8::Object> & This, 00264 const std::shared_ptr<FileOutput> & output 00265 = std::shared_ptr<FileOutput>()) 00266 { 00267 wrap(This, output); 00268 } 00269 00270 static Handle<v8::Value> 00271 New(const Arguments & args) 00272 { 00273 try { 00274 if (!args[0]->IsUndefined()) { 00275 new FileOutputJS 00276 (args.This(), 00277 std::shared_ptr<FileOutput> 00278 (new FileOutput 00279 (getArg<string>(args, 0, "", "filename")))); 00280 } 00281 else { 00282 new FileOutputJS 00283 (args.This(), 00284 std::shared_ptr<FileOutput> 00285 (new FileOutput())); 00286 } 00287 return args.This(); 00288 } HANDLE_JS_EXCEPTIONS; 00289 } 00290 00291 static void Initialize() 00292 { 00293 Persistent<FunctionTemplate> t = Register(New); 00294 00295 // Instance methods 00296 NODE_SET_PROTOTYPE_METHOD(t, "open", open); 00297 00298 registerAsyncCallback(&FileOutput::onPreFileOpen, 00299 "preFileOpen"); 00300 registerAsyncCallback(&FileOutput::onPostFileOpen, 00301 "postFileOpen"); 00302 registerAsyncCallback(&FileOutput::onPreFileClose, 00303 "preFileClose"); 00304 registerAsyncCallback(&FileOutput::onPostFileClose, 00305 "postFileClose"); 00306 registerAsyncCallback(&FileOutput::onFileWrite, 00307 "onFileWrite"); 00308 00309 } 00310 00311 static Handle<v8::Value> 00312 open(const Arguments & args) 00313 { 00314 try { 00315 getShared(args) 00316 ->open(getArg(args, 0, "filename"), 00317 getArg(args, 1, "", "compression"), 00318 getArg(args, 2, -1, "compressionLevel")); 00319 return args.This(); 00320 } HANDLE_JS_EXCEPTIONS; 00321 } 00322 }; 00323 00324 00325 /*****************************************************************************/ 00326 /* ROTATING FILE OUTPUT JS */ 00327 /*****************************************************************************/ 00328 00329 const char * RotatingFileOutputName = "RotatingFileOutput"; 00330 00331 struct RotatingFileOutputJS 00332 : public JSWrapped3<RotatingFileOutput, RotatingFileOutputJS, 00333 LogOutputJS, RotatingFileOutputName, 00334 loggerModule, true> { 00335 00336 RotatingFileOutputJS(const v8::Handle<v8::Object> & This, 00337 const std::shared_ptr<RotatingFileOutput> & output 00338 = std::shared_ptr<RotatingFileOutput>()) 00339 { 00340 wrap(This, output); 00341 } 00342 00343 static Handle<v8::Value> 00344 New(const Arguments & args) 00345 { 00346 try { 00347 new RotatingFileOutputJS 00348 (args.This(), 00349 std::shared_ptr<RotatingFileOutput> 00350 (new RotatingFileOutput())); 00351 return args.This(); 00352 } HANDLE_JS_EXCEPTIONS; 00353 } 00354 00355 static void Initialize() 00356 { 00357 Persistent<FunctionTemplate> t = Register(New); 00358 00359 // Instance methods 00360 NODE_SET_PROTOTYPE_METHOD(t, "open", open); 00361 00362 NODE_SET_METHOD(t, "findPeriod", findPeriod); 00363 NODE_SET_METHOD(t, "filenameFor", filenameFor); 00364 NODE_SET_METHOD(t, "parsePeriod", parsePeriod); 00365 00366 registerAsyncCallback(&RotatingFileOutput::onBeforeLogRotation, 00367 "beforeLogRotation"); 00368 registerAsyncCallback(&RotatingFileOutput::onAfterLogRotation, 00369 "afterLogRotation"); 00370 registerAsyncCallback(&RotatingFileOutput::onPreFileOpen, 00371 "preFileOpen"); 00372 registerAsyncCallback(&RotatingFileOutput::onPostFileOpen, 00373 "postFileOpen"); 00374 registerAsyncCallback(&RotatingFileOutput::onPreFileClose, 00375 "preFileClose"); 00376 registerAsyncCallback(&RotatingFileOutput::onPostFileClose, 00377 "postFileClose"); 00378 registerAsyncCallback(&RotatingFileOutput::onFileWrite, 00379 "onFileWrite"); 00380 00381 } 00382 00383 static Handle<v8::Value> 00384 open(const Arguments & args) 00385 { 00386 try { 00387 getShared(args) 00388 ->open(getArg(args, 0, "filenamePattern"), 00389 getArg(args, 1, "period"), 00390 getArg(args, 2, "", "compression"), 00391 getArg(args, 3, -1, "compressionLevel")); 00392 return args.This(); 00393 } HANDLE_JS_EXCEPTIONS; 00394 } 00395 00396 static Handle<v8::Value> 00397 findPeriod(const Arguments & args) 00398 { 00399 try { 00400 return JS::toJS(Datacratic::findPeriod 00401 (getArg(args, 0, "date"), 00402 getArg(args, 1, "periodName"))); 00403 } HANDLE_JS_EXCEPTIONS; 00404 } 00405 00406 static Handle<v8::Value> 00407 filenameFor(const Arguments & args) 00408 { 00409 try { 00410 return JS::toJS(Datacratic::filenameFor 00411 (getArg(args, 0, "date"), 00412 getArg(args, 1, "filenamePattern"))); 00413 } HANDLE_JS_EXCEPTIONS; 00414 } 00415 00416 static Handle<v8::Value> 00417 parsePeriod(const Arguments & args) 00418 { 00419 try { 00420 return JS::toJS(Datacratic::parsePeriod 00421 (getArg(args, 0, "period"))); 00422 } HANDLE_JS_EXCEPTIONS; 00423 } 00424 00425 }; 00426 00427 00428 /*****************************************************************************/ 00429 /* PUBLISH OUTPUT JS */ 00430 /*****************************************************************************/ 00431 00432 const char * PublishOutputName = "PublishOutput"; 00433 00434 struct PublishOutputJS 00435 : public JSWrapped3<PublishOutput, PublishOutputJS, LogOutputJS, 00436 PublishOutputName, loggerModule, true> { 00437 00438 PublishOutputJS(const v8::Handle<v8::Object> & This, 00439 const std::shared_ptr<PublishOutput> & output 00440 = std::shared_ptr<PublishOutput>()) 00441 { 00442 wrap(This, output); 00443 } 00444 00445 static Handle<v8::Value> 00446 New(const Arguments & args) 00447 { 00448 try { 00449 new PublishOutputJS 00450 (args.This(), 00451 std::shared_ptr<PublishOutput> 00452 (new PublishOutput())); 00453 return args.This(); 00454 } HANDLE_JS_EXCEPTIONS; 00455 } 00456 00457 static void Initialize() 00458 { 00459 Persistent<FunctionTemplate> t = Register(New); 00460 00461 // Instance methods 00462 NODE_SET_PROTOTYPE_METHOD(t, "bind", bind); 00463 } 00464 00465 static Handle<v8::Value> 00466 bind(const Arguments & args) 00467 { 00468 try { 00469 getShared(args) 00470 ->bind(getArg(args, 0, "bindUri")); 00471 return args.This(); 00472 } HANDLE_JS_EXCEPTIONS; 00473 } 00474 }; 00475 00476 00477 /*****************************************************************************/ 00478 /* REMOTE OUTPUT JS */ 00479 /*****************************************************************************/ 00480 00481 const char * RemoteOutputName = "RemoteOutput"; 00482 00483 struct RemoteOutputJS 00484 : public JSWrapped3<RemoteOutput, RemoteOutputJS, LogOutputJS, 00485 RemoteOutputName, loggerModule, true> { 00486 00487 RemoteOutputJS(const v8::Handle<v8::Object> & This, 00488 const std::shared_ptr<RemoteOutput> & output 00489 = std::shared_ptr<RemoteOutput>()) 00490 { 00491 wrap(This, output); 00492 } 00493 00494 static Handle<v8::Value> 00495 New(const Arguments & args) 00496 { 00497 try { 00498 new RemoteOutputJS 00499 (args.This(), 00500 std::shared_ptr<RemoteOutput> 00501 (new RemoteOutput())); 00502 return args.This(); 00503 } HANDLE_JS_EXCEPTIONS; 00504 } 00505 00506 static void Initialize() 00507 { 00508 Persistent<FunctionTemplate> t = Register(New); 00509 00510 // Instance methods 00511 NODE_SET_PROTOTYPE_METHOD(t, "connect", connect); 00512 NODE_SET_PROTOTYPE_METHOD(t, "shutdown", shutdown); 00513 } 00514 00515 static Handle<v8::Value> 00516 connect(const Arguments & args) 00517 { 00518 try { 00519 getShared(args) 00520 ->connect(getArg(args, 0, "port"), 00521 getArg(args, 1, "hostname"), 00522 getArg(args, 2, 10.0, "timeout")); 00523 return args.This(); 00524 } HANDLE_JS_EXCEPTIONS; 00525 } 00526 00527 static Handle<v8::Value> 00528 shutdown(const Arguments & args) 00529 { 00530 try { 00531 getShared(args)->shutdown(); 00532 return args.This(); 00533 } HANDLE_JS_EXCEPTIONS; 00534 } 00535 }; 00536 00537 00538 /*****************************************************************************/ 00539 /* REMOTE INPUT JS */ 00540 /*****************************************************************************/ 00541 00542 const char * RemoteInputName = "RemoteInput"; 00543 00544 struct RemoteInputJS 00545 : public JSWrapped2<RemoteInput, RemoteInputJS, 00546 RemoteInputName, loggerModule, true> { 00547 00548 RemoteInputJS(const v8::Handle<v8::Object> & This, 00549 const std::shared_ptr<RemoteInput> & input 00550 = std::shared_ptr<RemoteInput>()) 00551 { 00552 wrap(This, input); 00553 } 00554 00555 static Handle<v8::Value> 00556 New(const Arguments & args) 00557 { 00558 try { 00559 new RemoteInputJS 00560 (args.This(), 00561 std::shared_ptr<RemoteInput> 00562 (new RemoteInput())); 00563 return args.This(); 00564 } HANDLE_JS_EXCEPTIONS; 00565 } 00566 00567 static void Initialize() 00568 { 00569 Persistent<FunctionTemplate> t = Register(New); 00570 00571 // Instance methods 00572 NODE_SET_PROTOTYPE_METHOD(t, "listen", listen); 00573 NODE_SET_PROTOTYPE_METHOD(t, "shutdown", shutdown); 00574 NODE_SET_PROTOTYPE_METHOD(t, "port", port); 00575 } 00576 00577 static Handle<v8::Value> 00578 listen(const Arguments & args) 00579 { 00580 try { 00581 struct ev_loop * loop = ev_default_loop(0); 00582 ev_ref(loop); 00583 00584 v8::Persistent<v8::Object> phandle 00585 = v8::Persistent<v8::Object>::New(args.This()); 00586 00587 auto cleanup = [=] () 00588 { 00589 v8::Persistent<v8::Object> handle = phandle; 00590 ev_unref(loop); 00591 handle.Clear(); 00592 handle.Dispose(); 00593 }; 00594 00595 ML::Call_Guard doCleanup(cleanup); // cleanup on exception 00596 00597 getShared(args)->listen(getArg(args, 0, -1, "port"), 00598 getArg(args, 1, "localhost", "address"), 00599 cleanup); 00600 00601 doCleanup.clear(); 00602 00603 return args.This(); 00604 } HANDLE_JS_EXCEPTIONS; 00605 } 00606 00607 static Handle<v8::Value> 00608 port(const Arguments & args) 00609 { 00610 try { 00611 return JS::toJS(getShared(args)->port()); 00612 } HANDLE_JS_EXCEPTIONS; 00613 } 00614 00615 static Handle<v8::Value> 00616 shutdown(const Arguments & args) 00617 { 00618 try { 00619 getShared(args)->shutdown(); 00620 return args.This(); 00621 } HANDLE_JS_EXCEPTIONS; 00622 } 00623 }; 00624 00625 00626 /*****************************************************************************/ 00627 /* LOGGER JS */ 00628 /*****************************************************************************/ 00629 00630 const char * LoggerName = "Logger"; 00631 00632 struct LoggerJS 00633 : public JSWrapped2<Logger, LoggerJS, LoggerName, loggerModule, true> { 00634 00635 LoggerJS(const v8::Handle<v8::Object> & This, 00636 const std::shared_ptr<Logger> & logger 00637 = std::shared_ptr<Logger>()) 00638 { 00639 wrap(This, logger); 00640 } 00641 00642 static Handle<v8::Value> 00643 New(const Arguments & args) 00644 { 00645 try { 00646 new LoggerJS(args.This(), 00647 std::shared_ptr<Logger>(new Logger())); 00648 return args.This(); 00649 } HANDLE_JS_EXCEPTIONS; 00650 } 00651 00652 static void Initialize() 00653 { 00654 Persistent<FunctionTemplate> t = Register(New); 00655 00656 // Instance methods 00657 NODE_SET_PROTOTYPE_METHOD(t, "logTo", logTo); 00658 NODE_SET_PROTOTYPE_METHOD(t, "addOutput", addOutput); 00659 NODE_SET_PROTOTYPE_METHOD(t, "clearOutputs", clearOutputs); 00660 NODE_SET_PROTOTYPE_METHOD(t, "logMessage", logMessage); 00661 NODE_SET_PROTOTYPE_METHOD(t, "start", start); 00662 NODE_SET_PROTOTYPE_METHOD(t, "shutdown", shutdown); 00663 NODE_SET_PROTOTYPE_METHOD(t, "subscribe", subscribe); 00664 } 00665 00666 static Handle<v8::Value> 00667 start(const Arguments & args) 00668 { 00669 try { 00670 // Make sure Node doesn't exit and we don't get GCd when the 00671 // event loop is running. 00672 00673 struct ev_loop * loop = ev_default_loop(0); 00674 ev_ref(loop); 00675 v8::Persistent<v8::Object> phandle 00676 = v8::Persistent<v8::Object>::New(args.This()); 00677 00678 auto cleanup = [=] () 00679 { 00680 v8::Persistent<v8::Object> handle = phandle; 00681 ev_unref(loop); 00682 handle.Clear(); 00683 handle.Dispose(); 00684 }; 00685 00686 ML::Call_Guard doCleanup(cleanup); // cleanup on exception 00687 00688 getShared(args)->start(cleanup); 00689 00690 doCleanup.clear(); 00691 00692 return args.This(); 00693 } HANDLE_JS_EXCEPTIONS; 00694 } 00695 00696 static boost::regex getRegex(const Arguments & args, 00697 int argNum, 00698 const std::string & name) 00699 { 00700 string s = getArg(args, argNum, "", name); 00701 if (s == "") 00702 return boost::regex(); 00703 return boost::regex(s); 00704 } 00705 00706 00707 static Handle<v8::Value> 00708 addOutput(const Arguments & args) 00709 { 00710 try { 00711 getShared(args) 00712 ->addOutput(getArg(args, 0, "output"), 00713 getRegex(args, 1, "allowChannels"), 00714 getRegex(args, 2, "denyChannels"), 00715 getArg(args, 3, 1.0, "logProbability")); 00716 00717 return args.This(); 00718 } HANDLE_JS_EXCEPTIONS; 00719 } 00720 00721 static Handle<v8::Value> 00722 logTo(const Arguments & args) 00723 { 00724 try { 00725 getShared(args) 00726 ->logTo(getArg(args, 0, "logUri"), 00727 getRegex(args, 1, "allowChannels"), 00728 getRegex(args, 2, "denyChannels"), 00729 getArg(args, 3, 1.0, "logProbability")); 00730 00731 return args.This(); 00732 } HANDLE_JS_EXCEPTIONS; 00733 } 00734 00735 static Handle<v8::Value> 00736 clearOutputs(const Arguments & args) 00737 { 00738 try { 00739 getShared(args)->clearOutputs(); 00740 return args.This(); 00741 } HANDLE_JS_EXCEPTIONS; 00742 } 00743 00744 static Handle<v8::Value> 00745 logMessage(const Arguments & args) 00746 { 00747 try { 00748 auto getEl = [&] (int el) 00749 { 00750 return getArg<string>(args, el + 1, "logItem"); 00751 }; 00752 00753 getShared(args)->logMessage(getArg(args, 0, "channel"), 00754 args.Length() - 1, 00755 getEl); 00756 return args.This(); 00757 } HANDLE_JS_EXCEPTIONS; 00758 } 00759 00760 static Handle<v8::Value> 00761 shutdown(const Arguments & args) 00762 { 00763 try { 00764 getShared(args)->shutdown(); 00765 return args.This(); 00766 } HANDLE_JS_EXCEPTIONS; 00767 } 00768 00769 static Handle<v8::Value> 00770 subscribe(const Arguments & args) 00771 { 00772 try { 00773 getShared(args)->subscribe(getArg(args, 0, "subscribeUri"), 00774 getArg(args, 1, vector<string>(), 00775 "channels"), 00776 getArg(args, 2, "", "identity")); 00777 return args.This(); 00778 } HANDLE_JS_EXCEPTIONS; 00779 } 00780 }; 00781 00782 std::shared_ptr<Logger> 00783 from_js(const JSValue & value, std::shared_ptr<Logger> *) 00784 { 00785 return LoggerJS::fromJS(value); 00786 } 00787 00788 Logger * 00789 from_js(const JSValue & value, Logger **) 00790 { 00791 return LoggerJS::fromJS(value).get(); 00792 } 00793 00794 00795 } // namespace JS 00796 } // namespace Datacratic