Skip to content

Commit

Permalink
feat: Allow early logger initialization (#804)
Browse files Browse the repository at this point in the history
  • Loading branch information
guybedford committed Jun 20, 2024
1 parent a1bd16c commit 514d014
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 61 deletions.
3 changes: 3 additions & 0 deletions integration-tests/js-compute/fixtures/app/src/logger.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { Logger } from "fastly:logger";
import { routes, isRunningLocally } from "./routes";

const earlyLogger = new Logger("AnotherLog");

routes.set("/logger", () => {
if (isRunningLocally()) {
let logger = new Logger("ComputeLog");
logger.log("Hello!");
earlyLogger.log("World!");
}

return new Response();
Expand Down
6 changes: 1 addition & 5 deletions runtime/fastly/builtins/fastly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,7 @@ bool Fastly::getLogger(JSContext *cx, unsigned argc, JS::Value *vp) {
if (!args.requireAtLeast(cx, "fastly.getLogger", 1))
return false;

auto name = core::encode(cx, args[0]);
if (!name)
return false;

JS::RootedObject logger(cx, Logger::create(cx, name.begin()));
JS::RootedObject logger(cx, Logger::create(cx, args[0]));
if (!logger) {
return false;
}
Expand Down
51 changes: 29 additions & 22 deletions runtime/fastly/builtins/logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,31 @@ namespace fastly::logger {
bool Logger::log(JSContext *cx, unsigned argc, JS::Value *vp) {
METHOD_HEADER(1)

host_api::LogEndpoint endpoint(JS::GetReservedSlot(self, Logger::Slots::Endpoint).toInt32());
JS::RootedValue endpoint_id(cx, JS::GetReservedSlot(self, Slots::Endpoint));

// If the endpoint has not yet been loaded up, do it now, throwing any endpoint error for the
// first log.
if (endpoint_id.isNull()) {
JS::RootedString endpoint_name(cx, JS::GetReservedSlot(self, Slots::EndpointName).toString());
auto endpoint_name_str = core::encode(cx, endpoint_name);
if (!endpoint_name_str) {
return false;
}

auto res = host_api::LogEndpoint::get(
std::string_view{endpoint_name_str.ptr.get(), endpoint_name_str.len});
if (auto *err = res.to_err()) {
HANDLE_ERROR(cx, *err);
return false;
}

endpoint_id.set(JS::Int32Value(res.unwrap().handle));
JS::SetReservedSlot(self, Slots::Endpoint, endpoint_id);

MOZ_ASSERT(endpoint_id.isInt32());
}

host_api::LogEndpoint endpoint(endpoint_id.toInt32());

auto msg = core::encode(cx, args.get(0));
if (!msg) {
Expand Down Expand Up @@ -38,36 +62,19 @@ const JSFunctionSpec Logger::methods[] = {JS_FN("log", log, 1, JSPROP_ENUMERATE)

const JSPropertySpec Logger::properties[] = {JS_PS_END};

JSObject *Logger::create(JSContext *cx, const char *name) {
JSObject *Logger::create(JSContext *cx, JS::HandleValue endpoint_name) {
JS::RootedObject logger(cx, JS_NewObjectWithGivenProto(cx, &class_, proto_obj));
if (!logger) {
return nullptr;
}

auto res = host_api::LogEndpoint::get(std::string_view{name, strlen(name)});
if (auto *err = res.to_err()) {
HANDLE_ERROR(cx, *err);
return nullptr;
}

JS::SetReservedSlot(logger, Slots::Endpoint, JS::Int32Value(res.unwrap().handle));

JS::SetReservedSlot(logger, Slots::Endpoint, JS::NullValue());
JS::SetReservedSlot(logger, Slots::EndpointName, endpoint_name);
return logger;
}

bool Logger::constructor(JSContext *cx, unsigned argc, JS::Value *vp) {
REQUEST_HANDLER_ONLY("The Logger builtin");
CTOR_HEADER("Logger", 1);

auto name = core::encode(cx, args[0]);
auto handle_res = host_api::LogEndpoint::get(name);
if (auto *err = handle_res.to_err()) {
HANDLE_ERROR(cx, *err);
return false;
}

JS::RootedObject logger(cx, JS_NewObjectForConstructor(cx, &class_, args));
JS::SetReservedSlot(logger, Slots::Endpoint, JS::Int32Value(handle_res.unwrap().handle));
auto logger = Logger::create(cx, args[0]);
args.rval().setObject(*logger);
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions runtime/fastly/builtins/logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ class Logger : public builtins::BuiltinImpl<Logger> {
static constexpr const char *class_name = "Logger";
static const int ctor_length = 1;

enum Slots { Endpoint, Count };
enum Slots { Endpoint, EndpointName, Count };
static const JSFunctionSpec static_methods[];
static const JSPropertySpec static_properties[];
static const JSFunctionSpec methods[];
static const JSPropertySpec properties[];

static JSObject *create(JSContext *cx, const char *name);
static JSObject *create(JSContext *cx, JS::HandleValue endpoint_name);
static bool constructor(JSContext *cx, unsigned argc, JS::Value *vp);
};

Expand Down
9 changes: 1 addition & 8 deletions runtime/js-compute-runtime/builtins/fastly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,14 @@ bool Fastly::getGeolocationForIpAddress(JSContext *cx, unsigned argc, JS::Value
return JS_ParseJSON(cx, geo_info_str, args.rval());
}

// TODO(performance): consider allowing logger creation during initialization, but then throw
// when trying to log.
// https://github.com/fastly/js-compute-runtime/issues/225
bool Fastly::getLogger(JSContext *cx, unsigned argc, JS::Value *vp) {
JS::CallArgs args = CallArgsFromVp(argc, vp);
REQUEST_HANDLER_ONLY("fastly.getLogger");
JS::RootedObject self(cx, &args.thisv().toObject());
if (!args.requireAtLeast(cx, "fastly.getLogger", 1))
return false;

auto name = core::encode(cx, args[0]);
if (!name)
return false;

JS::RootedObject logger(cx, builtins::Logger::create(cx, name.begin()));
JS::RootedObject logger(cx, builtins::Logger::create(cx, args[0]));
if (!logger) {
return false;
}
Expand Down
51 changes: 29 additions & 22 deletions runtime/js-compute-runtime/builtins/logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,31 @@ namespace builtins {
bool Logger::log(JSContext *cx, unsigned argc, JS::Value *vp) {
METHOD_HEADER(1)

host_api::LogEndpoint endpoint(JS::GetReservedSlot(self, Logger::Slots::Endpoint).toInt32());
JS::RootedValue endpoint_id(cx, JS::GetReservedSlot(self, Slots::Endpoint));

// If the endpoint has not yet been loaded up, do it now, throwing any endpoint error for the
// first log.
if (endpoint_id.isNull()) {
JS::RootedString endpoint_name(cx, JS::GetReservedSlot(self, Slots::EndpointName).toString());
auto endpoint_name_str = core::encode(cx, endpoint_name);
if (!endpoint_name_str) {
return false;
}

auto res = host_api::LogEndpoint::get(
std::string_view{endpoint_name_str.ptr.get(), endpoint_name_str.len});
if (auto *err = res.to_err()) {
HANDLE_ERROR(cx, *err);
return false;
}

endpoint_id.set(JS::Int32Value(res.unwrap().handle));
JS::SetReservedSlot(self, Slots::Endpoint, endpoint_id);

MOZ_ASSERT(endpoint_id.isInt32());
}

host_api::LogEndpoint endpoint(endpoint_id.toInt32());

auto msg = core::encode(cx, args.get(0));
if (!msg) {
Expand Down Expand Up @@ -36,36 +60,19 @@ const JSFunctionSpec Logger::methods[] = {JS_FN("log", log, 1, JSPROP_ENUMERATE)

const JSPropertySpec Logger::properties[] = {JS_PS_END};

JSObject *Logger::create(JSContext *cx, const char *name) {
JSObject *Logger::create(JSContext *cx, JS::HandleValue endpoint_name) {
JS::RootedObject logger(cx, JS_NewObjectWithGivenProto(cx, &class_, proto_obj));
if (!logger) {
return nullptr;
}

auto res = host_api::LogEndpoint::get(std::string_view{name, strlen(name)});
if (auto *err = res.to_err()) {
HANDLE_ERROR(cx, *err);
return nullptr;
}

JS::SetReservedSlot(logger, Slots::Endpoint, JS::Int32Value(res.unwrap().handle));

JS::SetReservedSlot(logger, Slots::Endpoint, JS::NullValue());
JS::SetReservedSlot(logger, Slots::EndpointName, endpoint_name);
return logger;
}

bool Logger::constructor(JSContext *cx, unsigned argc, JS::Value *vp) {
REQUEST_HANDLER_ONLY("The Logger builtin");
CTOR_HEADER("Logger", 1);

auto name = core::encode(cx, args[0]);
auto handle_res = host_api::LogEndpoint::get(name);
if (auto *err = handle_res.to_err()) {
HANDLE_ERROR(cx, *err);
return false;
}

JS::RootedObject logger(cx, JS_NewObjectForConstructor(cx, &class_, args));
JS::SetReservedSlot(logger, Slots::Endpoint, JS::Int32Value(handle_res.unwrap().handle));
auto logger = Logger::create(cx, args[0]);
args.rval().setObject(*logger);
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions runtime/js-compute-runtime/builtins/logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ class Logger : public BuiltinImpl<Logger> {
static constexpr const char *class_name = "Logger";
static const int ctor_length = 1;

enum Slots { Endpoint, Count };
enum Slots { Endpoint, EndpointName, Count };
static const JSFunctionSpec static_methods[];
static const JSPropertySpec static_properties[];
static const JSFunctionSpec methods[];
static const JSPropertySpec properties[];

static JSObject *create(JSContext *cx, const char *name);
static JSObject *create(JSContext *cx, JS::HandleValue endpoint_name);
static bool constructor(JSContext *cx, unsigned argc, JS::Value *vp);
static bool init_class(JSContext *cx, JS::HandleObject global);
};
Expand Down

0 comments on commit 514d014

Please sign in to comment.