]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw: add functionality of SetAttribute and AddEvent method in postRequest context
authorOmri Zeneva <ozeneva@redhat.com>
Wed, 11 May 2022 13:39:49 +0000 (09:39 -0400)
committerOmri Zeneva <ozeneva@redhat.com>
Mon, 13 Jun 2022 06:05:11 +0000 (02:05 -0400)
opentelemetry supports mainly string, int64, double and boolean for values of trace's Attributes,
so we should validate those types and static cast to the proper type, which is different than Lua types

SetAttribute Closure will be returned to lua only if the request's trace is real and not noop span or even null like what happens in preRequest Context

AddEvent method comes to give us the ability to record an event. the event can be a single string that represents the event, or event name and key-value pairs.

Signed-off-by: Omri Zeneva <ozeneva@redhat.com>
src/common/tracer.h
src/rgw/rgw_lua_request.cc

index 5d77a0dcf159c37e4a471f5bb8ab5bff6c255b73..9d13c78aafcee3800ed635677ee83c332dbb87ba 100644 (file)
@@ -11,6 +11,7 @@
 
 using jspan = opentelemetry::nostd::shared_ptr<opentelemetry::trace::Span>;
 using jspan_context = opentelemetry::trace::SpanContext;
+using jspan_attribute = opentelemetry::common::AttributeValue;
 
 namespace tracing {
 
@@ -54,12 +55,13 @@ void decode(jspan_context& span_ctx, ceph::buffer::list::const_iterator& bl);
 
 #include <string_view>
 
-
 class Value {
  public:
   template <typename T> Value(T val) {}
 };
 
+using jspan_attribute = Value;
+
 struct jspan_context {
   jspan_context() {}
   jspan_context(bool sampled_flag, bool is_remote) {}
@@ -69,9 +71,12 @@ struct span_stub {
   jspan_context _ctx;
   template <typename T>
   void SetAttribute(std::string_view key, const T& value) const noexcept {}
-  void AddEvent(std::string_view, std::initializer_list<std::pair<std::string_view, Value>> fields) {}
+  void AddEvent(std::string_view) {}
+  void AddEvent(std::string_view, std::initializer_list<std::pair<std::string_view, jspan_attribute>> fields) {}
+  template <typename T> void AddEvent(std::string_view name, const T& fields = {}) {}
   const jspan_context& GetContext() { return _ctx; }
   void UpdateName(std::string_view) {}
+  bool IsRecording() { return false; }
 };
 
 class jspan {
index 58baa48b70e7945f89bf4ea26a50c4d67c4d7e80..242ed9fa98b9099aefafab60437c00a6b899686f 100644 (file)
@@ -41,6 +41,80 @@ int RequestLog(lua_State* L)
   return ONE_RETURNVAL;
 }
 
+int SetAttribute(lua_State* L)  {
+  auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(1)));
+
+  if (!s->trace || !s->trace->IsRecording()) {
+    return 0;
+  }
+
+  auto key = luaL_checkstring(L, 1);
+  int value_type = lua_type(L, 2);
+
+  switch (value_type) {
+    case LUA_TSTRING:
+      s->trace->SetAttribute(key, lua_tostring(L, 2));
+      break;
+
+    case LUA_TNUMBER:
+      if (lua_isinteger(L, 2)) {
+        s->trace->SetAttribute(key, static_cast<int64_t>(lua_tointeger(L, 2)));
+      } else {
+        s->trace->SetAttribute(key, static_cast<double>(lua_tonumber(L, 2)));
+      }
+      break;
+
+    default:
+      luaL_error(L, "unsupported value type for SetAttribute");
+  }
+  return 0;
+}
+
+int AddEvent(lua_State* L)  {
+  auto s = reinterpret_cast<req_state*>(lua_touserdata(L, lua_upvalueindex(1)));
+
+  if (!s->trace || !s->trace->IsRecording()) {
+    return 0;
+  }
+
+  int args = lua_gettop(L);
+  if (args == 1) {
+    auto log = luaL_checkstring(L, 1);
+    s->trace->AddEvent(log);
+  } else if(args == 2) {
+    auto event_name = luaL_checkstring(L, 1);
+    std::unordered_map<const char*, jspan_attribute> event_values;
+    lua_pushnil(L);
+    while (lua_next(L, 2) != 0) {
+      if (lua_type(L, -2) != LUA_TSTRING) {
+        // skip pair if key is not a string
+        lua_pop(L, 1);
+        continue;
+      }
+
+      auto key = luaL_checkstring(L, -2);
+      int value_type = lua_type(L, -1);
+      switch (value_type) {
+        case LUA_TSTRING:
+          event_values.emplace(key, lua_tostring(L, -1));
+          break;
+
+        case LUA_TNUMBER:
+          if (lua_isinteger(L, -1)) {
+            event_values.emplace(key, static_cast<int64_t>(lua_tointeger(L, -1)));
+          } else {
+            event_values.emplace(key, static_cast<double>(lua_tonumber(L, -1)));
+          }
+          break;
+      }
+      lua_pop(L, 1);
+    }
+    lua_pop(L, 1);
+    s->trace->AddEvent(event_name, event_values);
+  }
+  return 0;
+}
+
 struct ResponseMetaTable : public EmptyMetaTable {
   static std::string TableName() {return "Response";} 
   static std::string Name() {return TableName() + "Meta";}
@@ -159,6 +233,12 @@ struct TraceMetaTable : public EmptyMetaTable {
 
     if (strcasecmp(index, "Enable") == 0) {
       lua_pushboolean(L, s->trace_enabled);
+    } else if(strcasecmp(index, "SetAttribute") == 0) {
+        lua_pushlightuserdata(L, s);
+        lua_pushcclosure(L, SetAttribute, ONE_UPVAL);
+    } else if(strcasecmp(index, "AddEvent") == 0) {
+        lua_pushlightuserdata(L, s);
+        lua_pushcclosure(L, AddEvent, ONE_UPVAL);
     } else {
       return error_unknown_field(L, index, TableName());
     }