influxdb-cpp icon indicating copy to clipboard operation
influxdb-cpp copied to clipboard

Question: how can I use the API without linked calls?

Open j-e-f-f-williams opened this issue 5 years ago • 14 comments

Hello,

I have history with C and relatively new to C++ and your API is a pattern I have not seen before. I have the test app working fine with the call like: int ret = influxdb_cpp::builder() .meas("imu") .tag("track", "Home Testing") .field("ax", ax) .field("ay", ay) .field("az", az) .field("gx", gx) .field("gy", gy) .field("gz", gz) .field("yaw", yaw) .field("pitch", pitch) .field("roll", roll) .field("temperature", temperature) .field("pressure", pressure) .field("altitude", altitude) .timestamp( std::chrono::duration_cast<std::chrono::nanoseconds>(clock.now().time_since_epoch()).count() ) .post_http(si, &resp);

but I have a thread pool that handle a queue I have created. The queue contain a generic payload for more than 1 type of measures. The fields and tags are passed in as maps in the format { tag name, tag value}

So therefore I need to iterate over the map and call .field or .tag APIs.

I can't seem to figure out a calling mechanism to support this where I create the builder and then add details to it iterating over my map(s) and then calling the post_http.

Thought I would post this here for some help. In the mean time I will dig deeper to see if I can understand the way your API works.

Thanks, Jeff

j-e-f-f-williams avatar Oct 19 '18 14:10 j-e-f-f-williams

Hi,

Great to hear from you.

Your scene and suggestion is really good.

The cue I could give you is the member variant lines_.

What chain-able call finished is to build lines_ that to be send.

Apologize for my busy working these days, otherwise I'll add this feature ASAP.

Looking forward to your reply.

Thank you, Orca

orca-zhang avatar Oct 20 '18 17:10 orca-zhang

Without even needing to look into the source for the datatypes, you could probably just use cpp's auto feature. In pseudocode, something along the lines of

auto& m = influxdb_cpp::builder().meas("imu").tag("track", "Home Testing");
foreach key, value in std::map {
    m = m.field(key, value);
}
...
m.post_http(si, &resp);

If you need a separate map for tags, you should create an additional loop before the fields loop as well.

jha avatar Dec 21 '18 21:12 jha

Without even needing to look into the source for the datatypes, you could probably just use cpp's auto feature. In pseudocode, something along the lines of

auto& m = influxdb_cpp::builder().meas("imu").tag("track", "Home Testing");
foreach key, value in std::map {
    m = m.field(key, value);
}
...
m.post_http(si, &resp);

If you need a separate map for tags, you should create an additional loop before the fields loop as well.

I followed your suggestion, but I got an error message like this.

error: use of deleted function 'influxdb_cpp::detail::tag_caller& influxdb_cpp::detail::tag_caller::operator=(const influxdb_cpp::detail::tag_caller&)'

Could you help me?

JBongJ avatar May 22 '19 06:05 JBongJ

Without even needing to look into the source for the datatypes, you could probably just use cpp's auto feature. In pseudocode, something along the lines of

auto& m = influxdb_cpp::builder().meas("imu").tag("track", "Home Testing");
foreach key, value in std::map {
    m = m.field(key, value);
}
...
m.post_http(si, &resp);

If you need a separate map for tags, you should create an additional loop before the fields loop as well.

I followed your suggestion, but I got an error message like this.

error: use of deleted function 'influxdb_cpp::detail::tag_caller& influxdb_cpp::detail::tag_caller::operator=(const influxdb_cpp::detail::tag_caller&)'

Could you help me?

Do some small modifications. Try the code belong, remove the assignment when setting fields would be OK.

auto& m = influxdb_cpp::builder().meas("imu").tag("track", "Home Testing");
foreach key, value in std::map {
    m.field(key, value); // notice this line please
}
...
m.post_http(si, &resp);

orca-zhang avatar May 23 '19 02:05 orca-zhang

I use the linked call like this:

     43             std::string dataId = i.first;
     44             map<std::string, int> countMap = dataIdCountMap[dataId];
     45
     46             auto& m = influxdb_cpp::builder().meas("gather")
     47                         .tag("system_name", systemName.c_str())
     48                         .tag("data_id", dataId.c_str());
     49             for (const auto& j: countMap) {
     50                 m.field(j.first, j.second);
     51             }
                     int ret = m.post_http(si, &resp);

but compile error:

error: 'struct influxdb_cpp::detail::tag_caller' has no member named 'post_http'
             int ret = m.post_http(si, &resp);
                         ^

@orca-zhang @jha Could you help me?

axiaoxin avatar Jul 08 '19 10:07 axiaoxin

I came up with a solution using std::optional (C++17). Rather messy, but it gets the job done.

