]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Merge pull request #46313 from zenomri/wip-omri-tracing-lua
authorYuval Lifshitz <ylifshit@redhat.com>
Tue, 14 Jun 2022 09:22:21 +0000 (12:22 +0300)
committerGitHub <noreply@github.com>
Tue, 14 Jun 2022 09:22:21 +0000 (12:22 +0300)
rgw: add SetAttribute and AddEvent functions for TraceMetaTable in Lua

Reviewed-by: yuvalif
1  2 
doc/radosgw/lua-scripting.rst
src/rgw/rgw_lua_request.cc
src/test/rgw/test_rgw_lua.cc

index fe8c6e271653fb614135f74e461931892abc9d77,5240f933597bb2c9c5cf9feb403db75fa9bf609d..cba75b2bcec3ec2efa8d6990a736c405430e7486
@@@ -309,27 -309,30 +309,40 @@@ The ``Request.Log()`` function prints t
  Background Context
  --------------------
  The ``background`` context may be used for purposes that include analytics, monitoring, caching data for other context executions.
 +- Background script execution default interval is 5 seconds.
  
 +Global ``RGW`` Table
 +--------------------
  The ``RGW`` Lua table is accessible from all contexts and saves data written to it
  during execution so that it may be read and used later during other executions, from the same context of a different one.
 -
 -- Background script execution default interval is 5 seconds.
 -
  - Each RGW instance has its own private and ephemeral ``RGW`` Lua table that is lost when the daemon restarts. Note that ``background`` context scripts will run on every instance.
 +- The maximum number of entries in the table is 100,000. Each entry has a string key a value with a combined length of no more than 1KB.
 +A Lua script will abort with an error if the number of entries or entry size exceeds these limits.
 +- The ``RGW`` Lua table uses string indeces and can store values of type: string, integer, double and boolean
 +
 +Increment/Decrement Functions
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 +Since entries in the ``RGW`` table could be accessed from multiple places at the same time we need a way
 +to atomically increment and decrement numeric values in it. For that the following functions should be used:
 +- ``RGW.increment(<key>, [value])`` would increment the value of ``key`` by ``value`` if value is provided or by 1 if not
 +- ``RGW.decrement(<key>, [value])`` would decrement the value of ``key`` by ``value`` if value is provided or by 1 if not
 +- if the value of ``key`` is not numeric, the execution of the script would fail
 +- if we try to increment or decrement by non-numeric values, the execution of the script would fail
  
 -- The maximum number of entries in the table is 100,000. Each entry has a key and string value with a combined length of no more than 1KB. 
 -  A Lua script will abort with an error if the number of entries or entry size exceeds these limits.
  
+ Tracing
+ ~~~~~~~
+ Tracing functions can be used only in `postRequest` context.
+ - ``Request.Trace.SetAttribute()`` - sets the attribute for the request's trace.
+   Takes two arguments. The first is the `key`, which should be a string. The second is the value, which can either be a string or a number.
+   Using the attribute, you can locate specific traces.
+ - ``Request.Trace.AddEvent()`` - adds an event to the first span of the request's trace
+   An event is defined by event name, event time, and zero or more event attributes.
+   Therefore, the function accepts one or two arguments. A string containing the event name should be the first argument, followed by the event attributes, which is optional for events without attributes.
+   An event's attributes must be a table of strings.
  Lua Code Samples
  ----------------
  - Print information on source and destination objects in case of copy:
