Skip to content

Commit 5a82b90

Browse files
authored
feat: support *_metric ABI(s) (#148)
1 parent b1d5575 commit 5a82b90

11 files changed

+305
-17
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ t/servroot
1212
node_modules/
1313
t/testdata/rust/*/target
1414
utils/reindex
15+
.idea/

gen_wasm_host_api.py

+43-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/env python
1+
#!/usr/bin/env python3
22
# Copyright 2022 Shenzhen ZhiLiu Technology Co., Ltd.
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,8 +18,8 @@
1818
import sys
1919
from string import Template
2020

21+
MAX_WASM_API_ARG = 12
2122

22-
max_wasm_api_arg = 12
2323
header = """/*
2424
* Copyright 2022 Shenzhen ZhiLiu Technology Co., Ltd.
2525
*
@@ -74,10 +74,9 @@
7474
#endif
7575
"""
7676

77-
78-
def predefined_macro(vm):
77+
def generate_wasm_runtime_struct(vm):
7978
if vm == "wasmtime":
80-
vm_def = """
79+
return """
8180
#define DEFINE_WASM_API(NAME, ARG_CHECK) \\
8281
static wasm_trap_t* wasmtime_##NAME( \\
8382
void *env, \\
@@ -105,7 +104,7 @@ def predefined_macro(vm):
105104
106105
"""
107106
elif vm == "wasmedge":
108-
vm_def = """
107+
return """
109108
#define DEFINE_WASM_API(NAME, ARG_CHECK) \\
110109
static WasmEdge_Result wasmedge_##NAME( \\
111110
void *Data, \\
@@ -130,7 +129,10 @@ def predefined_macro(vm):
130129
131130
"""
132131

133-
for i in range(max_wasm_api_arg + 1):
132+
def predefined_macro(vm):
133+
vm_def = generate_wasm_runtime_struct(vm)
134+
135+
for i in range(MAX_WASM_API_ARG + 1):
134136
if i == 0:
135137
void_def = """
136138
#define DEFINE_WASM_NAME_ARG_VOID \\
@@ -164,8 +166,29 @@ def predefined_macro(vm):
164166
vm_def += " int32_t p%d = WasmEdge_ValueGetI32(In[%d]); \\\n" % (j, j)
165167
param_s = ", ".join('p' + str(j) for j in range(i))
166168
vm_def += " int32_t res = NAME(%s);\n" % (param_s)
167-
return vm_def
168169

170+
if vm == "wasmtime":
171+
vm_def += r'''
172+
#define DEFINE_WASM_NAME_ARG_I32_I64 \
173+
2, { \
174+
WASM_I32, WASM_I64, }
175+
#define DEFINE_WASM_API_ARG_CHECK_I32_I64(NAME) \
176+
int32_t p0 = args[0].of.i32; \
177+
int64_t p1 = args[1].of.i64; \
178+
int32_t res = NAME(p0, p1);
179+
'''
180+
elif vm == "wasmedge":
181+
vm_def += r'''
182+
#define DEFINE_WASM_NAME_ARG_I32_I64 \
183+
2, { \
184+
WasmEdge_ValType_I32, WasmEdge_ValType_I64, }
185+
#define DEFINE_WASM_API_ARG_CHECK_I32_I64(NAME) \
186+
int32_t p0 = WasmEdge_ValueGetI32(In[0]); \
187+
int64_t p1 = WasmEdge_ValueGetI64(In[1]); \
188+
int32_t res = NAME(p0, p1);
189+
'''
190+
191+
return vm_def
169192

170193
def get_host_apis(src_dir):
171194
apis = []
@@ -180,24 +203,25 @@ def get_host_apis(src_dir):
180203
name = m.group(1)
181204
elif line[0] == '{' and matching:
182205
matching = False
183-
n_param = len(api.split(','))
206+
api_list = api.split(',')
207+
n_param = len(api_list)
184208
if "(void)" in api:
185209
n_param -= 1
186210
apis.append({
187211
"name": name,
188-
"n_param": n_param
212+
"n_param": n_param,
213+
"raw_func": api
189214
})
190215
api = ""
191216
if matching:
192217
api += line.rstrip()
193218
return apis
194219

195-
196220
if __name__ == '__main__':
197221
host_api_def = ""
198222
api_def = ""
199223
name_def = ""
200-
for i in range(max_wasm_api_arg + 1):
224+
for i in range(MAX_WASM_API_ARG + 1):
201225
if i == 0:
202226
host_api_def += "#define DEFINE_WASM_API_ARG_VOID void\n"
203227
else:
@@ -212,6 +236,9 @@ def get_host_apis(src_dir):
212236
param_s += ", "
213237
param_s += "int32_t"
214238
host_api_def += "#define DEFINE_WASM_API_ARG_%s%s\n" % (param_suffix, param_s)
239+
240+
host_api_def += """#define DEFINE_WASM_API_ARG_I32_I64 \\\n int32_t, int64_t"""
241+
215242
host_api_def += "\n\n"
216243

217244
src_dir = sys.argv[1]
@@ -222,6 +249,8 @@ def get_host_apis(src_dir):
222249
n_param = api["n_param"]
223250
if n_param == 0:
224251
param_suffix = "VOID"
252+
elif n_param == 2 and "int64_t" in api["raw_func"]:
253+
param_suffix = "I32_I64"
225254
else:
226255
param_suffix = "I32_%d" % n_param
227256

@@ -249,7 +278,7 @@ def get_host_apis(src_dir):
249278
vm_header="#include <wasmtime.h>",
250279
vm_api_header_name="NGX_HTTP_WASM_API_WASMTIME_H",
251280
wasm_api_def=wasmtime_def,
252-
max_wasm_api_arg=max_wasm_api_arg,
281+
max_wasm_api_arg=MAX_WASM_API_ARG,
253282
))
254283

255284
wasmedge_def = predefined_macro("wasmedge")
@@ -261,5 +290,5 @@ def get_host_apis(src_dir):
261290
vm_header="#include <wasmedge/wasmedge.h>",
262291
vm_api_header_name="NGX_HTTP_WASM_API_WASMEDGE_H",
263292
wasm_api_def=wasmedge_def,
264-
max_wasm_api_arg=max_wasm_api_arg,
293+
max_wasm_api_arg=MAX_WASM_API_ARG,
265294
))

install-wasmedge.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ if echo "int main(void) {}" | gcc -o /dev/null -v -x c - &> /dev/stdout| grep co
2020
exit 0
2121
fi
2222

23-
curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash -s -- -e none -p ./wasmedge -v 0.10.0
23+
curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.10.0/utils/install.sh | bash -s -- -e none -p ./wasmedge -v 0.10.0

proxy_wasm_abi.md

+35-1
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,40 @@ We only implement `proxy_send_local_response` as an alias because proxy-wasm-go-
345345
* returns:
346346
- `i32 (proxy_result_t) call_result`
347347

348-
Dispatch a HTTP call to upstream (`upstream_name_data`, `upstream_name_size`). Once the response is
348+
Dispatch an HTTP call to upstream (`upstream_name_data`, `upstream_name_size`). Once the response is
349349
returned to the host, `proxy_on_http_call_response` will be called with a unique call identifier
350350
(`return_callout_id`).
351+
352+
## metric extensions
353+
354+
### `proxy_define_metric`
355+
356+
* params:
357+
- `i32 (proxy_metric_type_t) metric_type`
358+
- `i32 (const char*) name_ptr`
359+
- `i32 (size_t) name_size`
360+
- `i32 (uint32_t*) metric_id`
361+
* returns:
362+
- `i32 (proxy_result_t) call_result`
363+
364+
### `proxy_increment_metric`
365+
366+
* params:
367+
- `i32 (uint32_t) metric_id`
368+
- `i64 (int64_t) offset`
369+
* returns:
370+
- `i32 (proxy_result_t) call_result`
371+
372+
### `proxy_record_metric`
373+
374+
* Params:
375+
- `i32 (uint32_t) metric_id`
376+
- `i64 (uint64_t) value`
377+
* returns:
378+
- `i32 (proxy_result_t) call_result`
379+
380+
### `proxy_get_metric`
381+
382+
* Params:
383+
- `i32 (uint32_t) metric_id`
384+
- `i64 (uint64_t*) result`

src/http/ngx_http_wasm_api.c

+25
Original file line numberDiff line numberDiff line change
@@ -1789,3 +1789,28 @@ proxy_call_foreign_function(int32_t fn_data, int32_t fn_size,
17891789
{
17901790
return PROXY_RESULT_UNIMPLEMENTED;
17911791
}
1792+
1793+
int32_t
1794+
proxy_define_metric(int32_t type, int32_t name_data, int32_t name_size,
1795+
int32_t result)
1796+
{
1797+
return PROXY_RESULT_OK;
1798+
}
1799+
1800+
int32_t
1801+
proxy_increment_metric(int32_t metric_id, int64_t offset)
1802+
{
1803+
return PROXY_RESULT_OK;
1804+
}
1805+
1806+
int32_t
1807+
proxy_record_metric(int32_t metric_id, int64_t value)
1808+
{
1809+
return PROXY_RESULT_OK;
1810+
}
1811+
1812+
int32_t
1813+
proxy_get_metric(int32_t metric_id, int64_t result)
1814+
{
1815+
return PROXY_RESULT_OK;
1816+
}

src/http/ngx_http_wasm_api_def.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
#define DEFINE_WASM_API_ARG_I32_12 \
5353
int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, \
5454
int32_t, int32_t, int32_t, int32_t
55-
55+
#define DEFINE_WASM_API_ARG_I32_I64 \
56+
int32_t, int64_t
5657

5758
int32_t proxy_set_effective_context(DEFINE_WASM_API_ARG_I32_1);
5859
int32_t proxy_get_property(DEFINE_WASM_API_ARG_I32_4);
@@ -91,6 +92,10 @@ int32_t proxy_grpc_close(DEFINE_WASM_API_ARG_I32_1);
9192
int32_t proxy_get_status(DEFINE_WASM_API_ARG_I32_3);
9293
int32_t proxy_done(DEFINE_WASM_API_ARG_VOID);
9394
int32_t proxy_call_foreign_function(DEFINE_WASM_API_ARG_I32_6);
95+
int32_t proxy_define_metric(DEFINE_WASM_API_ARG_I32_4);
96+
int32_t proxy_increment_metric(DEFINE_WASM_API_ARG_I32_I64);
97+
int32_t proxy_record_metric(DEFINE_WASM_API_ARG_I32_I64);
98+
int32_t proxy_get_metric(DEFINE_WASM_API_ARG_I32_I64);
9499

95100

96101

src/http/ngx_http_wasm_api_wasmedge.h

+20
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,14 @@ typedef struct {
219219
int32_t p11 = WasmEdge_ValueGetI32(In[11]); \
220220
int32_t res = NAME(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
221221

222+
#define DEFINE_WASM_NAME_ARG_I32_I64 \
223+
2, { \
224+
WasmEdge_ValType_I32, WasmEdge_ValType_I64, }
225+
#define DEFINE_WASM_API_ARG_CHECK_I32_I64(NAME) \
226+
int32_t p0 = WasmEdge_ValueGetI32(In[0]); \
227+
int64_t p1 = WasmEdge_ValueGetI64(In[1]); \
228+
int32_t res = NAME(p0, p1);
229+
222230
DEFINE_WASM_API(proxy_set_effective_context,
223231
DEFINE_WASM_API_ARG_CHECK_I32_1(proxy_set_effective_context))
224232
DEFINE_WASM_API(proxy_get_property,
@@ -293,6 +301,14 @@ DEFINE_WASM_API(proxy_done,
293301
DEFINE_WASM_API_ARG_CHECK_VOID(proxy_done))
294302
DEFINE_WASM_API(proxy_call_foreign_function,
295303
DEFINE_WASM_API_ARG_CHECK_I32_6(proxy_call_foreign_function))
304+
DEFINE_WASM_API(proxy_define_metric,
305+
DEFINE_WASM_API_ARG_CHECK_I32_4(proxy_define_metric))
306+
DEFINE_WASM_API(proxy_increment_metric,
307+
DEFINE_WASM_API_ARG_CHECK_I32_I64(proxy_increment_metric))
308+
DEFINE_WASM_API(proxy_record_metric,
309+
DEFINE_WASM_API_ARG_CHECK_I32_I64(proxy_record_metric))
310+
DEFINE_WASM_API(proxy_get_metric,
311+
DEFINE_WASM_API_ARG_CHECK_I32_I64(proxy_get_metric))
296312

297313
static ngx_wasm_wasmedge_host_api_t host_apis[] = {
298314
DEFINE_WASM_NAME(proxy_set_effective_context, DEFINE_WASM_NAME_ARG_I32_1)
@@ -332,6 +348,10 @@ static ngx_wasm_wasmedge_host_api_t host_apis[] = {
332348
DEFINE_WASM_NAME(proxy_get_status, DEFINE_WASM_NAME_ARG_I32_3)
333349
DEFINE_WASM_NAME(proxy_done, DEFINE_WASM_NAME_ARG_VOID)
334350
DEFINE_WASM_NAME(proxy_call_foreign_function, DEFINE_WASM_NAME_ARG_I32_6)
351+
DEFINE_WASM_NAME(proxy_define_metric, DEFINE_WASM_NAME_ARG_I32_4)
352+
DEFINE_WASM_NAME(proxy_increment_metric, DEFINE_WASM_NAME_ARG_I32_I64)
353+
DEFINE_WASM_NAME(proxy_record_metric, DEFINE_WASM_NAME_ARG_I32_I64)
354+
DEFINE_WASM_NAME(proxy_get_metric, DEFINE_WASM_NAME_ARG_I32_I64)
335355
{ ngx_null_string, NULL, 0, {} }
336356
};
337357

src/http/ngx_http_wasm_api_wasmtime.h

+20
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,14 @@ typedef struct {
222222
int32_t p11 = args[11].of.i32; \
223223
int32_t res = NAME(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
224224

225+
#define DEFINE_WASM_NAME_ARG_I32_I64 \
226+
2, { \
227+
WASM_I32, WASM_I64, }
228+
#define DEFINE_WASM_API_ARG_CHECK_I32_I64(NAME) \
229+
int32_t p0 = args[0].of.i32; \
230+
int64_t p1 = args[1].of.i64; \
231+
int32_t res = NAME(p0, p1);
232+
225233
DEFINE_WASM_API(proxy_set_effective_context,
226234
DEFINE_WASM_API_ARG_CHECK_I32_1(proxy_set_effective_context))
227235
DEFINE_WASM_API(proxy_get_property,
@@ -296,6 +304,14 @@ DEFINE_WASM_API(proxy_done,
296304
DEFINE_WASM_API_ARG_CHECK_VOID(proxy_done))
297305
DEFINE_WASM_API(proxy_call_foreign_function,
298306
DEFINE_WASM_API_ARG_CHECK_I32_6(proxy_call_foreign_function))
307+
DEFINE_WASM_API(proxy_define_metric,
308+
DEFINE_WASM_API_ARG_CHECK_I32_4(proxy_define_metric))
309+
DEFINE_WASM_API(proxy_increment_metric,
310+
DEFINE_WASM_API_ARG_CHECK_I32_I64(proxy_increment_metric))
311+
DEFINE_WASM_API(proxy_record_metric,
312+
DEFINE_WASM_API_ARG_CHECK_I32_I64(proxy_record_metric))
313+
DEFINE_WASM_API(proxy_get_metric,
314+
DEFINE_WASM_API_ARG_CHECK_I32_I64(proxy_get_metric))
299315

300316
static ngx_wasm_wasmtime_host_api_t host_apis[] = {
301317
DEFINE_WASM_NAME(proxy_set_effective_context, DEFINE_WASM_NAME_ARG_I32_1)
@@ -335,6 +351,10 @@ static ngx_wasm_wasmtime_host_api_t host_apis[] = {
335351
DEFINE_WASM_NAME(proxy_get_status, DEFINE_WASM_NAME_ARG_I32_3)
336352
DEFINE_WASM_NAME(proxy_done, DEFINE_WASM_NAME_ARG_VOID)
337353
DEFINE_WASM_NAME(proxy_call_foreign_function, DEFINE_WASM_NAME_ARG_I32_6)
354+
DEFINE_WASM_NAME(proxy_define_metric, DEFINE_WASM_NAME_ARG_I32_4)
355+
DEFINE_WASM_NAME(proxy_increment_metric, DEFINE_WASM_NAME_ARG_I32_I64)
356+
DEFINE_WASM_NAME(proxy_record_metric, DEFINE_WASM_NAME_ARG_I32_I64)
357+
DEFINE_WASM_NAME(proxy_get_metric, DEFINE_WASM_NAME_ARG_I32_I64)
338358
{ ngx_null_string, NULL, 0, {} }
339359
};
340360

src/proxy_wasm/proxy_wasm_types.h

+8
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ typedef enum {
5858
} proxy_result_t;
5959

6060

61+
typedef enum {
62+
Counter = 0,
63+
Gauge = 1,
64+
Histogram = 2,
65+
Max = 2,
66+
} metric_type_t;
67+
68+
6169
typedef enum {
6270
PROXY_LOG_TRACE,
6371
PROXY_LOG_DEBUG,

t/metric.t

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Copyright 2022 Shenzhen ZhiLiu Technology Co., Ltd.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
use t::WASM 'no_plan';
16+
17+
run_tests();
18+
log_level('debug');
19+
20+
21+
__DATA__
22+
23+
=== TEST 1: load metric plugin
24+
---
25+
--- config
26+
location /t {
27+
content_by_lua_block {
28+
local wasm = require("resty.proxy-wasm")
29+
local plugin = assert(wasm.load("plugin", "t/testdata/metric/main.go.wasm"))
30+
local ctx = assert(wasm.on_configure(plugin, '{}'))
31+
assert(wasm.on_http_request_headers(ctx))
32+
}
33+
}
34+
--- request
35+
GET /t
36+
--- error_log
37+
Record success

0 commit comments

Comments
 (0)