-
-
Save erikcw/e999e1fb438dbbb91533 to your computer and use it in GitHub Desktop.
# Dependencies | |
# nginx_lua | |
# lua uuid module (luarocks install uuid) | |
http { | |
# this will be the request id | |
map $host $request_uuid { | |
default ''; | |
} | |
log_format log_with_request_id '$remote_addr - $remote_user [$time_local] "$request" ' | |
'$status $body_bytes_sent "$http_referer" ' | |
'"$http_user_agent" "$http_x_forwarded_for" ' | |
'request_id: $request_uuid'; | |
server { | |
# your server block here ... | |
access_log /var/log/nginx.log log_with_request_id; | |
set_by_lua $request_uuid ' | |
if ngx.var.http_x_request_id == nil then | |
return uuid() | |
else | |
return ngx.var.http_x_request_id | |
end | |
'; | |
} | |
} |
Beware that $request_id generated by nginx is not a real UUID (it is not the same format).
Beware that $request_id generated by nginx is not a real UUID (it is not the same format).
That should not make a difference. UUID4 has 122 random bits (the remaining 6 are used to record the UUID version and variant, at least for the variant that LUA produces). The dashes between the hex digits are a convention, not a requirement for UUIDs; they simply delimit the 16 bytes into a groups of lengths 4, 2, 2, 2 and 6. You can 'transform' a $random_id
value into a UUID with simple text transformations (replace the 13th hex digit with 4
, update the 17th hex digit (0
, 4
, C
-> 8
; 1
, 5
, D
-> 9
; 2
, 6
, E
-> A
; 3
, 7
, F
-> B
), insert the dashes).
If all you need is a unique identifier for a request, $random_id
is going to be way faster, don't get too hung up on the difference.
Beware that $request_id generated by nginx is not a real UUID (it is not the same format).
That should not make a difference. UUID4 has 122 random bits (the remaining 6 are used to record the UUID version and variant, at least for the variant that LUA produces). The dashes between the hex digits are a convention, not a requirement for UUIDs; they simply delimit the 16 bytes into a groups of lengths 4, 2, 2, 2 and 6. You can 'transform' a
$random_id
value into a UUID with simple text transformations (replace the 13th hex digit with4
, update the 17th hex digit (0
,4
,C
->8
;1
,5
,D
->9
;2
,6
,E
->A
;3
,7
,F
->B
), insert the dashes).If all you need is a unique identifier for a request,
$random_id
is going to be way faster, don't get too hung up on the difference.
Looks like it could be implemented just with plain nginx's if
and set
statements:
# Sets $uuid variable as UUIDv4 (variant 1) converted from $request_id
set $uuid_m 4;
if ($request_id ~ '^(?<uuid_g1>[0-9a-f]{8})(?<uuid_g2>[0-9a-f]{4})(?<uuid_g3>[0-9a-f]{3})(?<uuid_n>[0-9a-f]{1})(?<uuid_g4>[0-9a-f]{3})(?<uuid_g5>[0-9a-f]{12})') {
}
if ($uuid_n = 0) {
set $uuid_n 8;
}
if ($uuid_n = 4) {
set $uuid_n 8;
}
if ($uuid_n = c) {
set $uuid_n 8;
}
if ($uuid_n = 1) {
set $uuid_n 9;
}
if ($uuid_n = 5) {
set $uuid_n 9;
}
if ($uuid_n = d) {
set $uuid_n 9;
}
if ($uuid_n = 2) {
set $uuid_n a;
}
if ($uuid_n = 6) {
set $uuid_n a;
}
if ($uuid_n = e) {
set $uuid_n a;
}
if ($uuid_n = 3) {
set $uuid_n b;
}
if ($uuid_n = 7) {
set $uuid_n b;
}
if ($uuid_n = f) {
set $uuid_n b;
}
set $uuid $uuid_g1-$uuid_g2-$uuid_m$uuid_g3-$uuid_n$uuid_g4-$uuid_g5;
map would be nice for previous answer
map $uuid_n $uuid_n {
0 8;
1 9;
2 a;
3 b;
4 8;
5 9;
6 a;
7 b;
c 8;
d 9;
e a;
f b;
}
Looks like it could be implemented just with plain nginx's if and set statements:
Your regex doesn't replace hex digit 13, you shifted digit 13-31 to positions 14-32, dropping off the 32nd hex digit. Probably not a big deal if your random values are properly random.
You can use a single map to do all the work with 4 regexes (one for each group of digit 17 values):
# map $request_id, a 32 (lowercase) hex digit random value, to a valid UUID4 value, formatted in 8h-4h-4h-4h-12h format.
# replaces hex digit 13 with '4', and the upper two bits of hex digit 17 with binary '10'
map $request_id $request_uuid4 {
# <8h><4h><ignored h><3h><h digit for 0b??00><3h><12h>
"~^(?<uuid_g1>[0-9a-f]{8})(?<uuid_g2>[0-9a-f]{4})[0-9a-f](?<uuid_g3>[0-9a-f]{3})[048c](?<uuid_g4>[0-9a-f]{3})(?<uuid_g5>[0-9a-f]{12})$" "${uuid_g1}-${uuid_g2}-4${uuid_g3}-8${uuid_g4}-${uuid_g5}";
# <8h><4h><ignored h><3h><h digit for 0b??01><3h><12h>
"~^(?<uuid_g1>[0-9a-f]{8})(?<uuid_g2>[0-9a-f]{4})[0-9a-f](?<uuid_g3>[0-9a-f]{3})[159d](?<uuid_g4>[0-9a-f]{3})(?<uuid_g5>[0-9a-f]{12})$" "${uuid_g1}-${uuid_g2}-4${uuid_g3}-9${uuid_g4}-${uuid_g5}";
# <8h><4h><ignored h><3h><h digit for 0b??10><3h><12h>
"~^(?<uuid_g1>[0-9a-f]{8})(?<uuid_g2>[0-9a-f]{4})[0-9a-f](?<uuid_g3>[0-9a-f]{3})[26ae](?<uuid_g4>[0-9a-f]{3})(?<uuid_g5>[0-9a-f]{12})$" "${uuid_g1}-${uuid_g2}-4${uuid_g3}-a${uuid_g4}-${uuid_g5}";
# <8h><4h><ignored h><3h><h digit for 0b??11><3h><12h>
"~^(?<uuid_g1>[0-9a-f]{8})(?<uuid_g2>[0-9a-f]{4})[0-9a-f](?<uuid_g3>[0-9a-f]{3})[37bf](?<uuid_g4>[0-9a-f]{3})(?<uuid_g5>[0-9a-f]{12})$" "${uuid_g1}-${uuid_g2}-4${uuid_g3}-b${uuid_g4}-${uuid_g5}";
}
# use $request_uuid4 in your log directive, or in a addheader directive to send the value back in responses.
Note that NGINX 1.11.0 and up include a unique request id:
$request_id
. It's a 16-byte random value expressed in hex (so has a few bits more entropy than the UUID4 value produced by the LUA library). See the NGINX source code if you want to compare the implementation to the LUA version. 1.11.0 was released in May 2016, after this gist was created, but you no longer need LUA to provide you with a request tracking ID.