void Test(influxdb_cpp::server_info& si)
{
   std::unordered_map<std::string, float> kvps;

   auto m = influxdb_cpp::builder();
   std::optional<std::reference_wrapper<std::decay_t<decltype(m.meas("").field("",""))>>> field;

   for (auto it = kvps.begin(); it != kvps.end(); ++it)
   {
      const auto& key = it->first;
      const auto& value = it->second;

      if (field.has_value())
         field = field->get().field(key.c_str(), value);
      else
         field = m.meas("imu").tag("track", "Home Testing").field(key.c_str(), value);
   }

   if (kvps.empty())
     return;

   field->get().post_http(si);
}

ghost avatar Jul 13 '19 17:07 ghost

When meas_caller will be implemented?

Andrew15381 avatar Oct 06 '19 11:10 Andrew15381

Same compilation error for me when building the following code:

 auto &m = influxdb_cpp::builder().meas("test");

    m.field("val", 10); // notice this line please
    //m.timestamp(1578569518);
    m.post_http(si, &resp);
 

error: ‘struct influxdb_cpp::detail::tag_caller’ has no member named ‘post_http’ m.post_http(si, &resp);

Any incoming fix or workaround for this issue ?

jguiban avatar Jan 09 '20 17:01 jguiban

auto &m = influxdb_cpp::builder().meas("test");
auto & f = m.field("val", 10);
f.post_http(si, &resp);

orca-zhang avatar Jan 12 '20 02:01 orca-zhang

I was having trouble with this part. To prevent using deleted references, I recommend using:

influxdb_cpp::builder builder;
auto &m = builder.meas("test");
auto & f = m.field("val", 10);
f.post_http(si, &resp);

oallaire avatar Mar 06 '20 20:03 oallaire

` auto & builder = influxdb_cpp::builder() .meas(request->measure());

    for(int i = 0; i< request->tags_size(); i++)
    {
        auto & tag = request->tags(i);
        builder.tag(tag.key(),tag.val());
    }
//!!!!!!!!!!!!!!important, becasue field use ',' but tag use ' '
auto & field_builder = (influxdb_cpp::detail::field_caller&)builder;
  
    for(int i = 0; i< request->intfs_size(); i++)
    {
        auto & intf = request->intfs(i);
        builder.field(intf.key(),intf.val());
    }
  
    for(int i = 0; i< request->boolfs_size(); i++)
    {
        auto & boolf = request->boolfs(i);
        builder.field(boolf.key(),boolf.val());
    }
    for(int i = 0; i< request->stringfs_size(); i++)
    {
        auto & stringf = request->stringfs(i);
        builder.field(stringf.key(),stringf.val());
    }
    for(int i = 0; i< request->floatfs_size(); i++)
    {
        auto & floatf = request->floatfs(i);
        builder.field(floatf.key(),floatf.val());
    } 

    std::string resp;
    int ret = field_builder
    .timestamp(request->timestamp())
    .post_http(si_, &resp);

` After tag(), typecast to field_caller is important, because tag_caller and field_caller behave differently(delim is , or blank)

sjtuzwj avatar Jan 13 '21 10:01 sjtuzwj

auto &m = influxdb_cpp::builder().meas("test");
auto & f = m.field("val", 10);
f.post_http(si, &resp);

after above, it doesn't act, can you help me?

sunnyinchina avatar Nov 05 '23 13:11 sunnyinchina

I was having trouble with this part. To prevent using deleted references, I recommend using:

influxdb_cpp::builder builder;
auto &m = builder.meas("test");
auto & f = m.field("val", 10);
f.post_http(si, &resp);

As you mentioned, one field is ok, but two or more field is wrong, how to resolve it?

sunnyinchina avatar Nov 05 '23 13:11 sunnyinchina

Hi, I have a similar need. I noticed multiple insert is supported.

influxdb_cpp::builder()
    .meas("foo")  // series 1
    .field("x", 10)

    .meas("bar")  // series 2
    .field("y", 10.3)
    .send_udp("127.0.0.1", 8091);

I hope to implement a caching mechanism to save post_http overhead For example:

class MyLogger {
    void Write2DB(...) {
        buffer
            .meas("foo")
            .tag("k", "v")
            .tag("x", "y")
            .field("x", 10)
            .field("y", 10.3, 2)
            .field("z", 10.3456)
            .field("b", !!10)
            .timestamp(1512722735522840439);
        bufferSize++;
        if (bufferSize > 10) {
            buffer.post_http(si);
            buffer = ...; // a new object
            bufferSize = 0;
        }
    }
    auto buffer = ...; // something like influxdb_cpp::builder
    int bufferSize = 0;
}

Is there any way to achieve this now?

fyr233 avatar Mar 13 '24 15:03 fyr233