Simple merge
index 0e3214211ff92e08ed598c393989096d0fa71eac,a2430313719d15f1d96783bdd1d36a10f7890880..eeca2a09267a6ecc871ae7a365921453448d4ef6
@@@ -856,308 -850,53 +860,355 @@@ TEST(TestRGWLuaBackground, MultipleStar
    lua_background.start();
    std::this_thread::sleep_for(wait_time);
    // should be a change in len
 -  EXPECT_GT(lua_background.get_table_value("hello").size(), value_len);
 +  EXPECT_GT(get_table_value<std::string>(lua_background, "hello").size(), value_len);
 +}
 +
 +TEST(TestRGWLuaBackground, TableValues)
 +{
 +  TestBackground lua_background("");
 +
 +  const std::string request_script = R"(
 +    RGW["key1"] = "string value"
 +    RGW["key2"] = 42
 +    RGW["key3"] = 42.2
 +    RGW["key4"] = true
 +  )";
 +
 +  DEFINE_REQ_STATE;
 +
 +  const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_EQ(rc, 0);
 +  EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "string value");
 +  EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42);
 +  EXPECT_EQ(get_table_value<double>(lua_background, "key3"), 42.2);
 +  EXPECT_TRUE(get_table_value<bool>(lua_background, "key4"));
 +}
 +
 +TEST(TestRGWLuaBackground, TablePersist)
 +{
 +  TestBackground lua_background("");
 +
 +  std::string request_script = R"(
 +    RGW["key1"] = "string value"
 +    RGW["key2"] = 42
 +  )";
 +
 +  DEFINE_REQ_STATE;
 +
 +  auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_EQ(rc, 0);
 +  EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "string value");
 +  EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42);
 +  
 +  request_script = R"(
 +    RGW["key3"] = RGW["key1"]
 +    RGW["key4"] = RGW["key2"]
 +  )";
 +  
 +  rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_EQ(rc, 0);
 +  EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "string value");
 +  EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42);
 +  EXPECT_EQ(get_table_value<std::string>(lua_background, "key3"), "string value");
 +  EXPECT_EQ(get_table_value<long long int>(lua_background, "key4"), 42);
 +}
 +
 +TEST(TestRGWLuaBackground, TableValuesFromRequest)
 +{
 +  TestBackground lua_background("");
 +  lua_background.start();
 +
 +  const std::string request_script = R"(
 +    RGW["key1"] = Request.Response.RGWCode
 +    RGW["key2"] = Request.Response.Message
 +    RGW["key3"] = Request.Response.RGWCode*0.1
 +    RGW["key4"] = Request.Tags["key1"] == Request.Tags["key2"] 
 +  )";
 +
 +  DEFINE_REQ_STATE;
 +  s.tagset.add_tag("key1", "val1");
 +  s.tagset.add_tag("key2", "val1");
 +  s.err.ret = -99;
 +  s.err.message = "hi";
 +
 +  const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_EQ(rc, 0);
 +  EXPECT_EQ(get_table_value<long long int>(lua_background, "key1"), -99);
 +  EXPECT_EQ(get_table_value<std::string>(lua_background, "key2"), "hi");
 +  EXPECT_EQ(get_table_value<double>(lua_background, "key3"), -9.9);
 +  EXPECT_EQ(get_table_value<bool>(lua_background, "key4"), true);
 +}
 +
 +TEST(TestRGWLuaBackground, TableInvalidValue)
 +{
 +  TestBackground lua_background("");
 +  lua_background.start();
 +
 +  const std::string request_script = R"(
 +    RGW["key1"] = "val1"
 +    RGW["key2"] = 42
 +    RGW["key3"] = 42.2
 +    RGW["key4"] = true
 +    RGW["key5"] = Request.Tags
 +  )";
 +
 +  DEFINE_REQ_STATE;
 +  s.tagset.add_tag("key1", "val1");
 +  s.tagset.add_tag("key2", "val2");
 +
 +  const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_NE(rc, 0);
 +  EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "val1");
 +  EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42);
 +  EXPECT_EQ(get_table_value<double>(lua_background, "key3"), 42.2);
 +  EXPECT_EQ(get_table_value<bool>(lua_background, "key4"), true);
 +}
 +
 +TEST(TestRGWLuaBackground, TableErase)
 +{
 +  TestBackground lua_background("");
 +
 +  std::string request_script = R"(
 +    RGW["size"] = 0
 +    RGW["key1"] = "string value"
 +    RGW["key2"] = 42
 +    RGW["key3"] = "another string value"
 +    RGW["size"] = #RGW
 +  )";
 +
 +  DEFINE_REQ_STATE;
 +
 +  auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_EQ(rc, 0);
 +  EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "string value");
 +  EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42);
 +  EXPECT_EQ(get_table_value<std::string>(lua_background, "key3"), "another string value");
 +  EXPECT_EQ(get_table_value<long long int>(lua_background, "size"), 4);
 +  
 +  request_script = R"(
 +    -- erase key1
 +    RGW["key1"] = nil
 +    -- following should be a no op
 +    RGW["key4"] = nil
 +    RGW["size"] = #RGW
 +  )";
 +  
 +  rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_EQ(rc, 0);
 +  EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "");
 +  EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42);
 +  EXPECT_EQ(get_table_value<std::string>(lua_background, "key3"), "another string value");
 +  EXPECT_EQ(get_table_value<long long int>(lua_background, "size"), 3);
 +}
 +
 +TEST(TestRGWLuaBackground, TableIterate)
 +{
 +  TestBackground lua_background("");
 +
 +  const std::string request_script = R"(
 +    RGW["key1"] = "string value"
 +    RGW["key2"] = 42
 +    RGW["key3"] = 42.2
 +    RGW["key4"] = true
 +    RGW["size"] = 0
 +    for k, v in pairs(RGW) do
 +      RGW["size"] = RGW["size"] + 1
 +    end
 +  )";
 +
 +  DEFINE_REQ_STATE;
 +
 +  const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_EQ(rc, 0);
 +  EXPECT_EQ(get_table_value<std::string>(lua_background, "key1"), "string value");
 +  EXPECT_EQ(get_table_value<long long int>(lua_background, "key2"), 42);
 +  EXPECT_EQ(get_table_value<double>(lua_background, "key3"), 42.2);
 +  EXPECT_TRUE(get_table_value<bool>(lua_background, "key4"));
 +  EXPECT_EQ(get_table_value<long long int>(lua_background, "size"), 5);
 +}
 +
 +TEST(TestRGWLuaBackground, TableIncrement)
 +{
 +  TestBackground lua_background("");
 +
 +  const std::string request_script = R"(
 +    RGW["key1"] = 42
 +    RGW["key2"] = 42.2
 +    RGW.increment("key1")
 +    assert(RGW["key1"] == 43)
 +    RGW.increment("key2")
 +    assert(RGW["key2"] == 43.2)
 +  )";
 +
 +  DEFINE_REQ_STATE;
 +
 +  const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_EQ(rc, 0);
 +}
 +
 +TEST(TestRGWLuaBackground, TableIncrementBy)
 +{
 +  TestBackground lua_background("");
 +
 +  const std::string request_script = R"(
 +    RGW["key1"] = 42
 +    RGW["key2"] = 42.2
 +    RGW.increment("key1", 10)
 +    assert(RGW["key1"] == 52)
 +    RGW.increment("key2", 10)
 +    assert(RGW["key2"] == 52.2)
 +    RGW.increment("key1", 0.2)
 +    assert(RGW["key1"] == 52.2)
 +  )";
 +
 +  DEFINE_REQ_STATE;
 +
 +  const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_EQ(rc, 0);
 +}
 +
 +TEST(TestRGWLuaBackground, TableDecrement)
 +{
 +  TestBackground lua_background("");
 +
 +  const std::string request_script = R"(
 +    RGW["key1"] = 42
 +    RGW["key2"] = 42.2
 +    RGW.decrement("key1")
 +    assert(RGW["key1"] == 41)
 +    RGW.decrement("key2")
 +    assert(RGW["key2"] == 41.2)
 +  )";
 +
 +  DEFINE_REQ_STATE;
 +
 +  const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_EQ(rc, 0);
 +}
 +
 +TEST(TestRGWLuaBackground, TableDecrementBy)
 +{
 +  TestBackground lua_background("");
 +
 +  const std::string request_script = R"(
 +    RGW["key1"] = 42
 +    RGW["key2"] = 42.2
 +    RGW.decrement("key1", 10)
 +    assert(RGW["key1"] == 32)
 +    RGW.decrement("key2", 10)
 +    assert(RGW["key2"] == 32.2)
 +    RGW.decrement("key1", 0.8)
 +    assert(RGW["key1"] == 31.2)
 +  )";
 +
 +  DEFINE_REQ_STATE;
 +
 +  const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_EQ(rc, 0);
 +}
 +
 +TEST(TestRGWLuaBackground, TableIncrementValueError)
 +{
 +  TestBackground lua_background("");
 +
 +  std::string request_script = R"(
 +    -- cannot increment string values
 +    RGW["key1"] = "hello"
 +    RGW.increment("key1")
 +  )";
 +
 +  DEFINE_REQ_STATE;
 +
 +  auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_NE(rc, 0);
 +  
 +  request_script = R"(
 +    -- cannot increment bool values
 +    RGW["key1"] = true
 +    RGW.increment("key1")
 +  )";
 +
 +  rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_NE(rc, 0);
 +  
 +  request_script = R"(
 +    -- cannot increment by string values
 +    RGW["key1"] = 99
 +    RGW.increment("key1", "kaboom")
 +  )";
 +
 +  rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_NE(rc, 0);
 +}
 +
 +TEST(TestRGWLuaBackground, TableIncrementError)
 +{
 +  TestBackground lua_background("");
 +
 +  std::string request_script = R"(
 +    -- missing argument
 +    RGW["key1"] = 11
 +    RGW.increment()
 +  )";
 +
 +  DEFINE_REQ_STATE;
 +
 +  auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_NE(rc, 0);
 +  
 +  request_script = R"(
 +    -- used as settable field
 +    RGW.increment = 11
 +  )";
 +
 +  rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script, &lua_background);
 +  ASSERT_NE(rc, 0);
  }
  
