Skip to content

feat: Add support in the request-id plugin to generate id in [0-9a-f]{32} format #8720

Description

@prastamaha

Description

Hi guys, when I'm trying to integrate apisix opentelemetry plugin with trace_id_source = x-request-id , I got following error in apisix log

2023/01/23 11:36:36 [error] 49#49: *5867 lua entry thread aborted: runtime error: bad argument #1 to '?' (invalid value)
stack traceback:
coroutine 0:
        [C]: in function 'gsub'
        ...deps/share/lua/5.1/opentelemetry/trace/exporter/otlp.lua:18: in function 'hex2bytes'
        ...deps/share/lua/5.1/opentelemetry/trace/exporter/otlp.lua:50: in function 'export_spans'
        ...are/lua/5.1/opentelemetry/trace/batch_span_processor.lua:18: in function 'process_batches'
        ...are/lua/5.1/opentelemetry/trace/batch_span_processor.lua:46: in function <...are/lua/5.1/opentelemetry/trace/batch_span_processor.lua:29>, context: ngx.timer, client: 10.224.104.5, server: 0.0.0.0:9080

After a little dive into it, turns out the value of x-request-id header must be match with regex [0-9a-f]{32} since traceId only support that pattern. and currently request-id plugin doesn't support that regex patterns.

My configurations looks like this.

# conf/config.yaml
plugins:
- request-id
- opentelemetry
plugin_attr:
  opentelemetry:
    trace_id_source: x-request-id
    resource:
      service.name: APISIX
    collector:
      address: http://jaeger.jaeger.svc.cluster.local:4318/  # OTLP receiver
# global rules to enable the plugin globally
{
  "value": {
    "plugins": {
      "request-id": {
        "header_name": "X-Request-Id",
        "algorithm": "uuid",
        "include_in_response": true
      },
      "opentelemetry": {
        "additional_attributes": [
          "route_id",
          "request_method"
        ],
        "sampler": {
          "options": {
            "root": {
              "name": "always_off"
            },
            "fraction": 0
          },
          "name": "always_on"
        }
      }
    },
    "id": "1"
  },
  "createdIndex": 15,
  "modifiedIndex": 14622,
  "key": "/apisix/global_rules/1"
}

I thought it would be nice if traceID could use the request id generated by the request-id plugin. by default the request-id plugin uses a uuid that doesn't match trace_id_source with regex [0-9a-f]{32}

As a workaround, I create the logic with serverless-pre-function plugin as request-id plugin replacement.

curl -X PUT http://127.0.0.1:9180/apisix/admin/global_rules/1 -H 'X-API-Key: edd1c9f034335f136f87ad84b625c8f1' -H 'Content-Type: application/json' \
-d '{
       "plugins": {
          "serverless-pre-function": {
            "phase": "rewrite",
            "functions" : ["return function() local headers = ngx.req.get_headers() if not headers[\"X-Request-Id\"] then local characters = {\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\"} local id = \"\" for i = 1, 32 do local index = math.random(1, #characters) id = id .. characters[index] end ngx.req.set_header(\"X-Request-Id\", id) ngx.header[\"X-Request-Id\"] = id else ngx.header[\"X-Request-Id\"] = headers[\"X-Request-Id\"] end end"]
          }
       }

Test result:

$ curl http://httpbin.kubernetestest.com/ip -sI                       

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 32
Connection: keep-alive
X-Request-Id: 943ee4e49cdcfa9a69521123978d0f3e
Date: Mon, 23 Jan 2023 14:47:20 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.1.0

With this, I propose to add above lua code in the request-id plugin as a new algorithm.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions