Skip to content

Commit

Permalink
feat: logging
Browse files Browse the repository at this point in the history
  • Loading branch information
bsrdjan committed Aug 4, 2023
1 parent af5af20 commit 9d72919
Show file tree
Hide file tree
Showing 7 changed files with 255 additions and 93 deletions.
16 changes: 9 additions & 7 deletions examples/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,37 @@ const delay = (seconds) =>
function my_stfc_connection(request_context, abap_input) {
const connection_attributes = request_context["connection_attributes"];
console.log(
"NodeJS stfc context :",
"[js] stfc context :",
connection_attributes["sysId"],
connection_attributes["client"],
connection_attributes["user"],
connection_attributes["cpicConvId"],
connection_attributes["progName"]
);
console.log("NodeJS stfc request :", abap_input);
console.log("[js] stfc request :", abap_input);
for (let i = 1; i < 1000000000; i++) x = i / 3;
// (async () => await delay(5))();
//const x = (async () => await delay(5))();
abap_output = {
REQUTEXT: abap_input.REQUTEXT,
ECHOTEXT: abap_input.REQUTEXT,
RESPTEXT: `~~~ ${abap_input.REQUTEXT} ~~~`,
};
console.log("NodeJS stfc response:", abap_output);
console.log("[js] stfc response:", abap_output);
return abap_output;
}

server.start((err) => {
if (err) return console.error("error:", err);
console.log(
`Server alive: ${server.alive} client handle: ${server.client_connection} server handle: ${server.server_connection}`
`[js] Server alive: ${server.alive} client handle: ${server.client_connection} server handle: ${server.server_connection}`
);

// Expose the my_stfc_connection function as RFM with STFC_CONNECTION pararameters (function definition)
const RFM_NAME = "STFC_CONNECTION";
server.addFunction(RFM_NAME, my_stfc_connection, (err) => {
if (err) return console.error(`error adding ${RFM_NAME}: ${err}`);
console.log(
`Node.js function '${my_stfc_connection.name}' registered as ABAP '${RFM_NAME}' function`
`[js] Node.js function '${my_stfc_connection.name}' registered as ABAP '${RFM_NAME}' function`
);
});
});
Expand All @@ -52,6 +52,8 @@ const si = setInterval(() => {
setTimeout(() => {
server.stop(() => {
clearInterval(si);
console.log("bye bye!");
console.log("bye!");
});
}, 10 * 1000);

// my_stfc_connection({}, {});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "node-rfc",
"version": "3.2.0",
"version": "3.3.0",
"description": "nodejs bindings for SAP NW RFC SDK",
"keywords": [
"sap",
Expand Down
64 changes: 44 additions & 20 deletions src/cpp/Client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Client.h"
#include <mutex>
#include <thread>
#include "Log.h"
#include "Pool.h"

namespace node_rfc {
Expand Down Expand Up @@ -122,8 +123,6 @@ Client::Client(const Napi::CallbackInfo& info)
: Napi::ObjectWrap<Client>(info) {
init();

DEBUG("Client::Client ", id);

if (!info[0].IsUndefined() && (info[0].IsFunction() || !info[0].IsObject())) {
Napi::TypeError::New(Env(), "Client connection parameters missing")
.ThrowAsJavaScriptException();
Expand All @@ -148,25 +147,35 @@ Client::Client(const Napi::CallbackInfo& info)
info.Length());
Napi::TypeError::New(node_rfc::__env, errmsg).ThrowAsJavaScriptException();
}

_log(logClass::client, logSeverity::info, "client created: ", id);
};

Client::~Client(void) {
DEBUG("~ Client ", id);

if (pool == nullptr) {
// Close own connection
if (connectionHandle != nullptr) {
RFC_ERROR_INFO errorInfo;
DEBUG("Closing direct connection ", (pointer_t)connectionHandle);
_log(logClass::client,
logSeverity::info,
id,
" closing connection ",
(pointer_t)connectionHandle);
RFC_RC rc = RfcCloseConnection(connectionHandle, &errorInfo);
if (rc != RFC_OK) {
EDEBUG("Warning: Error closing the direct connection handle ",
(pointer_t)connectionHandle,
(uintptr_t)connectionHandle,
" client ",
id);
}
} else {
DEBUG("Client ", id, " handle already closed");
_log(logClass::client,
logSeverity::warning,
"Client ",
id,
" connection ",
(uintptr_t)connectionHandle,
" already closed");
}

// Unref client config
Expand All @@ -190,7 +199,6 @@ Napi::Value Client::connectionClosedError(const char* suffix) {
}

Napi::Object Client::NewInstance(Napi::Env env) {
// DEBUG("Client::NewInstance");
Napi::EscapableHandleScope scope(env);
Napi::Object obj = env.GetInstanceData<Napi::FunctionReference>()->New({});
return scope.Escape(napi_value(obj)).ToObject();
Expand Down Expand Up @@ -537,7 +545,10 @@ ErrorPair Client::connectionCheck(RFC_ERROR_INFO* errorInfo) {
) // closed
{
if (errorInfo->code == RFC_CANCELED) {
EDEBUG("Connection canceled ", (pointer_t)this->connectionHandle);
_log(logClass::client,
logSeverity::warning,
"connection cancelled ",
(pointer_t)this->connectionHandle);
}

RFC_CONNECTION_HANDLE new_handle;
Expand Down Expand Up @@ -565,22 +576,32 @@ ErrorPair Client::connectionCheck(RFC_ERROR_INFO* errorInfo) {
return ErrorPair(errorInfoOpen, updateError);
}

DEBUG("new handle assigned to managed client");
_log(logClass::pool,
logSeverity::info,
"closed connection handle ",
(uintptr_t)old_handle,
" replaced with ",
(uintptr_t)new_handle);
this->connectionHandle = new_handle;
} else {
// assign new handle to direct client
this->connectionHandle = new_handle;
}
DEBUG("Critical connection error: group ",
errorInfo->group,
" code ",
errorInfo->code,
" closed handle ",
(pointer_t)old_handle,
" new handle ",
(pointer_t)new_handle);
_log(logClass::client,
logSeverity::warning,
"Critical ABAP error: group ",
errorInfo->group,
" code ",
errorInfo->code,
" closed connection handle ",
(pointer_t)old_handle,
" replaced with ",
(pointer_t)new_handle);
} else {
DEBUG("Non-critical ABAP error: ", (pointer_t)this->connectionHandle);
_log(logClass::client,
logSeverity::warning,
"Non-critical ABAP error: ",
(pointer_t)this->connectionHandle);
}

return ErrorPair(errorInfoOpen, "");
Expand Down Expand Up @@ -612,7 +633,10 @@ Napi::Value Client::Release(const Napi::CallbackInfo& info) {
void cancelConnection(RFC_RC* rc,
RFC_CONNECTION_HANDLE connectionHandle,
RFC_ERROR_INFO* errorInfo) {
EDEBUG("Cancel connection ", (pointer_t)connectionHandle);
_log(logClass::client,
logSeverity::info,
"connection cancelled ",
(pointer_t)connectionHandle);
*rc = RfcCancel(connectionHandle, errorInfo);
}

Expand Down
71 changes: 71 additions & 0 deletions src/cpp/Log.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// SPDX-FileCopyrightText: 2014 SAP SE Srdjan Boskovic <srdjan.boskovic@sap.com>
//
// SPDX-License-Identifier: Apache-2.0

#ifndef NodeRfc_Log_H
#define NodeRfc_Log_H

#include <chrono>
#include <fstream>
#include <string>

namespace node_rfc {

#define SERVER_LOGFILE "_noderfc.log"

enum class logClass { client, pool, server, throughput };
enum class logSeverity { info, warning, error };

long long timestamp() {
using namespace std;
return chrono::duration_cast<chrono::milliseconds>(
chrono::system_clock::now().time_since_epoch())
.count();
}

template <typename... Args>
void _log(logClass component, logSeverity severity, Args&&... args) {
using namespace std;
string component_name;
string severity_name;
switch (component) {
case logClass::client:
component_name = "client";
break;
case logClass::server:
component_name = "server";
break;
case logClass::pool:
component_name = "pool";
break;
case logClass::throughput:
component_name = "throughput";
break;
default:
component_name = "component?";
}
switch (severity) {
case logSeverity::info:
severity_name = "info";
break;
case logSeverity::warning:
severity_name = "warning";
break;
case logSeverity::error:
severity_name = "error";
break;
default:
severity_name = "severity?";
}
ofstream ofs;
ofs.open(SERVER_LOGFILE, ofstream::out | ios::app);
time_t now = time(nullptr);
ofs << put_time(localtime(&now), "%F %T [") << timestamp() << "] ";
ofs << component_name << " (" << severity_name << ") ";
(ofs << ... << args);
ofs << endl;
ofs.close();
}

} // namespace node_rfc
#endif
Loading

0 comments on commit 9d72919

Please sign in to comment.