+ TEST(TestRGWLua, TracingSetAttribute)
+ {
+   const std::string script = R"(
+     Request.Trace.SetAttribute("str-attr", "value")
+     Request.Trace.SetAttribute("int-attr", 42)
+     Request.Trace.SetAttribute("double-attr", 42.5)
+   )";
+   DEFINE_REQ_STATE;
+   INIT_TRACE;
+   const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
+   ASSERT_EQ(rc, 0);
+ }
+ TEST(TestRGWLua, TracingSetBadAttribute)
+ {
+   const std::string script = R"(
+     Request.Trace.SetAttribute("attr", nil)
+   )";
+   DEFINE_REQ_STATE;
+   INIT_TRACE;
+   const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
+   #ifdef HAVE_JAEGER
+    ASSERT_NE(rc, 0);
+   #else
+    ASSERT_EQ(rc, 0);
+   #endif
+ }
+ TEST(TestRGWLua, TracingAddEvent)
+ {
+   const std::string script = R"(
+     event_attrs = {}
+     event_attrs["x"] = "value-x"
+     event_attrs[42] = 42
+     event_attrs[42.5] = 42.5
+     event_attrs["y"] = "value-y"
+     Request.Trace.AddEvent("my_event", event_attrs)
+   )";
+   DEFINE_REQ_STATE;
+   INIT_TRACE;
+   const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
+   ASSERT_EQ(rc, 0);
+ }