From f2402a05e77c0dffe3ae1e764dab917cb482f097 Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Sat, 4 Apr 2020 14:21:36 +0800 Subject: [PATCH 01/21] adapt the new v3 protocol --- lib/skywalking/client.lua | 105 +++++------------------ lib/skywalking/management.lua | 46 ++++++++++ lib/skywalking/register.lua | 66 -------------- lib/skywalking/segment.lua | 20 ++--- lib/skywalking/segment_ref.lua | 109 ++++++------------------ lib/skywalking/segment_ref_test.lua | 50 +++++------ lib/skywalking/span.lua | 44 ++-------- lib/skywalking/span_test.lua | 42 +++++---- lib/skywalking/tracer.lua | 11 +-- lib/skywalking/tracing_context.lua | 12 +-- lib/skywalking/tracing_context_test.lua | 12 ++- lib/skywalking/util.lua | 2 +- lib/skywalking/util_test.lua | 4 +- t/segment_ref.t | 58 ++++++------- t/util.t | 53 +----------- 15 files changed, 192 insertions(+), 442 deletions(-) create mode 100644 lib/skywalking/management.lua delete mode 100644 lib/skywalking/register.lua diff --git a/lib/skywalking/client.lua b/lib/skywalking/client.lua index 0f0a292..2e7c908 100644 --- a/lib/skywalking/client.lua +++ b/lib/skywalking/client.lua @@ -33,27 +33,15 @@ function Client:startBackendTimer(backend_http_uri) check = function(premature) if not premature then - local serviceId = metadata_buffer:get('serviceId') - if (serviceId == nil or serviceId == 0) then + local instancePropertiesSubmitted = metadata_buffer:get('instancePropertiesSubmitted') + if (instancePropertiesSubmitted == nil or instancePropertiesSubmitted == false) then self:registerService(metadata_buffer, backend_http_uri) - end - - -- Register is in the async way, if register successfully, go for instance register - serviceId = metadata_buffer:get('serviceId') - if (serviceId ~= nil and serviceId ~= 0) then - local serviceInstId = metadata_buffer:get('serviceInstId') - if (serviceInstId == nil or serviceInstId == 0) then - self:registerServiceInstance(metadata_buffer, backend_http_uri) - end - end - - -- After all register successfully, begin to send trace segments - local serviceInstId = metadata_buffer:get('serviceInstId') - if (serviceInstId ~= nil and serviceInstId ~= 0) then - self:reportTraces(metadata_buffer, backend_http_uri) + else self:ping(metadata_buffer, backend_http_uri) end + self:reportTraces(metadata_buffer, backend_http_uri) + -- do the health check local ok, err = new_timer(delay, check) if not ok then @@ -79,103 +67,48 @@ function Client:registerService(metadata_buffer, backend_http_uri) local ERR = ngx.ERR local serviceName = metadata_buffer:get('serviceName') + local serviceInstanceName = metadata_buffer:get('serviceInstanceName') local cjson = require('cjson') - local serviceRegister = require("register").newServiceRegister(serviceName) - local serviceRegisterParam = cjson.encode(serviceRegister) + local reportInstance = require("register").newReportInstanceProperties(serviceName, serviceInstanceName) + local reportInstanceParam = cjson.encode(reportInstance) local http = require('resty.http') local httpc = http.new() - local res, err = httpc:request_uri(backend_http_uri .. '/v2/service/register', { + local res, err = httpc:request_uri(backend_http_uri .. '/v3/management/reportProperties', { method = "POST", - body = serviceRegisterParam, + body = reportInstanceParam, headers = { ["Content-Type"] = "application/json", }, }) if not res then - log(ERR, "Service register fails, " .. err) + log(ERR, "Instance report fails, " .. err) elseif res.status == 200 then - log(DEBUG, "Service register response = " .. res.body) - local registerResults = cjson.decode(res.body) - - for i, result in ipairs(registerResults) - do - if result.key == serviceName then - local serviceId = result.value - log(DEBUG, "Service registered, service id = " .. serviceId) - metadata_buffer:set('serviceId', serviceId) - end - end + log(DEBUG, "Instance report response = " .. res.body) + metadata_buffer:set('instancePropertiesSubmitted', true) else log(ERR, "Service register fails, response code " .. res.status) end end --- Register service instance -function Client:registerServiceInstance(metadata_buffer, backend_http_uri) - local log = ngx.log - local DEBUG = ngx.DEBUG - local ERR = ngx.ERR - - local serviceInstName = 'name:' .. metadata_buffer:get('serviceInstanceName') - metadata_buffer:set('serviceInstanceUUID', serviceInstName) - - local cjson = require('cjson') - local serviceInstanceRegister = require("register").newServiceInstanceRegister( - metadata_buffer:get('serviceId'), - serviceInstName, - ngx.now() * 1000) - local serviceInstanceRegisterParam = cjson.encode(serviceInstanceRegister) - - local http = require('resty.http') - local httpc = http.new() - local res, err = httpc:request_uri(backend_http_uri .. '/v2/instance/register', { - method = "POST", - body = serviceInstanceRegisterParam, - headers = { - ["Content-Type"] = "application/json", - }, - }) - - if err == nil then - if res.status == 200 then - log(DEBUG, "Service Instance register response = " .. res.body) - local registerResults = cjson.decode(res.body) - - for i, result in ipairs(registerResults) - do - if result.key == serviceInstName then - local serviceId = result.value - log(DEBUG, "Service Instance registered, service instance id = " .. serviceId) - metadata_buffer:set('serviceInstId', serviceId) - end - end - else - log(ERR, "Service Instance register fails, response code " .. res.status) - end - else - log(ERR, "Service Instance register fails, " .. err) - end -end - -- Ping the backend to update instance heartheat function Client:ping(metadata_buffer, backend_http_uri) local log = ngx.log local DEBUG = ngx.DEBUG local ERR = ngx.ERR + local serviceName = metadata_buffer:get('serviceName') + local serviceInstanceName = metadata_buffer:get('serviceInstanceName') + local cjson = require('cjson') - local pingPkg = require("register").newServiceInstancePingPkg( - metadata_buffer:get('serviceInstId'), - metadata_buffer:get('serviceInstanceUUID'), - ngx.now() * 1000) + local pingPkg = require("register").newServiceInstancePingPkg(serviceName, serviceInstanceName) local pingPkgParam = cjson.encode(pingPkg) local http = require('resty.http') local httpc = http.new() - local res, err = httpc:request_uri(backend_http_uri .. '/v2/instance/heartbeat', { + local res, err = httpc:request_uri(backend_http_uri .. '/v3/management/keepAlive', { method = "POST", body = pingPkgParam, headers = { @@ -208,7 +141,7 @@ function Client:reportTraces(metadata_buffer, backend_http_uri) while segment ~= nil do - local res, err = httpc:request_uri(backend_http_uri .. '/v2/segments', { + local res, err = httpc:request_uri(backend_http_uri .. '/v3/segments', { method = "POST", body = segment, headers = { diff --git a/lib/skywalking/management.lua b/lib/skywalking/management.lua new file mode 100644 index 0000000..1f590ee --- /dev/null +++ b/lib/skywalking/management.lua @@ -0,0 +1,46 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one or more +-- contributor license agreements. See the NOTICE file distributed with +-- this work for additional information regarding copyright ownership. +-- The ASF licenses this file to You under the Apache License, Version 2.0 +-- (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +local _M = {} + +-- Return Services as service register parameter +function _M.newReportInstanceProperties(serviceName, serviceInstance) + local instanceProperties = { + service = serviceName, + serviceInstance = serviceInstance, + allProperties = {} + } + + local allProperties = { + language = "Lua" + } + + instanceProperties.allProperties[#instanceProperties.allProperties + 1] = allProperties + + return instanceProperties +end + +function _M.newServiceInstancePingPkg(serviceName, serviceInstance) + local serviceInstancePingPkg = { + service = serviceName, + serviceInstance = serviceInstance, + } + + return serviceInstancePingPkg +end + +return _M diff --git a/lib/skywalking/register.lua b/lib/skywalking/register.lua deleted file mode 100644 index 8223ebc..0000000 --- a/lib/skywalking/register.lua +++ /dev/null @@ -1,66 +0,0 @@ --- --- Licensed to the Apache Software Foundation (ASF) under one or more --- contributor license agreements. See the NOTICE file distributed with --- this work for additional information regarding copyright ownership. --- The ASF licenses this file to You under the Apache License, Version 2.0 --- (the "License"); you may not use this file except in compliance with --- the License. You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- - -local _M = {} - --- Return Services as service register parameter -function _M.newServiceRegister(unRegisterServiceName) - local serv = { - services = {} - } - - local service = { - serviceName = unRegisterServiceName, - -- Field type is optional, default value is `normal` - type = 'normal' - } - - serv.services[#serv.services + 1] = service - - return serv -end - -function _M.newServiceInstanceRegister(registeredServiceId, serviceInstUUID, registerTime) - local serviceInstances = { - instances = {} - } - - local serviceInstance = { - serviceId = registeredServiceId, - instanceUUID = serviceInstUUID, - time = registerTime, - properties = {} - } - - serviceInstance.properties[#serviceInstance.properties + 1] = {key = "language", value = "Lua"} - - serviceInstances.instances[#serviceInstances.instances + 1] = serviceInstance - - return serviceInstances -end - -function _M.newServiceInstancePingPkg(registeredServiceInstId, serviceInstUUID, updateTime) - local serviceInstancePingPkg = { - serviceInstanceId = registeredServiceInstId, - time = updateTime, - serviceInstanceUUID = serviceInstUUID, - } - - return serviceInstancePingPkg -end - -return _M diff --git a/lib/skywalking/segment.lua b/lib/skywalking/segment.lua index 7842f2c..227015b 100644 --- a/lib/skywalking/segment.lua +++ b/lib/skywalking/segment.lua @@ -23,8 +23,8 @@ local _M = {} -- local Segment = { -- trace_id, -- segment_id, --- service_id, --- service_inst_id, +-- service, +-- service_instance, -- spans, -- } @@ -33,22 +33,20 @@ local _M = {} -- Following SkyWalking official trace protocol v2 -- https://github.com/apache/skywalking-data-collect-protocol/blob/master/language-agent-v2/trace.proto -- local SegmentProtocol = { --- globalTraceIds, +-- traceId, -- traceSegmentId, --- serviceId, --- serviceInstanceId, +-- service, +-- serviceInstance, -- spans, -- } -- Return SegmentProtocol function _M.transform(segment) local segmentBuilder = {} - segmentBuilder.serviceId = segment.service_id - segmentBuilder.globalTraceIds = {} - segmentBuilder.globalTraceIds[1] = {idParts = segment.trace_id} - segmentBuilder.traceSegmentId = {idParts = segment.segment_id} - segmentBuilder.serviceId = segment.service_id - segmentBuilder.serviceInstanceId = segment.service_inst_id + segmentBuilder.traceId = segment.trace_id + segmentBuilder.traceSegmentId = segment.segment_id + segmentBuilder.service = segment.service + segmentBuilder.serviceInstance = segment.service_instance segmentBuilder.spans = {} diff --git a/lib/skywalking/segment_ref.lua b/lib/skywalking/segment_ref.lua index 7f85167..751c416 100644 --- a/lib/skywalking/segment_ref.lua +++ b/lib/skywalking/segment_ref.lua @@ -31,59 +31,34 @@ local _M = {} -- trace_id, -- segment_id, -- span_id, --- network_address, --- network_address_id = 0, --- entry_service_instance_id = 0, --- parent_service_instance_id = 0, --- entry_endpoint_name, --- entry_endpoint_id = 0, --- parent_endpoint_name, --- parent_endpoint_id = 0, +-- parent_service, +-- parent_service_instance, +-- parent_endpoint, +-- address_used_at_client, -- } function _M.new() return { type = 'CROSS_PROCESS', - network_address_id = 0, - entry_service_instance_id = 0, - parent_service_instance_id = 0, - entry_endpoint_id = 0, - parent_endpoint_id = 0, } end -- Deserialize value from the propagated context and initialize the SegmentRef -function _M.fromSW6Value(value) +function _M.fromSW8Value(value) local ref = _M.new() local parts = Util.split(value, '-') - if #parts ~= 9 then + if #parts ~= 8 then return nil end - ref.trace_id = Util.formatID(decode_base64(parts[2])) - ref.segment_id = Util.formatID(decode_base64(parts[3])) + ref.trace_id = decode_base64(parts[2]) + ref.segment_id = decode_base64(parts[3]) ref.span_id = tonumber(parts[4]) - ref.parent_service_instance_id = tonumber(parts[5]) - ref.entry_service_instance_id = tonumber(parts[6]) - local peerStr = decode_base64(parts[7]) - if string.sub(peerStr, 1, 1) == '#' then - ref.network_address = string.sub(peerStr, 2) - else - ref.network_address_id = tonumber(peerStr) - end - local entryEndpointStr = decode_base64(parts[8]) - if string.sub(entryEndpointStr, 1, 1) == '#' then - ref.entry_endpoint_name = string.sub(entryEndpointStr, 2) - else - ref.entry_endpoint_id = tonumber(entryEndpointStr) - end - local parentEndpointStr = decode_base64(parts[9]) - if string.sub(parentEndpointStr, 1, 1) == '#' then - ref.parent_endpoint_name = string.sub(parentEndpointStr, 2) - else - ref.parent_endpoint_id = tonumber(parentEndpointStr) - end + ref.parent_service = decode_base64(parts[5]) + ref.parent_service_instance = decode_base64(parts[6]) + ref.parent_endpoint = decode_base64(parts[7]) + ref.address_used_at_client = decode_base64(parts[8]) return ref end @@ -91,35 +66,13 @@ end -- Return string to represent this ref. function _M.serialize(ref) local encodedRef = '1' - encodedRef = encodedRef .. '-' .. encode_base64(Util.id2String(ref.trace_id)) - encodedRef = encodedRef .. '-' .. encode_base64(Util.id2String(ref.segment_id)) + encodedRef = encodedRef .. '-' .. encode_base64(ref.trace_id) + encodedRef = encodedRef .. '-' .. encode_base64(ref.segment_id) encodedRef = encodedRef .. '-' .. ref.span_id - encodedRef = encodedRef .. '-' .. ref.parent_service_instance_id - encodedRef = encodedRef .. '-' .. ref.entry_service_instance_id - - local networkAddress - if ref.network_address_id ~= 0 then - networkAddress = ref.network_address_id .. '' - else - networkAddress = '#' .. ref.network_address - end - encodedRef = encodedRef .. '-' .. encode_base64(networkAddress) - - local entryEndpoint - if ref.entry_endpoint_id ~= 0 then - entryEndpoint = ref.entry_endpoint_id .. '' - else - entryEndpoint = '#' .. ref.entry_endpoint_name - end - encodedRef = encodedRef .. '-' .. encode_base64(entryEndpoint) - - local parentEndpoint - if ref.parent_endpoint_id ~= 0 then - parentEndpoint = ref.parent_endpoint_id .. '' - else - parentEndpoint = '#' .. ref.parent_endpoint_name - end - encodedRef = encodedRef .. '-' .. encode_base64(parentEndpoint) + encodedRef = encodedRef .. '-' .. encode_base64(ref.parent_service) + encodedRef = encodedRef .. '-' .. encode_base64(ref.parent_service_instance) + encodedRef = encodedRef .. '-' .. encode_base64(ref.parent_endpoint) + encodedRef = encodedRef .. '-' .. encode_base64(ref.address_used_at_client) return encodedRef end @@ -131,31 +84,25 @@ end -- local RefProtocol = { -- -- Constant in LUA, no cross-thread -- refType = 'CrossProcess', +-- traceId, -- parentTraceSegmentId, -- parentSpanId, --- parentServiceInstanceId, --- networkAddress, --- networkAddressId, --- entryServiceInstanceId, --- entryEndpoint, --- entryEndpointId, +-- parentService, +-- parentServiceInstance, -- parentEndpoint, --- parentEndpointId, +-- networkAddressUsedAtPeer, -- } -- Return RefProtocol function _M.transform(ref) local refBuilder = {} refBuilder.refType = 'CrossProcess' - refBuilder.parentTraceSegmentId = {idParts = ref.segment_id } + refBuilder.traceId = ref.trace_id + refBuilder.parentTraceSegmentId = ref.segment_id refBuilder.parentSpanId = ref.span_id - refBuilder.parentServiceInstanceId = ref.parent_service_instance_id - refBuilder.networkAddress = ref.network_address - refBuilder.networkAddressId = ref.network_address_id - refBuilder.entryServiceInstanceId = ref.entry_service_instance_id - refBuilder.entryEndpoint = ref.entry_endpoint_name - refBuilder.entryEndpointId = ref.entry_endpoint_id - refBuilder.parentEndpoint = ref.parent_endpoint_name - refBuilder.parentEndpointId = ref.parent_endpoint_id + refBuilder.parentService = ref.parent_service + refBuilder.parentServiceInstance = ref.parent_service_instance + refBuilder.parentEndpoint = ref.parent_endpoint + refBuilder.networkAddressUsedAtPeer = ref.address_used_at_client return refBuilder end diff --git a/lib/skywalking/segment_ref_test.lua b/lib/skywalking/segment_ref_test.lua index 72c664e..11266cc 100644 --- a/lib/skywalking/segment_ref_test.lua +++ b/lib/skywalking/segment_ref_test.lua @@ -22,49 +22,43 @@ local cjson = require("cjson") TestSegmentRef = {} -- This test is originally from ContextCarrierV2HeaderTest in the Java agent. - function TestSegmentRef:testFromSW6Value() - local ref = SegmentRef.fromSW6Value('1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz') + function TestSegmentRef:testFromSW8Value() + local ref = SegmentRef.fromSW8Value('1-My40LjU=-MS4yLjM=-4-c2VydmljZQ==-aW5zdGFuY2U=-L2FwcA==-MTI3LjAuMC4xOjgwODA=') lu.assertNotNil(ref) - lu.assertEquals(ref.trace_id, {"3", "4", "5"}) - lu.assertEquals(ref.segment_id, {"1", "2", "3"}) + lu.assertEquals(ref.trace_id, "3.4.5") + lu.assertEquals(ref.segment_id, "1.2.3") lu.assertEquals(ref.span_id, 4) - lu.assertEquals(ref.parent_service_instance_id, 1) - lu.assertEquals(ref.entry_service_instance_id, 1) - lu.assertEquals(ref.network_address, '127.0.0.1:8080') - lu.assertEquals(ref.network_address_id, 0) - lu.assertEquals(ref.entry_endpoint_name, '/portal') - lu.assertEquals(ref.entry_endpoint_id, 0) - lu.assertEquals(ref.parent_endpoint_name, nil) - lu.assertEquals(ref.parent_endpoint_id, 123) + lu.assertEquals(ref.parent_service, "service") + lu.assertEquals(ref.parent_service_instance, "instance") + lu.assertEquals(ref.parent_endpoint, '/app') + lu.assertEquals(ref.address_used_at_client, '127.0.0.1:8080') - ref = SegmentRef.fromSW6Value('1-My40LjU=-MS') + ref = SegmentRef.fromSW8Value('1-My40LjU=-MS') lu.assertNil(ref) end function TestSegmentRef:testSerialize() local ref = SegmentRef.new() - ref.trace_id = {3, 4, 5} - ref.segment_id = {1, 2, 3} + ref.trace_id = "3.4.5" + ref.segment_id = "1.2.3" ref.span_id = 4 - ref.entry_service_instance_id = 1 - ref.parent_service_instance_id = 1 - ref.network_address = "127.0.0.1:8080" - ref.entry_endpoint_name = "/portal" - ref.parent_endpoint_id = 123 + ref.parent_service = "service" + ref.parent_service_instance = "instance" + ref.parent_endpoint = "/app" + ref.address_used_at_client = "127.0.0.1:8080" - lu.assertEquals(SegmentRef.serialize(ref), '1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz') + lu.assertEquals(SegmentRef.serialize(ref), '1-My40LjU=-MS4yLjM=-4-c2VydmljZQ==-aW5zdGFuY2U=-L2FwcA==-MTI3LjAuMC4xOjgwODA=') end function TestSegmentRef:testTransform() local ref = SegmentRef.new() - ref.trace_id = {3, 4, 5} - ref.segment_id = {1, 2, 3} + ref.trace_id = "3.4.5" + ref.segment_id = "1.2.3" ref.span_id = 4 - ref.entry_service_instance_id = 1 - ref.parent_service_instance_id = 1 - ref.network_address = "127.0.0.1:8080" - ref.entry_endpoint_name = "/portal" - ref.parent_endpoint_id = 123 + ref.parent_service = "service" + ref.parent_service_instance = "instance" + ref.parent_endpoint = "/app" + ref.address_used_at_client = "127.0.0.1:8080" local refProtocol = SegmentRef.transform(ref) local inJSON = cjson.encode(refProtocol) diff --git a/lib/skywalking/span.lua b/lib/skywalking/span.lua index 6dd30ec..162abbe 100644 --- a/lib/skywalking/span.lua +++ b/lib/skywalking/span.lua @@ -19,7 +19,7 @@ local spanLayer = require("span_layer") local Util = require('util') local SegmentRef = require("segment_ref") -local CONTEXT_CARRIER_KEY = 'sw6' +local CONTEXT_CARRIER_KEY = 'sw8' local _M = {} -- local Span = { @@ -27,7 +27,6 @@ local _M = {} -- parent_span_id, -- operation_name, -- tags, --- logs, -- layer = spanLayer.NONE, -- is_entry = false, -- is_exit = false, @@ -72,7 +71,7 @@ function _M.createEntrySpan(operationName, context, parent, contextCarrier) if contextCarrier ~= nil then local propagatedContext = contextCarrier[CONTEXT_CARRIER_KEY] if propagatedContext ~= nil then - local ref = SegmentRef.fromSW6Value(propagatedContext) + local ref = SegmentRef.fromSW8Value(propagatedContext) if ref ~= nil then -- If current trace id is generated by the context, in LUA case, mostly are yes -- use the ref trace id to override it, in order to keep trace id consistently same. @@ -97,45 +96,18 @@ function _M.createExitSpan(operationName, context, parent, peer, contextCarrier) injectableRef.trace_id = context.trace_id injectableRef.segment_id = context.segment_id injectableRef.span_id = span.span_id - -- injectableRef.network_address_id wouldn't be set. Right now, there is no network_address register mechanism - injectableRef.network_address = peer - - local entryServiceInstanceId - local entryEndpointName - -- -1 represent the endpoint id doesn't exist, but it is a meaningful value. - -- Once -1 is here, the entryEndpointName will be ignored. - local entryEndpointId = -1 + injectableRef.address_used_at_client = peer + injectableRef.parent_service = context.service + injectableRef.parent_service_instance = context.service_instance local firstSpan = context.internal.first_span + local parentEndpointName if context.internal.first_ref then - local firstRef = context.internal.first_ref - injectableRef.entry_service_instance_id = firstRef.entry_service_instance_id - entryEndpointName = firstRef.entry_endpoint_name - entryEndpointId = firstRef.entry_endpoint_id - entryServiceInstanceId = firstRef.entry_service_instance_id + parentEndpointName = context.internal.first_ref.entry_endpoint_name else - injectableRef.entry_service_instance_id = context.service_inst_id - if firstSpan.is_entry then - entryEndpointId = 0 - entryEndpointName = firstSpan.operation_name - end - entryServiceInstanceId = context.service_inst_id - end - - injectableRef.entry_service_instance_id = entryServiceInstanceId - injectableRef.parent_service_instance_id = context.service_inst_id - injectableRef.entry_endpoint_name = entryEndpointName - injectableRef.entry_endpoint_id = entryEndpointId - - local parentEndpointName - local parentEndpointId = -1 - - if firstSpan.is_entry then parentEndpointName = firstSpan.operation_name - parentEndpointId = 0 end - injectableRef.parent_endpoint_name = parentEndpointName - injectableRef.parent_endpoint_id = parentEndpointId + injectableRef.parent_endpoint = parentEndpointName contextCarrier[CONTEXT_CARRIER_KEY] = SegmentRef.serialize(injectableRef) end diff --git a/lib/skywalking/span_test.lua b/lib/skywalking/span_test.lua index 56e2fd2..01863d4 100644 --- a/lib/skywalking/span_test.lua +++ b/lib/skywalking/span_test.lua @@ -22,7 +22,7 @@ local SpanLayer = require("span_layer") TestSpan = {} function TestSpan:testNewEntry() - local context = TC.new(1, 1) + local context = TC.new("service", "instance") lu.assertNotNil(context) local span1 = Span.createEntrySpan("operation_name", context, nil, nil) @@ -35,11 +35,11 @@ TestSpan = {} end function TestSpan:testNewEntryWithContextCarrier() - local context = TC.new(1, 1) + local context = TC.new("service", "instance") lu.assertNotNil(context) -- Typical header from the SkyWalking Java Agent test case - local header = {sw6='1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz'} + local header = {sw8='1-My40LjU=-MS4yLjM=-4-c2VydmljZQ==-aW5zdGFuY2U=-L2FwcA==-MTI3LjAuMC4xOjgwODA='} local span1 = Span.createEntrySpan("operation_name", context, nil, header) lu.assertNotNil(span1) @@ -48,25 +48,21 @@ TestSpan = {} lu.assertEquals(span1.layer, SpanLayer.NONE) local ref = span1.refs[1] lu.assertNotNil(ref) - lu.assertEquals(ref.trace_id, {"3", "4", "5"}) + lu.assertEquals(ref.trace_id, "3.4.5") -- Context trace id will be overrided by the ref trace id - lu.assertEquals(context.trace_id, {"3", "4", "5"}) - lu.assertEquals(ref.segment_id, {"1", "2", "3"}) + lu.assertEquals(context.trace_id, "3.4.5") + lu.assertEquals(ref.segment_id, "1.2.3") lu.assertEquals(ref.span_id, 4) - lu.assertEquals(ref.parent_service_instance_id, 1) - lu.assertEquals(ref.entry_service_instance_id, 1) - lu.assertEquals(ref.network_address, '127.0.0.1:8080') - lu.assertEquals(ref.network_address_id, 0) - lu.assertEquals(ref.entry_endpoint_name, '/portal') - lu.assertEquals(ref.entry_endpoint_id, 0) - lu.assertEquals(ref.parent_endpoint_name, nil) - lu.assertEquals(ref.parent_endpoint_id, 123) + lu.assertEquals(ref.parent_service, "service") + lu.assertEquals(ref.parent_service_instance, "instance") + lu.assertEquals(ref.address_used_at_client, '127.0.0.1:8080') + lu.assertEquals(ref.parent_endpoint, '/app') lu.assertEquals(#(context.internal.active_spans), 1) end function TestSpan:testNewExit() - local context = TC.new(1, 1) + local context = TC.new("service", "instance") lu.assertNotNil(context) local contextCarrier = {} @@ -78,11 +74,11 @@ TestSpan = {} lu.assertEquals(span1.peer, '127.0.0.1:80') lu.assertEquals(#(context.internal.active_spans), 1) - lu.assertNotNil(contextCarrier['sw6']) + lu.assertNotNil(contextCarrier['sw8']) end function TestSpan:testNew() - local context = TC.new(1, 1) + local context = TC.new("service", "instance") lu.assertNotNil(context) local span1 = Span.new("operation_name", context, nil) @@ -98,7 +94,7 @@ TestSpan = {} lu.assertNotNil(span2.start_time) -- Use new context to check again - context = TC.new(1, 1) + context = TC.new("service", "instance") lu.assertNotNil(context) span1 = Span.new("operation_name", context, nil) @@ -108,9 +104,9 @@ TestSpan = {} end function TestSpan:testProperties() - local context = TC.new(1, 1) + local context = TC.new("service", "instance") - local header = {sw6='1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz'} + local header = {sw8='1-My40LjU=-MS4yLjM=-4-c2VydmljZQ==-aW5zdGFuY2U=-L2FwcA==-MTI3LjAuMC4xOjgwODA='} local span1 = Span.createEntrySpan("operation_name", context, nil, header) Span.start(span1, 1234567) lu.assertEquals(span1.start_time, 1234567) @@ -123,13 +119,13 @@ TestSpan = {} lu.assertEquals(span1.tags[1].value, 'value1') lu.assertEquals(#span1.refs, 1) - lu.assertEquals(span1.refs[1].network_address, '127.0.0.1:8080') + lu.assertEquals(span1.refs[1].address_used_at_client, '127.0.0.1:8080') end function TestSpan:testTransform() - local context = TC.new(1, 1) + local context = TC.new("service", "instance") - local header = {sw6='1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz'} + local header = {sw8='1-My40LjU=-MS4yLjM=-4-c2VydmljZQ==-aW5zdGFuY2U=-L2FwcA==-MTI3LjAuMC4xOjgwODA='} local span1 = Span.createEntrySpan("operation_name", context, nil, header) Span.start(span1, 1234567) Span.finish(span1, 2222222) diff --git a/lib/skywalking/tracer.lua b/lib/skywalking/tracer.lua index f0a1a1e..a729dd6 100644 --- a/lib/skywalking/tracer.lua +++ b/lib/skywalking/tracer.lua @@ -25,20 +25,15 @@ function Tracer:start(upstream_name) local tracingContext local serviceName = metadata_buffer:get("serviceName") - local serviceInstId = metadata_buffer:get("serviceInstId") - local serviceId = metadata_buffer:get('serviceId') - if (serviceInstId ~= nil and serviceInstId ~= 0) then - tracingContext = TC.new(serviceId, serviceInstId) - else - tracingContext = TC.newNoOP() - end + local serviceInstanceName = metadata_buffer:get('serviceInstanceName') + tracingContext = TC.new(serviceName, serviceInstanceName) -- Constant pre-defined in SkyWalking main repo -- 84 represents Nginx local nginxComponentId = 6000 local contextCarrier = {} - contextCarrier["sw6"] = ngx.req.get_headers()["sw6"] + contextCarrier["sw8"] = ngx.req.get_headers()["sw8"] local entrySpan = TC.createEntrySpan(tracingContext, ngx.var.uri, nil, contextCarrier) Span.start(entrySpan, ngx.now() * 1000) Span.setComponentId(entrySpan, nginxComponentId) diff --git a/lib/skywalking/tracing_context.lua b/lib/skywalking/tracing_context.lua index 23ecfb0..c997481 100644 --- a/lib/skywalking/tracing_context.lua +++ b/lib/skywalking/tracing_context.lua @@ -107,16 +107,16 @@ function _M.newNoOP() return {is_noop = true} end -function _M.new(serviceId, serviceInstID) - if serviceInstID == nil then +function _M.new(serviceName, serviceInstanceName) + if serviceInstanceName == nil then return _M.newNoOP() end local tracing_context = {} tracing_context.trace_id = Util.newID() tracing_context.segment_id = tracing_context.trace_id - tracing_context.service_id = serviceId - tracing_context.service_inst_id = serviceInstID + tracing_context.service = serviceName + tracing_context.service_instance = serviceInstanceName tracing_context.internal = Internal.new() tracing_context.internal.owner = tracing_context return tracing_context @@ -160,8 +160,8 @@ function _M.drainAfterFinished(tracingContext) local segment = {} segment.trace_id = tracingContext.trace_id segment.segment_id = tracingContext.segment_id - segment.service_id = tracingContext.service_id - segment.service_inst_id = tracingContext.service_inst_id + segment.service = tracingContext.service + segment.service_instance = tracingContext.service_instance segment.spans = tracingContext.internal.finished_spans return true, segment end diff --git a/lib/skywalking/tracing_context_test.lua b/lib/skywalking/tracing_context_test.lua index c5d4420..3c22a48 100644 --- a/lib/skywalking/tracing_context_test.lua +++ b/lib/skywalking/tracing_context_test.lua @@ -22,23 +22,21 @@ local Span = require('span') TestTracingContext = {} function TestTracingContext:testNew() - local context = TC.new(1, 1) + local context = TC.new("service", "instance") lu.assertNotNil(context) - lu.assertNotNil(context.segment_id[1]) - lu.assertNotNil(context.segment_id[2]) - lu.assertNotNil(context.segment_id[3]) + lu.assertNotNil(context.segment_id) lu.assertEquals(context.trace_id, context.segment_id) end function TestTracingContext:testInternal_NextSpanSeqID() - local context = TC.new(1, 1) + local context = TC.new("service", "instance") lu.assertEquals(context.internal.nextSpanID(context.internal), 0) end function TestTracingContext:testInternal_addActive() - local context = TC.new(1, 1) + local context = TC.new("service", "instance") local mockSpan = {span_id = 0} context.internal.addActive(context.internal, mockSpan) @@ -47,7 +45,7 @@ TestTracingContext = {} end function TestTracingContext:testSpanStack() - local context = TC.new(1, 1) + local context = TC.new("service", "instance") local span1 = TC.createEntrySpan(context, 'entry_op') local span2 = TC.createExitSpan(context, "exit_op", span1, "127.0.0.1") diff --git a/lib/skywalking/util.lua b/lib/skywalking/util.lua index 18fe0ba..2ea3079 100644 --- a/lib/skywalking/util.lua +++ b/lib/skywalking/util.lua @@ -83,7 +83,7 @@ end math.randomseed(random_seed()) function _M.newID() - return {timestamp(), math.random(0, MAX_ID_PART2), math.random(0, MAX_ID_PART3)} + return timestamp() .. math.random(0, MAX_ID_PART2) .. math.random(0, MAX_ID_PART3) end -- Format a trace/segment id into an array. diff --git a/lib/skywalking/util_test.lua b/lib/skywalking/util_test.lua index 10d8170..2089fe9 100644 --- a/lib/skywalking/util_test.lua +++ b/lib/skywalking/util_test.lua @@ -22,9 +22,7 @@ TestUtil = {} function TestUtil.testNewID() local id = Util.newID() - lu.assertNotNil(id[1]) - lu.assertNotNil(id[2]) - lu.assertNotNil(id[3]) + lu.assertNotNil(id) end function TestUtil.testTimestamp() diff --git a/t/segment_ref.t b/t/segment_ref.t index 8c9f76a..34b3eab 100644 --- a/t/segment_ref.t +++ b/t/segment_ref.t @@ -20,40 +20,32 @@ run_tests; __DATA__ -=== TEST 1: fromSW6Value +=== TEST 1: fromSW8Value --- http_config eval: $::HttpConfig --- config location /t { content_by_lua_block { local SegmentRef = require('segment_ref') - local ref = SegmentRef.fromSW6Value('1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz') + local ref = SegmentRef.fromSW8Value('1-My40LjU=-MS4yLjM=-4-c2VydmljZQ==-aW5zdGFuY2U=-L2FwcA==-MTI3LjAuMC4xOjgwODA=') ngx.say(ref.trace_id) ngx.say(ref.segment_id) ngx.say(ref.span_id) - ngx.say(ref.parent_service_instance_id) - ngx.say(ref.entry_service_instance_id) - ngx.say(ref.network_address) - ngx.say(ref.network_address_id) - ngx.say(ref.entry_endpoint_name) - ngx.say(ref.entry_endpoint_id) - ngx.say(ref.parent_endpoint_name) - ngx.say(ref.parent_endpoint_id) + ngx.say(ref.parent_service) + ngx.say(ref.parent_service_instance) + ngx.say(ref.parent_endpoint) + ngx.say(ref.address_used_at_client) } } --- request GET /t --- response_body -345 -123 +3.4.5 +1.2.3 4 -1 -1 +service +instance +/app 127.0.0.1:8080 -0 -/portal -0 -nil -123 --- no_error_log [error] @@ -66,21 +58,20 @@ nil content_by_lua_block { local SegmentRef = require('segment_ref') local ref = SegmentRef.new() - ref.trace_id = {3, 4, 5} - ref.segment_id = {1, 2, 3} + ref.trace_id = "3.4.5" + ref.segment_id = "1.2.3" ref.span_id = 4 - ref.entry_service_instance_id = 1 - ref.parent_service_instance_id = 1 - ref.network_address = "127.0.0.1:8080" - ref.entry_endpoint_name = "/portal" - ref.parent_endpoint_id = 123 + ref.parent_service = "service" + ref.parent_service_instance = "instance" + ref.parent_endpoint = "/app" + ref.address_used_at_client = "127.0.0.1:8080" ngx.say(SegmentRef.serialize(ref)) } } --- request GET /t --- response_body -1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz +1-My40LjU=-MS4yLjM=-4-c2VydmljZQ==-aW5zdGFuY2U=-L2FwcA==-MTI3LjAuMC4xOjgwODA= --- no_error_log [error] @@ -95,14 +86,13 @@ GET /t local cjson = require("cjson") local ref = SegmentRef.new() - ref.trace_id = {3, 4, 5} - ref.segment_id = {1, 2, 3} + ref.trace_id = "3.4.5" + ref.segment_id = "1.2.3" ref.span_id = 4 - ref.entry_service_instance_id = 1 - ref.parent_service_instance_id = 1 - ref.network_address = "127.0.0.1:8080" - ref.entry_endpoint_name = "/portal" - ref.parent_endpoint_id = 123 + ref.parent_service = "service" + ref.parent_service_instance = "instance" + ref.parent_endpoint = "/app" + ref.address_used_at_client = "127.0.0.1:8080" local refProtocol = SegmentRef.transform(ref) local inJSON = cjson.encode(refProtocol) diff --git a/t/util.t b/t/util.t index e526e4f..64d5cfa 100644 --- a/t/util.t +++ b/t/util.t @@ -47,43 +47,13 @@ true === TEST 2: newID --- http_config eval: $::HttpConfig ---- config - location /t { - content_by_lua_block { - local util = require('util') - local new_id = util.newID() - local regex = [[^\d+$]] - ngx.say(#new_id) - for i = 1, #new_id, 1 do - local m = ngx.re.match(new_id[i], regex) - if m and tonumber(m[0]) == new_id[i] then - ngx.say(i) - end - end - } - } ---- request -GET /t ---- response_body -3 -1 -2 -3 ---- no_error_log -[error] - - - -=== TEST 3: id2String ---- http_config eval: $::HttpConfig --- config location /t { content_by_lua_block { local util = require('util') local id = util.newID() - local id_str = util.id2String(id) local regex = [[^\d+\.\d+\.\d+$]] - local m = ngx.re.match(id_str, regex) + local m = ngx.re.match(id, regex) if m then ngx.say(true) end @@ -95,24 +65,3 @@ GET /t true --- no_error_log [error] - - - -=== TEST 4: formatID ---- http_config eval: $::HttpConfig ---- config - location /t { - content_by_lua_block { - local util = require('util') - local id = util.newID() - local id_str = util.id2String(id) - local parts = util.formatID(id_str) - ngx.say(#parts) - } - } ---- request -GET /t ---- response_body -3 ---- no_error_log -[error] From 6b72c4c35694fba5b0b98316469daba6fd220658 Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Sat, 4 Apr 2020 15:33:47 +0800 Subject: [PATCH 02/21] make sure the nginx tests and logs finish --- README.md | 20 ++++++++-------- examples/nginx.conf | 37 +++++++++-------------------- lib/skywalking/client.lua | 8 +++---- lib/skywalking/management.lua | 4 ++-- lib/skywalking/span.lua | 2 +- lib/skywalking/util.lua | 22 +---------------- skywalking-nginx-lua-1.0-0.rockspec | 2 +- 7 files changed, 30 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index b7dec3d..8276ab5 100644 --- a/README.md +++ b/README.md @@ -82,20 +82,20 @@ By using the `/examples/nginx.conf`, you could start the Nginx with LUA module o Then you could 1. See the `register logs` happens on the console log. ``` -2020/02/27 09:22:06 [debug] 20676#11799235: *4 [lua] content_by_lua(nginx.conf:118):4: Service register request = {"services":[{"type":"normal","serviceName":"User Service Name"}]} -2020/02/27 09:22:06 [debug] 20676#11799235: *2 [lua] client.lua:99: registerService(): Service register response = [{"key":"User Service Name","value":1}] +2020/04/04 15:15:37 [debug] 12089#1446111: *4 [lua] content_by_lua(nginx.conf:175):4: Instance report request = {"service":"User Service Name","serviceInstance":"User Service Instance Name","properties":[{"language":"Lua"}]} +2020/04/04 15:15:37 [debug] 12089#1446111: *2 [lua] client.lua:89: registerService(): Instance report response = {} +``` -2020/02/27 09:22:06 [debug] 20676#11799235: *2 [lua] client.lua:106: registerService(): Service registered, service id = 1 -2020/02/27 09:22:06 [debug] 20676#11799235: *4 [lua] content_by_lua(nginx.conf:134):3: Service instance register request = {"instances":[{"time":1582766526928,"instanceUUID":"name:User Service Instance Name","properties":[{"key":"language","value":"Lua"}],"serviceId":1}]} -2020/02/27 09:22:06 [debug] 20676#11799235: *2 [lua] client.lua:143: registerServiceInstance(): Service Instance register response = [{"key":"name:User Service Instance Name","value":1}] -2020/02/27 09:22:06 [debug] 20676#11799235: *2 [lua] client.lua:150: registerServiceInstance(): Service Instance registered, service instance id = 1 +1. See the `heartbeat logs` happens after the `register logs` +``` +2020/04/04 15:15:40 [debug] 12089#1446111: *4 [lua] content_by_lua(nginx.conf:188):3: KeepAlive request = {"service":"User Service Name","serviceInstance":"User Service Instance Name"} ``` -2. Access the `http://127.0.0.1:8080/ingress` then you could see the tracing happens and reported spans in the logs. +1. Access the `http://127.0.0.1:8080/ingress` then you could see the tracing happens and reported spans in the logs. ``` -2020/02/27 09:22:10 [debug] 20676#11799235: *9 [lua] tracer.lua:91: prepareForReport(): segment = {"spans":[{"operationName":"\/tier2\/lb","startTime":1582766530125,"endTime":1582766530139,"spanType":"Exit","spanId":1,"isError":false,"parentSpanId":0,"componentId":6000,"peer":"User Service Name-nginx:upstream_ip:port","spanLayer":"HTTP"},{"operationName":"\/tier2\/lb","startTime":1582766530125,"tags":[{"key":"http.method","value":"GET"},{"key":"http.params","value":"http:\/\/127.0.0.1\/tier2\/lb"}],"endTime":1582766530139,"spanType":"Entry","spanId":0,"isError":false,"parentSpanId":-1,"componentId":6000,"refs":[{"parentTraceSegmentId":{"idParts":[1582766530044,794206293,69887]},"parentEndpointId":0,"entryEndpointId":0,"parentServiceInstanceId":1,"parentEndpoint":"\/ingress","networkAddress":"#User Service Name-nginx:upstream_ip:port","parentSpanId":1,"entryServiceInstanceId":1,"networkAddressId":0,"entryEndpoint":"\/ingress"}],"spanLayer":"HTTP"}],"serviceInstanceId":1,"serviceId":1,"traceSegmentId":{"idParts":[1582766530052,794206293,69887]},"globalTraceIds":[{"idParts":[1582766530044,794206293,69887]}]} -2020/02/27 09:22:10 [debug] 20676#11799235: *9 [lua] tracer.lua:95: prepareForReport(): segment buffer size = 1 -2020/02/27 09:22:10 [debug] 20676#11799235: *6 [lua] tracer.lua:91: prepareForReport(): segment = {"spans":[{"operationName":"\/ingress","startTime":1582766530114,"endTime":1582766530140,"spanType":"Exit","spanId":1,"isError":false,"parentSpanId":0,"componentId":6000,"peer":"User Service Name-nginx:upstream_ip:port","spanLayer":"HTTP"},{"operationName":"\/ingress","startTime":1582766530114,"tags":[{"key":"http.method","value":"GET"},{"key":"http.params","value":"http:\/\/127.0.0.1\/ingress"}],"endTime":1582766530140,"spanType":"Entry","spanId":0,"parentSpanId":-1,"isError":false,"spanLayer":"HTTP","componentId":6000}],"serviceInstanceId":1,"serviceId":1,"traceSegmentId":{"idParts":[1582766530044,794206293,69887]},"globalTraceIds":[{"idParts":[1582766530044,794206293,69887]}]} +2020/04/04 15:15:46 [debug] 12089#1446111: *11 [lua] tracer.lua:83: prepareForReport(): segment = {"traceId":"1585984546953.410917649.45972","serviceInstance":"User Service Instance Name","spans":[{"operationName":"\/tier2\/lb","startTime":1585984546967,"endTime":1585984546968,"spanType":"Exit","spanId":1,"isError":false,"parentSpanId":0,"componentId":6000,"peer":"backend service","spanLayer":"Http"},{"operationName":"\/tier2\/lb","startTime":1585984546967,"tags":[{"key":"http.method","value":"GET"},{"key":"http.params","value":"http:\/\/127.0.0.1\/tier2\/lb"}],"endTime":1585984546968,"spanType":"Entry","spanId":0,"isError":false,"parentSpanId":-1,"componentId":6000,"refs":[{"traceId":"1585984546953.410917649.45972","networkAddressUsedAtPeer":"upstream service","parentEndpoint":"\/ingress","parentServiceInstance":"User Service Instance Name","parentSpanId":1,"parentService":"User Service Name","parentTraceSegmentId":"1585984546953.410917649.45972","refType":"CrossProcess"}],"spanLayer":"Http"}],"service":"User Service Name","traceSegmentId":"1585984546967.449397702.9959"} +2020/04/04 15:15:46 [debug] 12089#1446111: *11 [lua] tracer.lua:87: prepareForReport(): segment buffer size = 1 +2020/04/04 15:15:46 [debug] 12089#1446111: *8 [lua] tracer.lua:83: prepareForReport(): segment = {"traceId":"1585984546953.410917649.45972","serviceInstance":"User Service Instance Name","spans":[{"operationName":"\/ingress","startTime":1585984546953,"endTime":1585984546968,"spanType":"Exit","spanId":1,"isError":false,"parentSpanId":0,"componentId":6000,"peer":"upstream service","spanLayer":"Http"},{"operationName":"\/ingress","startTime":1585984546953,"tags":[{"key":"http.method","value":"GET"},{"key":"http.params","value":"http:\/\/localhost\/ingress"}],"endTime":1585984546968,"spanType":"Entry","spanId":0,"parentSpanId":-1,"isError":false,"spanLayer":"Http","componentId":6000}],"service":"User Service Name","traceSegmentId":"1585984546953.410917649.45972"} ``` ### Local Development and Unit Tests diff --git a/examples/nginx.conf b/examples/nginx.conf index d5f8544..374f9ff 100644 --- a/examples/nginx.conf +++ b/examples/nginx.conf @@ -101,7 +101,7 @@ http { default_type text/html; content_by_lua_block { ngx.say("

Backend service for testing only.

") - ngx.say("

Backend sw6 received headers: " .. ngx.req.get_headers()["sw6"] .. "

") + ngx.say("

Backend sw8 received headers: " .. ngx.req.get_headers()["sw8"] .. "

") } } @@ -109,49 +109,34 @@ http { # ------------------------------------------------------ # -- Mock OAP server to provide register and trace collection # ------------------------------------------------------ - location /v2/service/register { + location /v3/management/reportProperties { default_type text/html; lua_need_request_body on; content_by_lua_block { local cjson = require('cjson') - - ngx.log(ngx.DEBUG, 'Service register request = ', ngx.req.get_body_data()) - local param = cjson.decode(ngx.req.get_body_data()) - local registeredInfo = {} - registeredInfo[1] = {key=param.services[1].serviceName, value=1} - ngx.say(cjson.encode(registeredInfo)) - } - } - - location /v2/instance/register { - default_type text/html; - lua_need_request_body on; + ngx.log(ngx.DEBUG, 'Instance report request = ', ngx.req.get_body_data()) - content_by_lua_block { - local cjson = require('cjson') - ngx.log(ngx.DEBUG, 'Service instance register request = ', ngx.req.get_body_data()) - local param = cjson.decode(ngx.req.get_body_data()) - - local registeredInfo = {} - - registeredInfo[1] = {key=param.instances[1].instanceUUID, value=1} - ngx.say(cjson.encode(registeredInfo)) + local reportInfo = {} + ngx.say(cjson.encode(reportInfo)) } } - location /v2/instance/heartbeat { + location /v3/management/keepAlive { default_type text/html; lua_need_request_body on; content_by_lua_block { local cjson = require('cjson') - --ngx.log(ngx.DEBUG, 'Service instance ping request = ', ngx.req.get_body_data()) + ngx.log(ngx.DEBUG, 'KeepAlive request = ', ngx.req.get_body_data()) + + local keepAliveInfo = {} + ngx.say(cjson.encode(keepAliveInfo)) } } - location /v2/segments { + location /v3/segments { default_type text/html; lua_need_request_body on; diff --git a/lib/skywalking/client.lua b/lib/skywalking/client.lua index 2e7c908..35e180d 100644 --- a/lib/skywalking/client.lua +++ b/lib/skywalking/client.lua @@ -17,8 +17,8 @@ local Client = {} --- Tracing timer does the service and instance register --- After register successfully, it sends traces and heart beat +-- Tracing timer does the instance report and sends traces +-- After report successfully, it will heart beat function Client:startBackendTimer(backend_http_uri) local metadata_buffer = ngx.shared.tracing_buffer @@ -70,7 +70,7 @@ function Client:registerService(metadata_buffer, backend_http_uri) local serviceInstanceName = metadata_buffer:get('serviceInstanceName') local cjson = require('cjson') - local reportInstance = require("register").newReportInstanceProperties(serviceName, serviceInstanceName) + local reportInstance = require("management").newReportInstanceProperties(serviceName, serviceInstanceName) local reportInstanceParam = cjson.encode(reportInstance) local http = require('resty.http') @@ -103,7 +103,7 @@ function Client:ping(metadata_buffer, backend_http_uri) local serviceInstanceName = metadata_buffer:get('serviceInstanceName') local cjson = require('cjson') - local pingPkg = require("register").newServiceInstancePingPkg(serviceName, serviceInstanceName) + local pingPkg = require("management").newServiceInstancePingPkg(serviceName, serviceInstanceName) local pingPkgParam = cjson.encode(pingPkg) local http = require('resty.http') diff --git a/lib/skywalking/management.lua b/lib/skywalking/management.lua index 1f590ee..351b369 100644 --- a/lib/skywalking/management.lua +++ b/lib/skywalking/management.lua @@ -22,14 +22,14 @@ function _M.newReportInstanceProperties(serviceName, serviceInstance) local instanceProperties = { service = serviceName, serviceInstance = serviceInstance, - allProperties = {} + properties = {} } local allProperties = { language = "Lua" } - instanceProperties.allProperties[#instanceProperties.allProperties + 1] = allProperties + instanceProperties.properties[#instanceProperties.properties + 1] = allProperties return instanceProperties end diff --git a/lib/skywalking/span.lua b/lib/skywalking/span.lua index 162abbe..c729295 100644 --- a/lib/skywalking/span.lua +++ b/lib/skywalking/span.lua @@ -63,7 +63,7 @@ local _M = {} -- } -- Create an entry span. Represent the HTTP incoming request. --- @param contextCarrier, HTTP request header, which could carry the `sw6` context +-- @param contextCarrier, HTTP request header, which could carry the `sw8` context function _M.createEntrySpan(operationName, context, parent, contextCarrier) local span = _M.new(operationName, context, parent) span.is_entry = true diff --git a/lib/skywalking/util.lua b/lib/skywalking/util.lua index 2ea3079..7d642e3 100644 --- a/lib/skywalking/util.lua +++ b/lib/skywalking/util.lua @@ -83,27 +83,7 @@ end math.randomseed(random_seed()) function _M.newID() - return timestamp() .. math.random(0, MAX_ID_PART2) .. math.random(0, MAX_ID_PART3) -end - --- Format a trace/segment id into an array. --- An official ID should have three parts separated by '.' and each part of it is a number -function _M.formatID(str) - local regex = '.' - if _M.is_ngx_lua then - regex = [[\.]] - end - local parts = split(str, regex) - if #parts ~= 3 then - return nil - end - - return parts -end - --- @param id is an array with length = 3 -function _M.id2String(id) - return id[1] .. '.' .. id[2] .. '.' .. id[3] + return timestamp() .. '.' .. math.random(0, MAX_ID_PART2) .. '.' .. math.random(0, MAX_ID_PART3) end return _M diff --git a/skywalking-nginx-lua-1.0-0.rockspec b/skywalking-nginx-lua-1.0-0.rockspec index 0ec803c..458cc9c 100644 --- a/skywalking-nginx-lua-1.0-0.rockspec +++ b/skywalking-nginx-lua-1.0-0.rockspec @@ -18,7 +18,7 @@ dependencies = { build = { type = "builtin", modules = { - ["skywalking.register"] = "lib/skywalking/register.lua", + ["skywalking.management"] = "lib/skywalking/management.lua", ["skywalking.segment_ref"] = "lib/skywalking/segment_ref.lua", ["skywalking.segment"] = "lib/skywalking/segment.lua", ["skywalking.span_layer"] = "lib/skywalking/span_layer.lua", From d900c5be63db578c67bd6c949e1ef85b8a10c44e Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Sat, 4 Apr 2020 16:20:38 +0800 Subject: [PATCH 03/21] add service name not null check --- lib/skywalking/tracing_context.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/skywalking/tracing_context.lua b/lib/skywalking/tracing_context.lua index c997481..fbeaa82 100644 --- a/lib/skywalking/tracing_context.lua +++ b/lib/skywalking/tracing_context.lua @@ -108,7 +108,7 @@ function _M.newNoOP() end function _M.new(serviceName, serviceInstanceName) - if serviceInstanceName == nil then + if serviceInstanceName == nil or serviceName == nil then return _M.newNoOP() end From e4decaad5484de3466dd0a18e1e65a6f4e7e53ee Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Sat, 4 Apr 2020 16:31:37 +0800 Subject: [PATCH 04/21] fix wrong comment --- README.md | 2 +- lib/skywalking/client.lua | 5 ++--- lib/skywalking/segment.lua | 4 ++-- lib/skywalking/segment_ref.lua | 4 ++-- lib/skywalking/span.lua | 4 ++-- lib/skywalking/tracing_context.lua | 4 ++-- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 8276ab5..ae4a425 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ Then you could 1. See the `register logs` happens on the console log. ``` 2020/04/04 15:15:37 [debug] 12089#1446111: *4 [lua] content_by_lua(nginx.conf:175):4: Instance report request = {"service":"User Service Name","serviceInstance":"User Service Instance Name","properties":[{"language":"Lua"}]} -2020/04/04 15:15:37 [debug] 12089#1446111: *2 [lua] client.lua:89: registerService(): Instance report response = {} +2020/04/04 15:15:37 [debug] 12089#1446111: *2 [lua] client.lua:89: reportServiceInstance(): Instance report response = {} ``` 1. See the `heartbeat logs` happens after the `register logs` diff --git a/lib/skywalking/client.lua b/lib/skywalking/client.lua index 35e180d..1aa6f8d 100644 --- a/lib/skywalking/client.lua +++ b/lib/skywalking/client.lua @@ -35,7 +35,7 @@ function Client:startBackendTimer(backend_http_uri) if not premature then local instancePropertiesSubmitted = metadata_buffer:get('instancePropertiesSubmitted') if (instancePropertiesSubmitted == nil or instancePropertiesSubmitted == false) then - self:registerService(metadata_buffer, backend_http_uri) + self:reportServiceInstance(metadata_buffer, backend_http_uri) else self:ping(metadata_buffer, backend_http_uri) end @@ -60,8 +60,7 @@ function Client:startBackendTimer(backend_http_uri) end end --- Register service -function Client:registerService(metadata_buffer, backend_http_uri) +function Client:reportServiceInstance(metadata_buffer, backend_http_uri) local log = ngx.log local DEBUG = ngx.DEBUG local ERR = ngx.ERR diff --git a/lib/skywalking/segment.lua b/lib/skywalking/segment.lua index 227015b..5127b52 100644 --- a/lib/skywalking/segment.lua +++ b/lib/skywalking/segment.lua @@ -30,8 +30,8 @@ local _M = {} -- Due to nesting relationship inside Segment/Span/TracingContext at the runtime, -- SegmentProtocol is created to prepare JSON format serialization. --- Following SkyWalking official trace protocol v2 --- https://github.com/apache/skywalking-data-collect-protocol/blob/master/language-agent-v2/trace.proto +-- Following SkyWalking official trace protocol v3 +-- https://github.com/apache/skywalking-data-collect-protocol/blob/master/language-agent/Tracing.proto -- local SegmentProtocol = { -- traceId, -- traceSegmentId, diff --git a/lib/skywalking/segment_ref.lua b/lib/skywalking/segment_ref.lua index 751c416..d4f1eae 100644 --- a/lib/skywalking/segment_ref.lua +++ b/lib/skywalking/segment_ref.lua @@ -79,8 +79,8 @@ end -- Due to nesting relationship inside Segment/Span/TracingContext at the runtime, -- RefProtocol is created to prepare JSON format serialization. --- Following SkyWalking official trace protocol v2 --- https://github.com/apache/skywalking-data-collect-protocol/blob/master/language-agent-v2/trace.proto +-- Following SkyWalking official trace protocol v3 +-- https://github.com/apache/skywalking-data-collect-protocol/blob/master/language-agent/Tracing.proto -- local RefProtocol = { -- -- Constant in LUA, no cross-thread -- refType = 'CrossProcess', diff --git a/lib/skywalking/span.lua b/lib/skywalking/span.lua index c729295..06b585d 100644 --- a/lib/skywalking/span.lua +++ b/lib/skywalking/span.lua @@ -43,8 +43,8 @@ local _M = {} -- Due to nesting relationship inside Segment/Span/TracingContext at the runtime, -- SpanProtocol is created to prepare JSON format serialization. --- Following SkyWalking official trace protocol v2 --- https://github.com/apache/skywalking-data-collect-protocol/blob/master/language-agent-v2/trace.proto +-- Following SkyWalking official trace protocol v3 +-- https://github.com/apache/skywalking-data-collect-protocol/blob/master/language-agent/Tracing.proto -- local SpanProtocol = { -- spanId, -- parentSpanId, diff --git a/lib/skywalking/tracing_context.lua b/lib/skywalking/tracing_context.lua index fbeaa82..3a0dac2 100644 --- a/lib/skywalking/tracing_context.lua +++ b/lib/skywalking/tracing_context.lua @@ -97,8 +97,8 @@ local _M = {} -- local TracingContext = { -- trace_id, -- segment_id, --- service_id, --- service_inst_id, +-- service, +-- service_instance, -- is_noop = false, -- internal, -- } From 60a21b0984722b4e67d55cd2fe429fb8b2797e3c Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Mon, 6 Apr 2020 12:16:27 +0800 Subject: [PATCH 05/21] using the new agent test tool --- test/e2e/agent-test-tools/pom.xml | 2 +- .../src/test/resources/expectedData.yaml | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/e2e/agent-test-tools/pom.xml b/test/e2e/agent-test-tools/pom.xml index 09e6280..8bc739c 100644 --- a/test/e2e/agent-test-tools/pom.xml +++ b/test/e2e/agent-test-tools/pom.xml @@ -38,7 +38,7 @@ skywalking-collector 0.4.13 1.6.0 - 14b1499e65788d570ce5914b2ca7320cd36f961e + d5491d35462ec07982773d4f61ec71ad410ad48b ${project.basedir}/target/agent-test-tools https://github.com/apache/skywalking-agent-test-tool.git diff --git a/test/e2e/e2e-with-mock-collector/src/test/resources/expectedData.yaml b/test/e2e/e2e-with-mock-collector/src/test/resources/expectedData.yaml index a03ec9d..49513ff 100644 --- a/test/e2e/e2e-with-mock-collector/src/test/resources/expectedData.yaml +++ b/test/e2e/e2e-with-mock-collector/src/test/resources/expectedData.yaml @@ -49,9 +49,10 @@ segmentItems: parentSpanId: -1 componentId: 6000 refs: - - {parentEndpointId: 0, entryEndpointId: 0, parentServiceInstanceId: 1, parentEndpoint: /ingress, parentTraceSegmentId: not null, + - {parentEndpoint: /ingress, parentTraceSegmentId: not null, refType: 'CrossProcess', networkAddress: 'e2e-test-with-mock-collector:upstream_ip:port', parentSpanId: 1, - entryServiceInstanceId: 1, networkAddressId: 0, entryEndpoint: /ingress} + parentServiceInstance: 'e2e-test-with-mock-collector-instanceA', traceId: not null, + parentService: 'e2e-test-with-mock-collector'} spanLayer: Http - segmentId: not null spans: From 51925d7370667aa5524268c305dbc89569b93614 Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Mon, 6 Apr 2020 14:31:44 +0800 Subject: [PATCH 06/21] add uuid as the new id generate way --- .github/workflows/ci.yaml | 1 + LICENSE | 1 + .../dependencies/lua-resty-jit-uuid.lua | 425 ++++++++++++++++++ lib/skywalking/util.lua | 7 +- licenses/LICENSE-lua-resty-jit-uuid.txt | 21 + t/util.t | 2 +- 6 files changed, 452 insertions(+), 5 deletions(-) create mode 100644 lib/skywalking/dependencies/lua-resty-jit-uuid.lua create mode 100644 licenses/LICENSE-lua-resty-jit-uuid.txt diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f735fe3..6bcdf42 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -47,6 +47,7 @@ jobs: - name: 'Install Dependencies' run: | sudo luarocks install luaunit + sudo luarocks install luabitop sudo luarocks install lua-cjson 2.1.0-1 - name: "Install OpenResty" run: | diff --git a/LICENSE b/LICENSE index 037d158..7d17ec7 100644 --- a/LICENSE +++ b/LICENSE @@ -216,6 +216,7 @@ The following components are provided under a MIT license. See project link for The text of each license is also included at licenses/LICENSE-[project].txt. base64 dependencies/base64.lua https://github.com/iskolbin/lbase64 MIT + lua-resty-jit-uuid dependencies/lua-resty-jit-uuid.lua https://github.com/thibaultcha/lua-resty-jit-uuid MIT ======================================================================== diff --git a/lib/skywalking/dependencies/lua-resty-jit-uuid.lua b/lib/skywalking/dependencies/lua-resty-jit-uuid.lua new file mode 100644 index 0000000..f101009 --- /dev/null +++ b/lib/skywalking/dependencies/lua-resty-jit-uuid.lua @@ -0,0 +1,425 @@ +--- jit-uuid +-- Fast and dependency-free UUID library for LuaJIT/ngx_lua. +-- @module jit-uuid +-- @author Thibault Charbonnier +-- @license MIT +-- @release 0.0.7 + + +local bit = require 'bit' + + +local tohex = bit.tohex +local band = bit.band +local bor = bit.bor + + +local _M = { + _VERSION = '0.0.7' +} + + +---------- +-- seeding +---------- + + +--- Seed the random number generator. +-- Under the hood, this function calls `math.randomseed`. +-- It makes sure to use the most appropriate seeding technique for +-- the current environment, guaranteeing a unique seed. +-- +-- To guarantee unique UUIDs, you must have correctly seeded +-- the Lua pseudo-random generator (with `math.randomseed`). +-- You are free to seed it any way you want, but this function +-- can do it for you if you'd like, with some added guarantees. +-- +-- @param[type=number] seed (Optional) A seed to use. If none given, will +-- generate one trying to use the most appropriate technique. +-- @treturn number `seed`: the seed given to `math.randomseed`. +-- @usage +-- local uuid = require 'resty.jit-uuid' +-- uuid.seed() +-- +-- -- in ngx_lua, seed in the init_worker context: +-- init_worker_by_lua { +-- local uuid = require 'resty.jit-uuid' +-- uuid.seed() +-- } +function _M.seed(seed) + if not seed then + if ngx then + seed = ngx.time() + ngx.worker.pid() + + elseif package.loaded['socket'] and package.loaded['socket'].gettime then + seed = package.loaded['socket'].gettime()*10000 + + else + seed = os.time() + end + end + + math.randomseed(seed) + + return seed +end + + +------------- +-- validation +------------- + + +do + if ngx and string.find(ngx.config.nginx_configure(),'--with-pcre-jit',nil,true) then + local type = type + local re_find = ngx.re.find + local regex = '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' + + + --- Validate a string as a UUID. + -- To be considered valid, a UUID must be given in its canonical + -- form (hexadecimal digits including the hyphen characters). + -- This function validates UUIDs disregarding their generation algorithm, + -- and in a case-insensitive manner, but checks the variant field. + -- + -- Use JIT PCRE if available in OpenResty or fallbacks on Lua patterns. + -- + -- @param[type=string] str String to verify. + -- @treturn boolean `valid`: true if valid UUID, false otherwise. + -- @usage + -- local uuid = require 'resty.jit-uuid' + -- + -- uuid.is_valid 'cbb297c0-a956-486d-ad1d-f9bZZZZZZZZZ' --> false + -- uuid.is_valid 'cbb297c0-a956-486d-dd1d-f9b42df9465a' --> false (invalid variant) + -- uuid.is_valid 'cbb297c0a956486dad1df9b42df9465a' --> false (no dashes) + -- uuid.is_valid 'cbb297c0-a956-486d-ad1d-f9b42df9465a' --> true + function _M.is_valid(str) + -- it has proven itself efficient to first check the length with an + -- evenly distributed set of valid and invalid uuid lengths. + if type(str) ~= 'string' or #str ~= 36 then + return false + end + + return re_find(str, regex, 'ioj') ~= nil + end + + else + local match = string.match + local d = '[0-9a-fA-F]' + local p = '^' .. table.concat({ + d:rep(8), + d:rep(4), + d:rep(4), + '[89ab]' .. d:rep(3), + d:rep(12) + }, '%-') .. '$' + + + function _M.is_valid(str) + if type(str) ~= 'string' or #str ~= 36 then + return false + end + + return match(str, p) ~= nil + end + end +end + + +---------------- +-- v4 generation +---------------- + + +do + local fmt = string.format + local random = math.random + + + --- Generate a v4 UUID. + -- v4 UUIDs are created from randomly generated numbers. + -- + -- @treturn string `uuid`: a v4 (randomly generated) UUID. + -- @usage + -- local uuid = require 'resty.jit-uuid' + -- + -- local u1 = uuid() ---> __call metamethod + -- local u2 = uuid.generate_v4() + function _M.generate_v4() + return (fmt('%s%s%s%s-%s%s-%s%s-%s%s-%s%s%s%s%s%s', + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + + tohex(bor(band(random(0, 255), 0x0F), 0x40), 2), + tohex(random(0, 255), 2), + + tohex(bor(band(random(0, 255), 0x3F), 0x80), 2), + tohex(random(0, 255), 2), + + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + tohex(random(0, 255), 2))) + end +end + + +---------------- +-- v3/v5 generation +---------------- + + +do + if ngx then + local ffi = require 'ffi' + + + local tonumber = tonumber + local assert = assert + local error = error + local concat = table.concat + local type = type + local char = string.char + local fmt = string.format + local sub = string.sub + local gmatch = ngx.re.gmatch + local sha1_bin = ngx.sha1_bin + local md5 = ngx.md5 + local C = ffi.C + local ffi_new = ffi.new + local ffi_str = ffi.string + local ffi_cast = ffi.cast + local new_tab + do + local ok + ok, new_tab = pcall(require, 'table.new') + if not ok then + new_tab = function(narr, nrec) return {} end + end + end + + + ffi.cdef [[ + typedef unsigned char u_char; + typedef intptr_t ngx_int_t; + + u_char * ngx_hex_dump(u_char *dst, const u_char *src, size_t len); + ngx_int_t ngx_hextoi(u_char *line, size_t n); + ]] + + + local str_type = ffi.typeof('uint8_t[?]') + local u_char_type = ffi.typeof('u_char *') + + + local function bin_tohex(s) + local slen = #s + local blen = slen * 2 + local buf = ffi_new(str_type, blen) + + C.ngx_hex_dump(buf, s, slen) + + return ffi_str(buf, blen) + end + + + local function hex_to_i(s) + local buf = ffi_cast(u_char_type, s) + + local n = tonumber(C.ngx_hextoi(buf, #s)) + if n == -1 then + error("could not convert hex to number") + end + + return n + end + + + local buf = new_tab(16, 0) + + + local function factory(namespace, hash_fn) + if not _M.is_valid(namespace) then + return nil, 'namespace must be a valid UUID' + end + + local i = 0 + local iter, err = gmatch(namespace, [[([\da-f][\da-f])]]) + if not iter then + return nil, 'could not create iter: ' .. err + end + + while true do + local m, err = iter() + if err then + return nil, err + end + + if not m then + break + end + + i = i + 1 + buf[i] = char(tonumber(m[0], 16)) + end + + assert(i == 16, "invalid binary namespace buffer length") + local ns = concat(buf) + + return function(name) + if type(name) ~= 'string' then + return nil, 'name must be a string' + end + + local hash, ver, var = hash_fn(ns, name) + + return (fmt('%s-%s-%s%s-%s%s-%s', sub(hash, 1, 8), + sub(hash, 9, 12), + ver, + sub(hash, 15, 16), + var, + sub(hash, 19, 20), + sub(hash, 21, 32))) + end + end + + + local function v3_hash(binary, name) + local hash = md5(binary .. name) + + return hash, + tohex(bor(band(hex_to_i(sub(hash, 13, 14)), 0x0F), 0x30), 2), + tohex(bor(band(hex_to_i(sub(hash, 17, 18)), 0x3F), 0x80), 2) + end + + + local function v5_hash(binary, name) + local hash = bin_tohex(sha1_bin(binary .. name)) + + return hash, + tohex(bor(band(hex_to_i(sub(hash, 13, 14)), 0x0F), 0x50), 2), + tohex(bor(band(hex_to_i(sub(hash, 17, 18)), 0x3F), 0x80), 2) + end + + + --- Instanciate a v3 UUID factory. + -- @function factory_v3 + -- Creates a closure generating namespaced v3 UUIDs. + -- @param[type=string] namespace (must be a valid UUID according to `is_valid`) + -- @treturn function `factory`: a v3 UUID generator. + -- @treturn string `err`: a string describing an error + -- @usage + -- local uuid = require 'resty.jit-uuid' + -- + -- local fact = assert(uuid.factory_v3('e6ebd542-06ae-11e6-8e82-bba81706b27d')) + -- + -- local u1 = fact('hello') + -- ---> 3db7a435-8c56-359d-a563-1b69e6802c78 + -- + -- local u2 = fact('foobar') + -- ---> e8d3eeba-7723-3b72-bbc5-8f598afa6773 + function _M.factory_v3(namespace) + return factory(namespace, v3_hash) + end + + + --- Instanciate a v5 UUID factory. + -- @function factory_v5 + -- Creates a closure generating namespaced v5 UUIDs. + -- @param[type=string] namespace (must be a valid UUID according to `is_valid`) + -- @treturn function `factory`: a v5 UUID generator. + -- @treturn string `err`: a string describing an error + -- @usage + -- local uuid = require 'resty.jit-uuid' + -- + -- local fact = assert(uuid.factory_v5('e6ebd542-06ae-11e6-8e82-bba81706b27d')) + -- + -- local u1 = fact('hello') + -- ---> 4850816f-1658-5890-8bfd-1ed14251f1f0 + -- + -- local u2 = fact('foobar') + -- ---> c9be99fc-326b-5066-bdba-dcd31a6d01ab + function _M.factory_v5(namespace) + return factory(namespace, v5_hash) + end + + + --- Generate a v3 UUID. + -- v3 UUIDs are created from a namespace and a name (a UUID and a string). + -- The same name and namespace result in the same UUID. The same name and + -- different namespaces result in different UUIDs, and vice-versa. + -- The resulting UUID is derived using MD5 hashing. + -- + -- This is a sugar function which instanciates a short-lived v3 UUID factory. + -- It is an expensive operation, and intensive generation using the same + -- namespaces should prefer allocating their own long-lived factory with + -- `factory_v3`. + -- + -- @param[type=string] namespace (must be a valid UUID according to `is_valid`) + -- @param[type=string] name + -- @treturn string `uuid`: a v3 (namespaced) UUID. + -- @treturn string `err`: a string describing an error + -- @usage + -- local uuid = require 'resty.jit-uuid' + -- + -- local u = uuid.generate_v3('e6ebd542-06ae-11e6-8e82-bba81706b27d', 'hello') + -- ---> 3db7a435-8c56-359d-a563-1b69e6802c78 + function _M.generate_v3(namespace, name) + local fact, err = _M.factory_v3(namespace) + if not fact then + return nil, err + end + + return fact(name) + end + + + --- Generate a v5 UUID. + -- v5 UUIDs are created from a namespace and a name (a UUID and a string). + -- The same name and namespace result in the same UUID. The same name and + -- different namespaces result in different UUIDs, and vice-versa. + -- The resulting UUID is derived using SHA-1 hashing. + -- + -- This is a sugar function which instanciates a short-lived v5 UUID factory. + -- It is an expensive operation, and intensive generation using the same + -- namespaces should prefer allocating their own long-lived factory with + -- `factory_v5`. + -- + -- @param[type=string] namespace (must be a valid UUID according to `is_valid`) + -- @param[type=string] name + -- @treturn string `uuid`: a v5 (namespaced) UUID. + -- @treturn string `err`: a string describing an error + -- @usage + -- local uuid = require 'resty.jit-uuid' + -- + -- local u = uuid.generate_v5('e6ebd542-06ae-11e6-8e82-bba81706b27d', 'hello') + -- ---> 4850816f-1658-5890-8bfd-1ed14251f1f0 + function _M.generate_v5(namespace, name) + local fact, err = _M.factory_v5(namespace) + if not fact then + return nil, err + end + + return fact(name) + end + + else + function _M.factory_v3() error('v3 UUID generation only supported in ngx_lua', 2) end + function _M.generate_v3() error('v3 UUID generation only supported in ngx_lua', 2) end + function _M.factory_v5() error('v5 UUID generation only supported in ngx_lua', 2) end + function _M.generate_v5() error('v5 UUID generation only supported in ngx_lua', 2) end + end +end + + +return setmetatable(_M, { + __call = _M.generate_v4 +}) \ No newline at end of file diff --git a/lib/skywalking/util.lua b/lib/skywalking/util.lua index 7d642e3..1be980a 100644 --- a/lib/skywalking/util.lua +++ b/lib/skywalking/util.lua @@ -51,9 +51,6 @@ _M.split = split _M.timestamp = timestamp _M.is_ngx_lua = ok -local MAX_ID_PART2 = 1000000000 -local MAX_ID_PART3 = 100000 - local random_seed = function () local seed local frandom = io.open("/dev/urandom", "rb") @@ -80,10 +77,12 @@ local random_seed = function () return seed end +local uuid = require('dependencies/lua-resty-jit-uuid') +uuid.seed() math.randomseed(random_seed()) function _M.newID() - return timestamp() .. '.' .. math.random(0, MAX_ID_PART2) .. '.' .. math.random(0, MAX_ID_PART3) + return uuid.generate_v4() end return _M diff --git a/licenses/LICENSE-lua-resty-jit-uuid.txt b/licenses/LICENSE-lua-resty-jit-uuid.txt new file mode 100644 index 0000000..658b3d9 --- /dev/null +++ b/licenses/LICENSE-lua-resty-jit-uuid.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016-2019 Thibault Charbonnier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/t/util.t b/t/util.t index 64d5cfa..5ca2deb 100644 --- a/t/util.t +++ b/t/util.t @@ -52,7 +52,7 @@ true content_by_lua_block { local util = require('util') local id = util.newID() - local regex = [[^\d+\.\d+\.\d+$]] + local regex = [[^\d+\-\d+\-\d+\-\d+$]] local m = ngx.re.match(id, regex) if m then ngx.say(true) From 49f5585281acfd460389b90505333439ea89459b Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Mon, 6 Apr 2020 14:46:08 +0800 Subject: [PATCH 07/21] remove luabitop install --- .github/workflows/ci.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6bcdf42..f735fe3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -47,7 +47,6 @@ jobs: - name: 'Install Dependencies' run: | sudo luarocks install luaunit - sudo luarocks install luabitop sudo luarocks install lua-cjson 2.1.0-1 - name: "Install OpenResty" run: | From dc3dd9d3c515b3e7ebdd4ac447474a80dbe0d17f Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Mon, 6 Apr 2020 16:37:25 +0800 Subject: [PATCH 08/21] adapt the unit test, none nginx lua environment --- lib/skywalking/util.lua | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/skywalking/util.lua b/lib/skywalking/util.lua index 1be980a..105856a 100644 --- a/lib/skywalking/util.lua +++ b/lib/skywalking/util.lua @@ -51,6 +51,9 @@ _M.split = split _M.timestamp = timestamp _M.is_ngx_lua = ok +local MAX_ID_PART2 = 1000000000 +local MAX_ID_PART3 = 100000 + local random_seed = function () local seed local frandom = io.open("/dev/urandom", "rb") @@ -77,12 +80,21 @@ local random_seed = function () return seed end -local uuid = require('dependencies/lua-resty-jit-uuid') -uuid.seed() +local newID = function() + return timestamp() .. '.' .. math.random(0, MAX_ID_PART2) .. '.' .. math.random(0, MAX_ID_PART3) +end + math.randomseed(random_seed()) -function _M.newID() - return uuid.generate_v4() +-- for Nginx Lua +local ok, uuid = pcall(require, "dependencies/lua-resty-jit-uuid") +if ok then + uuid.seed() + newID = function() + return uuid.generate_v4() + end end +_M.newID = newID + return _M From e58d808ca14231633b311f423df3f3de6e80b9e6 Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Mon, 6 Apr 2020 17:12:05 +0800 Subject: [PATCH 09/21] upgrade checkout tools --- .github/workflows/ci.yaml | 2 +- .github/workflows/e2e.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f735fe3..b4ad31c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -31,7 +31,7 @@ jobs: strategy: fail-fast: true steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 with: submodules: true - uses: leafo/gh-actions-lua@v5 diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 267edf8..a930a5e 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -31,7 +31,7 @@ jobs: strategy: fail-fast: true steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 with: submodules: true - uses: actions/setup-java@v1 From 9e78022233e1f48b3ac8d688b05f6c7e8506c0d1 Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Mon, 6 Apr 2020 17:17:24 +0800 Subject: [PATCH 10/21] adapt the submodule update --- .github/workflows/ci.yaml | 8 ++++++-- .github/workflows/e2e.yaml | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b4ad31c..226ed7d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -32,8 +32,12 @@ jobs: fail-fast: true steps: - uses: actions/checkout@v2 - with: - submodules: true + # In the checkout@v2, it doesn't support git submodule. Execute the commands manually. + - name: checkout submodules + shell: bash + run: | + git submodule sync --recursive + git -c protocol.version=2 submodule update --init --force --recursive --depth=1 - uses: leafo/gh-actions-lua@v5 with: luaVersion: "5.3.5" diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index a930a5e..9f3c447 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -32,8 +32,12 @@ jobs: fail-fast: true steps: - uses: actions/checkout@v2 - with: - submodules: true + # In the checkout@v2, it doesn't support git submodule. Execute the commands manually. + - name: checkout submodules + shell: bash + run: | + git submodule sync --recursive + git -c protocol.version=2 submodule update --init --force --recursive --depth=1 - uses: actions/setup-java@v1 with: java-version: 8 From 451fc9edfc8375428ae60b10b47327f813594bac Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Mon, 6 Apr 2020 17:31:04 +0800 Subject: [PATCH 11/21] fix test failure --- t/util.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/util.t b/t/util.t index 5ca2deb..13208d4 100644 --- a/t/util.t +++ b/t/util.t @@ -52,7 +52,7 @@ true content_by_lua_block { local util = require('util') local id = util.newID() - local regex = [[^\d+\-\d+\-\d+\-\d+$]] + local regex = [[^[0-9a-f]+\-[0-9a-f]+\-[0-9a-f]+\-[0-9a-f]+\-[0-9a-f]+$]] local m = ngx.re.match(id, regex) if m then ngx.say(true) From 8fd8cdef5e13f2c7a92888e022aa0b0fd3179219 Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Tue, 7 Apr 2020 09:00:56 +0800 Subject: [PATCH 12/21] resolve issues --- README.md | 6 +++--- lib/skywalking/client.lua | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ae4a425..7e31525 100644 --- a/README.md +++ b/README.md @@ -80,18 +80,18 @@ You could choose master branch before the official 7.0.0 release. ### Debug Startup By using the `/examples/nginx.conf`, you could start the Nginx with LUA module or OpenResty. Such as `nginx -c /path/to/skywalking-nginx-lua/examples/nginx.conf` Then you could -1. See the `register logs` happens on the console log. +1. See the `instance properties update logs` happens on the console log. ``` 2020/04/04 15:15:37 [debug] 12089#1446111: *4 [lua] content_by_lua(nginx.conf:175):4: Instance report request = {"service":"User Service Name","serviceInstance":"User Service Instance Name","properties":[{"language":"Lua"}]} 2020/04/04 15:15:37 [debug] 12089#1446111: *2 [lua] client.lua:89: reportServiceInstance(): Instance report response = {} ``` -1. See the `heartbeat logs` happens after the `register logs` +2. See the `heartbeat logs` happens after the `register logs` ``` 2020/04/04 15:15:40 [debug] 12089#1446111: *4 [lua] content_by_lua(nginx.conf:188):3: KeepAlive request = {"service":"User Service Name","serviceInstance":"User Service Instance Name"} ``` -1. Access the `http://127.0.0.1:8080/ingress` then you could see the tracing happens and reported spans in the logs. +3. Access the `http://127.0.0.1:8080/ingress` then you could see the tracing happens and reported spans in the logs. ``` 2020/04/04 15:15:46 [debug] 12089#1446111: *11 [lua] tracer.lua:83: prepareForReport(): segment = {"traceId":"1585984546953.410917649.45972","serviceInstance":"User Service Instance Name","spans":[{"operationName":"\/tier2\/lb","startTime":1585984546967,"endTime":1585984546968,"spanType":"Exit","spanId":1,"isError":false,"parentSpanId":0,"componentId":6000,"peer":"backend service","spanLayer":"Http"},{"operationName":"\/tier2\/lb","startTime":1585984546967,"tags":[{"key":"http.method","value":"GET"},{"key":"http.params","value":"http:\/\/127.0.0.1\/tier2\/lb"}],"endTime":1585984546968,"spanType":"Entry","spanId":0,"isError":false,"parentSpanId":-1,"componentId":6000,"refs":[{"traceId":"1585984546953.410917649.45972","networkAddressUsedAtPeer":"upstream service","parentEndpoint":"\/ingress","parentServiceInstance":"User Service Instance Name","parentSpanId":1,"parentService":"User Service Name","parentTraceSegmentId":"1585984546953.410917649.45972","refType":"CrossProcess"}],"spanLayer":"Http"}],"service":"User Service Name","traceSegmentId":"1585984546967.449397702.9959"} 2020/04/04 15:15:46 [debug] 12089#1446111: *11 [lua] tracer.lua:87: prepareForReport(): segment buffer size = 1 diff --git a/lib/skywalking/client.lua b/lib/skywalking/client.lua index 1aa6f8d..0e74396 100644 --- a/lib/skywalking/client.lua +++ b/lib/skywalking/client.lua @@ -17,8 +17,8 @@ local Client = {} --- Tracing timer does the instance report and sends traces --- After report successfully, it will heart beat +-- Tracing timer reports instance properties report, keeps alive and sends traces +-- After report instance properties successfully, it sends keep alive packages. function Client:startBackendTimer(backend_http_uri) local metadata_buffer = ngx.shared.tracing_buffer From 0852bc775ad1cc219b4e4dea2afa0f2cadd45333 Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Tue, 7 Apr 2020 09:07:56 +0800 Subject: [PATCH 13/21] upgrade the agent test tool --- test/e2e/agent-test-tools/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/agent-test-tools/pom.xml b/test/e2e/agent-test-tools/pom.xml index 8bc739c..c6efbfb 100644 --- a/test/e2e/agent-test-tools/pom.xml +++ b/test/e2e/agent-test-tools/pom.xml @@ -38,7 +38,7 @@ skywalking-collector 0.4.13 1.6.0 - d5491d35462ec07982773d4f61ec71ad410ad48b + 1f009d692b99896c08cf9f26440f92287f0364e7 ${project.basedir}/target/agent-test-tools https://github.com/apache/skywalking-agent-test-tool.git From 050cc4757cad2385504d96ce5bab0a2871f23a0c Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Tue, 7 Apr 2020 11:30:10 +0800 Subject: [PATCH 14/21] fix err log style, handle json encode error --- lib/skywalking/client.lua | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/skywalking/client.lua b/lib/skywalking/client.lua index 0e74396..74d1404 100644 --- a/lib/skywalking/client.lua +++ b/lib/skywalking/client.lua @@ -70,7 +70,11 @@ function Client:reportServiceInstance(metadata_buffer, backend_http_uri) local cjson = require('cjson') local reportInstance = require("management").newReportInstanceProperties(serviceName, serviceInstanceName) - local reportInstanceParam = cjson.encode(reportInstance) + local reportInstanceParam, err = cjson.encode(reportInstance) + if err ~= nil then + log(ERR, "Request to report instance fails, ", err) + return + end local http = require('resty.http') local httpc = http.new() @@ -83,12 +87,12 @@ function Client:reportServiceInstance(metadata_buffer, backend_http_uri) }) if not res then - log(ERR, "Instance report fails, " .. err) + log(ERR, "Instance report fails, ", err) elseif res.status == 200 then log(DEBUG, "Instance report response = " .. res.body) metadata_buffer:set('instancePropertiesSubmitted', true) else - log(ERR, "Service register fails, response code " .. res.status) + log(ERR, "Instance report fails, response code " .. res.status) end end @@ -103,7 +107,10 @@ function Client:ping(metadata_buffer, backend_http_uri) local cjson = require('cjson') local pingPkg = require("management").newServiceInstancePingPkg(serviceName, serviceInstanceName) - local pingPkgParam = cjson.encode(pingPkg) + local pingPkgParam, err = cjson.encode(pingPkg) + if err ~= nil then + log(ERR, "Agent ping fails, ", err) + end local http = require('resty.http') local httpc = http.new() @@ -120,7 +127,7 @@ function Client:ping(metadata_buffer, backend_http_uri) log(ERR, "Agent ping fails, response code " .. res.status) end else - log(ERR, "Agent ping fails, " .. err) + log(ERR, "Agent ping fails, ", err) end end @@ -156,7 +163,7 @@ function Client:reportTraces(metadata_buffer, backend_http_uri) count = count + 1 end else - log(ERR, "Segment report fails, " .. err) + log(ERR, "Segment report fails, ", err) break end From f7ee71a7b9832a22e9ddb1bae92c0a27169209e8 Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Tue, 7 Apr 2020 11:33:53 +0800 Subject: [PATCH 15/21] fix log style --- lib/skywalking/client.lua | 8 ++++---- lib/skywalking/tracer.lua | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/skywalking/client.lua b/lib/skywalking/client.lua index 74d1404..7fd359b 100644 --- a/lib/skywalking/client.lua +++ b/lib/skywalking/client.lua @@ -89,10 +89,10 @@ function Client:reportServiceInstance(metadata_buffer, backend_http_uri) if not res then log(ERR, "Instance report fails, ", err) elseif res.status == 200 then - log(DEBUG, "Instance report response = " .. res.body) + log(DEBUG, "Instance report response = ", res.body) metadata_buffer:set('instancePropertiesSubmitted', true) else - log(ERR, "Instance report fails, response code " .. res.status) + log(ERR, "Instance report fails, response code ", res.status) end end @@ -124,7 +124,7 @@ function Client:ping(metadata_buffer, backend_http_uri) if err == nil then if res.status ~= 200 then - log(ERR, "Agent ping fails, response code " .. res.status) + log(ERR, "Agent ping fails, response code ", res.status) end else log(ERR, "Agent ping fails, ", err) @@ -157,7 +157,7 @@ function Client:reportTraces(metadata_buffer, backend_http_uri) if err == nil then if res.status ~= 200 then - log(ERR, "Segment report fails, response code " .. res.status) + log(ERR, "Segment report fails, response code ", res.status) break else count = count + 1 diff --git a/lib/skywalking/tracer.lua b/lib/skywalking/tracer.lua index a729dd6..13c6571 100644 --- a/lib/skywalking/tracer.lua +++ b/lib/skywalking/tracer.lua @@ -80,11 +80,11 @@ function Tracer:prepareForReport() local status, segment = TC.drainAfterFinished(ngx.ctx.tracingContext) if status then local segmentJson = require('cjson').encode(Segment.transform(segment)) - ngx.log(ngx.DEBUG, 'segment = ' .. segmentJson) + ngx.log(ngx.DEBUG, 'segment = ', segmentJson) local queue = ngx.shared.tracing_buffer local length = queue:lpush('segment', segmentJson) - ngx.log(ngx.DEBUG, 'segment buffer size = ' .. queue:llen('segment')) + ngx.log(ngx.DEBUG, 'segment buffer size = ', queue:llen('segment')) end end end From 897c83d5fe0e030244d6b5f3c8f747be45910139 Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Tue, 7 Apr 2020 12:37:13 +0800 Subject: [PATCH 16/21] simpler the error check style --- lib/skywalking/client.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/skywalking/client.lua b/lib/skywalking/client.lua index 7fd359b..09eeade 100644 --- a/lib/skywalking/client.lua +++ b/lib/skywalking/client.lua @@ -71,7 +71,7 @@ function Client:reportServiceInstance(metadata_buffer, backend_http_uri) local cjson = require('cjson') local reportInstance = require("management").newReportInstanceProperties(serviceName, serviceInstanceName) local reportInstanceParam, err = cjson.encode(reportInstance) - if err ~= nil then + if err then log(ERR, "Request to report instance fails, ", err) return end @@ -108,7 +108,7 @@ function Client:ping(metadata_buffer, backend_http_uri) local cjson = require('cjson') local pingPkg = require("management").newServiceInstancePingPkg(serviceName, serviceInstanceName) local pingPkgParam, err = cjson.encode(pingPkg) - if err ~= nil then + if err then log(ERR, "Agent ping fails, ", err) end From 694a4e3d5d99d65c09a094e9895bc71596d0aeaf Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Tue, 7 Apr 2020 17:57:38 +0800 Subject: [PATCH 17/21] resolve style and dependency issue --- .github/workflows/ci.yaml | 1 + .../dependencies/lua-resty-jit-uuid.lua | 425 ------------------ lib/skywalking/management.lua | 18 +- lib/skywalking/segment_ref.lua | 14 +- lib/skywalking/util.lua | 10 +- skywalking-nginx-lua-1.0-0.rockspec | 2 +- skywalking-nginx-lua-2.0-0.rockspec | 30 ++ 7 files changed, 51 insertions(+), 449 deletions(-) delete mode 100644 lib/skywalking/dependencies/lua-resty-jit-uuid.lua create mode 100644 skywalking-nginx-lua-2.0-0.rockspec diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 226ed7d..56c3529 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -52,6 +52,7 @@ jobs: run: | sudo luarocks install luaunit sudo luarocks install lua-cjson 2.1.0-1 + sudo luarocks install lua-resty-jit-uuid - name: "Install OpenResty" run: | wget -qO - https://openresty.org/package/pubkey.gpg | sudo apt-key add - diff --git a/lib/skywalking/dependencies/lua-resty-jit-uuid.lua b/lib/skywalking/dependencies/lua-resty-jit-uuid.lua deleted file mode 100644 index f101009..0000000 --- a/lib/skywalking/dependencies/lua-resty-jit-uuid.lua +++ /dev/null @@ -1,425 +0,0 @@ ---- jit-uuid --- Fast and dependency-free UUID library for LuaJIT/ngx_lua. --- @module jit-uuid --- @author Thibault Charbonnier --- @license MIT --- @release 0.0.7 - - -local bit = require 'bit' - - -local tohex = bit.tohex -local band = bit.band -local bor = bit.bor - - -local _M = { - _VERSION = '0.0.7' -} - - ----------- --- seeding ----------- - - ---- Seed the random number generator. --- Under the hood, this function calls `math.randomseed`. --- It makes sure to use the most appropriate seeding technique for --- the current environment, guaranteeing a unique seed. --- --- To guarantee unique UUIDs, you must have correctly seeded --- the Lua pseudo-random generator (with `math.randomseed`). --- You are free to seed it any way you want, but this function --- can do it for you if you'd like, with some added guarantees. --- --- @param[type=number] seed (Optional) A seed to use. If none given, will --- generate one trying to use the most appropriate technique. --- @treturn number `seed`: the seed given to `math.randomseed`. --- @usage --- local uuid = require 'resty.jit-uuid' --- uuid.seed() --- --- -- in ngx_lua, seed in the init_worker context: --- init_worker_by_lua { --- local uuid = require 'resty.jit-uuid' --- uuid.seed() --- } -function _M.seed(seed) - if not seed then - if ngx then - seed = ngx.time() + ngx.worker.pid() - - elseif package.loaded['socket'] and package.loaded['socket'].gettime then - seed = package.loaded['socket'].gettime()*10000 - - else - seed = os.time() - end - end - - math.randomseed(seed) - - return seed -end - - -------------- --- validation -------------- - - -do - if ngx and string.find(ngx.config.nginx_configure(),'--with-pcre-jit',nil,true) then - local type = type - local re_find = ngx.re.find - local regex = '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' - - - --- Validate a string as a UUID. - -- To be considered valid, a UUID must be given in its canonical - -- form (hexadecimal digits including the hyphen characters). - -- This function validates UUIDs disregarding their generation algorithm, - -- and in a case-insensitive manner, but checks the variant field. - -- - -- Use JIT PCRE if available in OpenResty or fallbacks on Lua patterns. - -- - -- @param[type=string] str String to verify. - -- @treturn boolean `valid`: true if valid UUID, false otherwise. - -- @usage - -- local uuid = require 'resty.jit-uuid' - -- - -- uuid.is_valid 'cbb297c0-a956-486d-ad1d-f9bZZZZZZZZZ' --> false - -- uuid.is_valid 'cbb297c0-a956-486d-dd1d-f9b42df9465a' --> false (invalid variant) - -- uuid.is_valid 'cbb297c0a956486dad1df9b42df9465a' --> false (no dashes) - -- uuid.is_valid 'cbb297c0-a956-486d-ad1d-f9b42df9465a' --> true - function _M.is_valid(str) - -- it has proven itself efficient to first check the length with an - -- evenly distributed set of valid and invalid uuid lengths. - if type(str) ~= 'string' or #str ~= 36 then - return false - end - - return re_find(str, regex, 'ioj') ~= nil - end - - else - local match = string.match - local d = '[0-9a-fA-F]' - local p = '^' .. table.concat({ - d:rep(8), - d:rep(4), - d:rep(4), - '[89ab]' .. d:rep(3), - d:rep(12) - }, '%-') .. '$' - - - function _M.is_valid(str) - if type(str) ~= 'string' or #str ~= 36 then - return false - end - - return match(str, p) ~= nil - end - end -end - - ----------------- --- v4 generation ----------------- - - -do - local fmt = string.format - local random = math.random - - - --- Generate a v4 UUID. - -- v4 UUIDs are created from randomly generated numbers. - -- - -- @treturn string `uuid`: a v4 (randomly generated) UUID. - -- @usage - -- local uuid = require 'resty.jit-uuid' - -- - -- local u1 = uuid() ---> __call metamethod - -- local u2 = uuid.generate_v4() - function _M.generate_v4() - return (fmt('%s%s%s%s-%s%s-%s%s-%s%s-%s%s%s%s%s%s', - tohex(random(0, 255), 2), - tohex(random(0, 255), 2), - tohex(random(0, 255), 2), - tohex(random(0, 255), 2), - - tohex(random(0, 255), 2), - tohex(random(0, 255), 2), - - tohex(bor(band(random(0, 255), 0x0F), 0x40), 2), - tohex(random(0, 255), 2), - - tohex(bor(band(random(0, 255), 0x3F), 0x80), 2), - tohex(random(0, 255), 2), - - tohex(random(0, 255), 2), - tohex(random(0, 255), 2), - tohex(random(0, 255), 2), - tohex(random(0, 255), 2), - tohex(random(0, 255), 2), - tohex(random(0, 255), 2))) - end -end - - ----------------- --- v3/v5 generation ----------------- - - -do - if ngx then - local ffi = require 'ffi' - - - local tonumber = tonumber - local assert = assert - local error = error - local concat = table.concat - local type = type - local char = string.char - local fmt = string.format - local sub = string.sub - local gmatch = ngx.re.gmatch - local sha1_bin = ngx.sha1_bin - local md5 = ngx.md5 - local C = ffi.C - local ffi_new = ffi.new - local ffi_str = ffi.string - local ffi_cast = ffi.cast - local new_tab - do - local ok - ok, new_tab = pcall(require, 'table.new') - if not ok then - new_tab = function(narr, nrec) return {} end - end - end - - - ffi.cdef [[ - typedef unsigned char u_char; - typedef intptr_t ngx_int_t; - - u_char * ngx_hex_dump(u_char *dst, const u_char *src, size_t len); - ngx_int_t ngx_hextoi(u_char *line, size_t n); - ]] - - - local str_type = ffi.typeof('uint8_t[?]') - local u_char_type = ffi.typeof('u_char *') - - - local function bin_tohex(s) - local slen = #s - local blen = slen * 2 - local buf = ffi_new(str_type, blen) - - C.ngx_hex_dump(buf, s, slen) - - return ffi_str(buf, blen) - end - - - local function hex_to_i(s) - local buf = ffi_cast(u_char_type, s) - - local n = tonumber(C.ngx_hextoi(buf, #s)) - if n == -1 then - error("could not convert hex to number") - end - - return n - end - - - local buf = new_tab(16, 0) - - - local function factory(namespace, hash_fn) - if not _M.is_valid(namespace) then - return nil, 'namespace must be a valid UUID' - end - - local i = 0 - local iter, err = gmatch(namespace, [[([\da-f][\da-f])]]) - if not iter then - return nil, 'could not create iter: ' .. err - end - - while true do - local m, err = iter() - if err then - return nil, err - end - - if not m then - break - end - - i = i + 1 - buf[i] = char(tonumber(m[0], 16)) - end - - assert(i == 16, "invalid binary namespace buffer length") - local ns = concat(buf) - - return function(name) - if type(name) ~= 'string' then - return nil, 'name must be a string' - end - - local hash, ver, var = hash_fn(ns, name) - - return (fmt('%s-%s-%s%s-%s%s-%s', sub(hash, 1, 8), - sub(hash, 9, 12), - ver, - sub(hash, 15, 16), - var, - sub(hash, 19, 20), - sub(hash, 21, 32))) - end - end - - - local function v3_hash(binary, name) - local hash = md5(binary .. name) - - return hash, - tohex(bor(band(hex_to_i(sub(hash, 13, 14)), 0x0F), 0x30), 2), - tohex(bor(band(hex_to_i(sub(hash, 17, 18)), 0x3F), 0x80), 2) - end - - - local function v5_hash(binary, name) - local hash = bin_tohex(sha1_bin(binary .. name)) - - return hash, - tohex(bor(band(hex_to_i(sub(hash, 13, 14)), 0x0F), 0x50), 2), - tohex(bor(band(hex_to_i(sub(hash, 17, 18)), 0x3F), 0x80), 2) - end - - - --- Instanciate a v3 UUID factory. - -- @function factory_v3 - -- Creates a closure generating namespaced v3 UUIDs. - -- @param[type=string] namespace (must be a valid UUID according to `is_valid`) - -- @treturn function `factory`: a v3 UUID generator. - -- @treturn string `err`: a string describing an error - -- @usage - -- local uuid = require 'resty.jit-uuid' - -- - -- local fact = assert(uuid.factory_v3('e6ebd542-06ae-11e6-8e82-bba81706b27d')) - -- - -- local u1 = fact('hello') - -- ---> 3db7a435-8c56-359d-a563-1b69e6802c78 - -- - -- local u2 = fact('foobar') - -- ---> e8d3eeba-7723-3b72-bbc5-8f598afa6773 - function _M.factory_v3(namespace) - return factory(namespace, v3_hash) - end - - - --- Instanciate a v5 UUID factory. - -- @function factory_v5 - -- Creates a closure generating namespaced v5 UUIDs. - -- @param[type=string] namespace (must be a valid UUID according to `is_valid`) - -- @treturn function `factory`: a v5 UUID generator. - -- @treturn string `err`: a string describing an error - -- @usage - -- local uuid = require 'resty.jit-uuid' - -- - -- local fact = assert(uuid.factory_v5('e6ebd542-06ae-11e6-8e82-bba81706b27d')) - -- - -- local u1 = fact('hello') - -- ---> 4850816f-1658-5890-8bfd-1ed14251f1f0 - -- - -- local u2 = fact('foobar') - -- ---> c9be99fc-326b-5066-bdba-dcd31a6d01ab - function _M.factory_v5(namespace) - return factory(namespace, v5_hash) - end - - - --- Generate a v3 UUID. - -- v3 UUIDs are created from a namespace and a name (a UUID and a string). - -- The same name and namespace result in the same UUID. The same name and - -- different namespaces result in different UUIDs, and vice-versa. - -- The resulting UUID is derived using MD5 hashing. - -- - -- This is a sugar function which instanciates a short-lived v3 UUID factory. - -- It is an expensive operation, and intensive generation using the same - -- namespaces should prefer allocating their own long-lived factory with - -- `factory_v3`. - -- - -- @param[type=string] namespace (must be a valid UUID according to `is_valid`) - -- @param[type=string] name - -- @treturn string `uuid`: a v3 (namespaced) UUID. - -- @treturn string `err`: a string describing an error - -- @usage - -- local uuid = require 'resty.jit-uuid' - -- - -- local u = uuid.generate_v3('e6ebd542-06ae-11e6-8e82-bba81706b27d', 'hello') - -- ---> 3db7a435-8c56-359d-a563-1b69e6802c78 - function _M.generate_v3(namespace, name) - local fact, err = _M.factory_v3(namespace) - if not fact then - return nil, err - end - - return fact(name) - end - - - --- Generate a v5 UUID. - -- v5 UUIDs are created from a namespace and a name (a UUID and a string). - -- The same name and namespace result in the same UUID. The same name and - -- different namespaces result in different UUIDs, and vice-versa. - -- The resulting UUID is derived using SHA-1 hashing. - -- - -- This is a sugar function which instanciates a short-lived v5 UUID factory. - -- It is an expensive operation, and intensive generation using the same - -- namespaces should prefer allocating their own long-lived factory with - -- `factory_v5`. - -- - -- @param[type=string] namespace (must be a valid UUID according to `is_valid`) - -- @param[type=string] name - -- @treturn string `uuid`: a v5 (namespaced) UUID. - -- @treturn string `err`: a string describing an error - -- @usage - -- local uuid = require 'resty.jit-uuid' - -- - -- local u = uuid.generate_v5('e6ebd542-06ae-11e6-8e82-bba81706b27d', 'hello') - -- ---> 4850816f-1658-5890-8bfd-1ed14251f1f0 - function _M.generate_v5(namespace, name) - local fact, err = _M.factory_v5(namespace) - if not fact then - return nil, err - end - - return fact(name) - end - - else - function _M.factory_v3() error('v3 UUID generation only supported in ngx_lua', 2) end - function _M.generate_v3() error('v3 UUID generation only supported in ngx_lua', 2) end - function _M.factory_v5() error('v5 UUID generation only supported in ngx_lua', 2) end - function _M.generate_v5() error('v5 UUID generation only supported in ngx_lua', 2) end - end -end - - -return setmetatable(_M, { - __call = _M.generate_v4 -}) \ No newline at end of file diff --git a/lib/skywalking/management.lua b/lib/skywalking/management.lua index 351b369..64e9fda 100644 --- a/lib/skywalking/management.lua +++ b/lib/skywalking/management.lua @@ -19,28 +19,22 @@ local _M = {} -- Return Services as service register parameter function _M.newReportInstanceProperties(serviceName, serviceInstance) - local instanceProperties = { - service = serviceName, - serviceInstance = serviceInstance, - properties = {} - } - local allProperties = { language = "Lua" } - instanceProperties.properties[#instanceProperties.properties + 1] = allProperties - - return instanceProperties + return { + service = serviceName, + serviceInstance = serviceInstance, + properties = {allProperties} + } end function _M.newServiceInstancePingPkg(serviceName, serviceInstance) - local serviceInstancePingPkg = { + return { service = serviceName, serviceInstance = serviceInstance, } - - return serviceInstancePingPkg end return _M diff --git a/lib/skywalking/segment_ref.lua b/lib/skywalking/segment_ref.lua index d4f1eae..c680da3 100644 --- a/lib/skywalking/segment_ref.lua +++ b/lib/skywalking/segment_ref.lua @@ -66,13 +66,13 @@ end -- Return string to represent this ref. function _M.serialize(ref) local encodedRef = '1' - encodedRef = encodedRef .. '-' .. encode_base64(ref.trace_id) - encodedRef = encodedRef .. '-' .. encode_base64(ref.segment_id) - encodedRef = encodedRef .. '-' .. ref.span_id - encodedRef = encodedRef .. '-' .. encode_base64(ref.parent_service) - encodedRef = encodedRef .. '-' .. encode_base64(ref.parent_service_instance) - encodedRef = encodedRef .. '-' .. encode_base64(ref.parent_endpoint) - encodedRef = encodedRef .. '-' .. encode_base64(ref.address_used_at_client) + .. '-' .. encode_base64(ref.trace_id) + .. '-' .. encode_base64(ref.segment_id) + .. '-' .. ref.span_id + .. '-' .. encode_base64(ref.parent_service) + .. '-' .. encode_base64(ref.parent_service_instance) + .. '-' .. encode_base64(ref.parent_endpoint) + .. '-' .. encode_base64(ref.address_used_at_client) return encodedRef end diff --git a/lib/skywalking/util.lua b/lib/skywalking/util.lua index 105856a..ca0d01c 100644 --- a/lib/skywalking/util.lua +++ b/lib/skywalking/util.lua @@ -80,19 +80,21 @@ local random_seed = function () return seed end -local newID = function() - return timestamp() .. '.' .. math.random(0, MAX_ID_PART2) .. '.' .. math.random(0, MAX_ID_PART3) -end math.randomseed(random_seed()) +local newID -- for Nginx Lua -local ok, uuid = pcall(require, "dependencies/lua-resty-jit-uuid") +local ok, uuid = pcall(require, "lua-resty-jit-uuid") if ok then uuid.seed() newID = function() return uuid.generate_v4() end +else + newID = function() + return timestamp() .. '.' .. math.random(0, MAX_ID_PART2) .. '.' .. math.random(0, MAX_ID_PART3) + end end _M.newID = newID diff --git a/skywalking-nginx-lua-1.0-0.rockspec b/skywalking-nginx-lua-1.0-0.rockspec index 458cc9c..0ec803c 100644 --- a/skywalking-nginx-lua-1.0-0.rockspec +++ b/skywalking-nginx-lua-1.0-0.rockspec @@ -18,7 +18,7 @@ dependencies = { build = { type = "builtin", modules = { - ["skywalking.management"] = "lib/skywalking/management.lua", + ["skywalking.register"] = "lib/skywalking/register.lua", ["skywalking.segment_ref"] = "lib/skywalking/segment_ref.lua", ["skywalking.segment"] = "lib/skywalking/segment.lua", ["skywalking.span_layer"] = "lib/skywalking/span_layer.lua", diff --git a/skywalking-nginx-lua-2.0-0.rockspec b/skywalking-nginx-lua-2.0-0.rockspec new file mode 100644 index 0000000..b44f819 --- /dev/null +++ b/skywalking-nginx-lua-2.0-0.rockspec @@ -0,0 +1,30 @@ +package = "skywalking-nginx-lua" +version = "2.0-0" +source = { + url = "git://github.com/apache/skywalking-nginx-lua", + branch = "master", +} + +description = { + summary = "The Nginx Lua agent for Apache SkyWalking", + homepage = "https://github.com/apache/skywalking-nginx-lua", + license = "Apache License 2.0" +} + +dependencies = { + "lua-resty-http = 0.15" + "lua-resty-jit-uuid = 0.0.7" +} + +build = { + type = "builtin", + modules = { + ["skywalking.management"] = "lib/skywalking/management.lua", + ["skywalking.segment_ref"] = "lib/skywalking/segment_ref.lua", + ["skywalking.segment"] = "lib/skywalking/segment.lua", + ["skywalking.span_layer"] = "lib/skywalking/span_layer.lua", + ["skywalking.span"] = "lib/skywalking/span.lua", + ["skywalking.tracing_context"] = "lib/skywalking/tracing_context.lua", + ["skywalking.util"] = "lib/skywalking/util.lua", + } +} From cb29810cbc92ba9270ad7f15bac5d6d24552583b Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Tue, 7 Apr 2020 17:59:49 +0800 Subject: [PATCH 18/21] adding the required lib on document --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7e31525..ab2c756 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,7 @@ All codes in the `lib/skywalking` require the `*_test.lua` to do the UnitTest. T The following libs are required in runtime or test cases, please use `LuaRocks` to install them. - lua-cjson. NOTICE, some platforms such as MacOS 10.15 may have issue with the latest release of this lib, consider to install an old release.(`luarocks install lua-cjson 2.1.0-1`) - luaunit +- lua-resty-jit-uuid # APIs This LUA tracing lib is originally designed for Nginx+LUA/OpenResty ecosystems. But we write it to support more complex cases. From 0e2f678186a4a709fe9597f29c3ef807fac55eae Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Tue, 7 Apr 2020 18:31:35 +0800 Subject: [PATCH 19/21] fix uuid error --- LICENSE | 3 +- lib/skywalking/resty/jit-uuid.lua | 425 ++++++++++++++++++++++++++++++ lib/skywalking/util.lua | 2 +- 3 files changed, 427 insertions(+), 3 deletions(-) create mode 100644 lib/skywalking/resty/jit-uuid.lua diff --git a/LICENSE b/LICENSE index 7d17ec7..7b2bcf4 100644 --- a/LICENSE +++ b/LICENSE @@ -216,8 +216,7 @@ The following components are provided under a MIT license. See project link for The text of each license is also included at licenses/LICENSE-[project].txt. base64 dependencies/base64.lua https://github.com/iskolbin/lbase64 MIT - lua-resty-jit-uuid dependencies/lua-resty-jit-uuid.lua https://github.com/thibaultcha/lua-resty-jit-uuid MIT - + lua-resty-jit-uuid lib/resty/jit-uuid.lua https://github.com/thibaultcha/lua-resty-jit-uuid MIT ======================================================================== BSD 2-Clause License diff --git a/lib/skywalking/resty/jit-uuid.lua b/lib/skywalking/resty/jit-uuid.lua new file mode 100644 index 0000000..f101009 --- /dev/null +++ b/lib/skywalking/resty/jit-uuid.lua @@ -0,0 +1,425 @@ +--- jit-uuid +-- Fast and dependency-free UUID library for LuaJIT/ngx_lua. +-- @module jit-uuid +-- @author Thibault Charbonnier +-- @license MIT +-- @release 0.0.7 + + +local bit = require 'bit' + + +local tohex = bit.tohex +local band = bit.band +local bor = bit.bor + + +local _M = { + _VERSION = '0.0.7' +} + + +---------- +-- seeding +---------- + + +--- Seed the random number generator. +-- Under the hood, this function calls `math.randomseed`. +-- It makes sure to use the most appropriate seeding technique for +-- the current environment, guaranteeing a unique seed. +-- +-- To guarantee unique UUIDs, you must have correctly seeded +-- the Lua pseudo-random generator (with `math.randomseed`). +-- You are free to seed it any way you want, but this function +-- can do it for you if you'd like, with some added guarantees. +-- +-- @param[type=number] seed (Optional) A seed to use. If none given, will +-- generate one trying to use the most appropriate technique. +-- @treturn number `seed`: the seed given to `math.randomseed`. +-- @usage +-- local uuid = require 'resty.jit-uuid' +-- uuid.seed() +-- +-- -- in ngx_lua, seed in the init_worker context: +-- init_worker_by_lua { +-- local uuid = require 'resty.jit-uuid' +-- uuid.seed() +-- } +function _M.seed(seed) + if not seed then + if ngx then + seed = ngx.time() + ngx.worker.pid() + + elseif package.loaded['socket'] and package.loaded['socket'].gettime then + seed = package.loaded['socket'].gettime()*10000 + + else + seed = os.time() + end + end + + math.randomseed(seed) + + return seed +end + + +------------- +-- validation +------------- + + +do + if ngx and string.find(ngx.config.nginx_configure(),'--with-pcre-jit',nil,true) then + local type = type + local re_find = ngx.re.find + local regex = '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' + + + --- Validate a string as a UUID. + -- To be considered valid, a UUID must be given in its canonical + -- form (hexadecimal digits including the hyphen characters). + -- This function validates UUIDs disregarding their generation algorithm, + -- and in a case-insensitive manner, but checks the variant field. + -- + -- Use JIT PCRE if available in OpenResty or fallbacks on Lua patterns. + -- + -- @param[type=string] str String to verify. + -- @treturn boolean `valid`: true if valid UUID, false otherwise. + -- @usage + -- local uuid = require 'resty.jit-uuid' + -- + -- uuid.is_valid 'cbb297c0-a956-486d-ad1d-f9bZZZZZZZZZ' --> false + -- uuid.is_valid 'cbb297c0-a956-486d-dd1d-f9b42df9465a' --> false (invalid variant) + -- uuid.is_valid 'cbb297c0a956486dad1df9b42df9465a' --> false (no dashes) + -- uuid.is_valid 'cbb297c0-a956-486d-ad1d-f9b42df9465a' --> true + function _M.is_valid(str) + -- it has proven itself efficient to first check the length with an + -- evenly distributed set of valid and invalid uuid lengths. + if type(str) ~= 'string' or #str ~= 36 then + return false + end + + return re_find(str, regex, 'ioj') ~= nil + end + + else + local match = string.match + local d = '[0-9a-fA-F]' + local p = '^' .. table.concat({ + d:rep(8), + d:rep(4), + d:rep(4), + '[89ab]' .. d:rep(3), + d:rep(12) + }, '%-') .. '$' + + + function _M.is_valid(str) + if type(str) ~= 'string' or #str ~= 36 then + return false + end + + return match(str, p) ~= nil + end + end +end + + +---------------- +-- v4 generation +---------------- + + +do + local fmt = string.format + local random = math.random + + + --- Generate a v4 UUID. + -- v4 UUIDs are created from randomly generated numbers. + -- + -- @treturn string `uuid`: a v4 (randomly generated) UUID. + -- @usage + -- local uuid = require 'resty.jit-uuid' + -- + -- local u1 = uuid() ---> __call metamethod + -- local u2 = uuid.generate_v4() + function _M.generate_v4() + return (fmt('%s%s%s%s-%s%s-%s%s-%s%s-%s%s%s%s%s%s', + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + + tohex(bor(band(random(0, 255), 0x0F), 0x40), 2), + tohex(random(0, 255), 2), + + tohex(bor(band(random(0, 255), 0x3F), 0x80), 2), + tohex(random(0, 255), 2), + + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + tohex(random(0, 255), 2), + tohex(random(0, 255), 2))) + end +end + + +---------------- +-- v3/v5 generation +---------------- + + +do + if ngx then + local ffi = require 'ffi' + + + local tonumber = tonumber + local assert = assert + local error = error + local concat = table.concat + local type = type + local char = string.char + local fmt = string.format + local sub = string.sub + local gmatch = ngx.re.gmatch + local sha1_bin = ngx.sha1_bin + local md5 = ngx.md5 + local C = ffi.C + local ffi_new = ffi.new + local ffi_str = ffi.string + local ffi_cast = ffi.cast + local new_tab + do + local ok + ok, new_tab = pcall(require, 'table.new') + if not ok then + new_tab = function(narr, nrec) return {} end + end + end + + + ffi.cdef [[ + typedef unsigned char u_char; + typedef intptr_t ngx_int_t; + + u_char * ngx_hex_dump(u_char *dst, const u_char *src, size_t len); + ngx_int_t ngx_hextoi(u_char *line, size_t n); + ]] + + + local str_type = ffi.typeof('uint8_t[?]') + local u_char_type = ffi.typeof('u_char *') + + + local function bin_tohex(s) + local slen = #s + local blen = slen * 2 + local buf = ffi_new(str_type, blen) + + C.ngx_hex_dump(buf, s, slen) + + return ffi_str(buf, blen) + end + + + local function hex_to_i(s) + local buf = ffi_cast(u_char_type, s) + + local n = tonumber(C.ngx_hextoi(buf, #s)) + if n == -1 then + error("could not convert hex to number") + end + + return n + end + + + local buf = new_tab(16, 0) + + + local function factory(namespace, hash_fn) + if not _M.is_valid(namespace) then + return nil, 'namespace must be a valid UUID' + end + + local i = 0 + local iter, err = gmatch(namespace, [[([\da-f][\da-f])]]) + if not iter then + return nil, 'could not create iter: ' .. err + end + + while true do + local m, err = iter() + if err then + return nil, err + end + + if not m then + break + end + + i = i + 1 + buf[i] = char(tonumber(m[0], 16)) + end + + assert(i == 16, "invalid binary namespace buffer length") + local ns = concat(buf) + + return function(name) + if type(name) ~= 'string' then + return nil, 'name must be a string' + end + + local hash, ver, var = hash_fn(ns, name) + + return (fmt('%s-%s-%s%s-%s%s-%s', sub(hash, 1, 8), + sub(hash, 9, 12), + ver, + sub(hash, 15, 16), + var, + sub(hash, 19, 20), + sub(hash, 21, 32))) + end + end + + + local function v3_hash(binary, name) + local hash = md5(binary .. name) + + return hash, + tohex(bor(band(hex_to_i(sub(hash, 13, 14)), 0x0F), 0x30), 2), + tohex(bor(band(hex_to_i(sub(hash, 17, 18)), 0x3F), 0x80), 2) + end + + + local function v5_hash(binary, name) + local hash = bin_tohex(sha1_bin(binary .. name)) + + return hash, + tohex(bor(band(hex_to_i(sub(hash, 13, 14)), 0x0F), 0x50), 2), + tohex(bor(band(hex_to_i(sub(hash, 17, 18)), 0x3F), 0x80), 2) + end + + + --- Instanciate a v3 UUID factory. + -- @function factory_v3 + -- Creates a closure generating namespaced v3 UUIDs. + -- @param[type=string] namespace (must be a valid UUID according to `is_valid`) + -- @treturn function `factory`: a v3 UUID generator. + -- @treturn string `err`: a string describing an error + -- @usage + -- local uuid = require 'resty.jit-uuid' + -- + -- local fact = assert(uuid.factory_v3('e6ebd542-06ae-11e6-8e82-bba81706b27d')) + -- + -- local u1 = fact('hello') + -- ---> 3db7a435-8c56-359d-a563-1b69e6802c78 + -- + -- local u2 = fact('foobar') + -- ---> e8d3eeba-7723-3b72-bbc5-8f598afa6773 + function _M.factory_v3(namespace) + return factory(namespace, v3_hash) + end + + + --- Instanciate a v5 UUID factory. + -- @function factory_v5 + -- Creates a closure generating namespaced v5 UUIDs. + -- @param[type=string] namespace (must be a valid UUID according to `is_valid`) + -- @treturn function `factory`: a v5 UUID generator. + -- @treturn string `err`: a string describing an error + -- @usage + -- local uuid = require 'resty.jit-uuid' + -- + -- local fact = assert(uuid.factory_v5('e6ebd542-06ae-11e6-8e82-bba81706b27d')) + -- + -- local u1 = fact('hello') + -- ---> 4850816f-1658-5890-8bfd-1ed14251f1f0 + -- + -- local u2 = fact('foobar') + -- ---> c9be99fc-326b-5066-bdba-dcd31a6d01ab + function _M.factory_v5(namespace) + return factory(namespace, v5_hash) + end + + + --- Generate a v3 UUID. + -- v3 UUIDs are created from a namespace and a name (a UUID and a string). + -- The same name and namespace result in the same UUID. The same name and + -- different namespaces result in different UUIDs, and vice-versa. + -- The resulting UUID is derived using MD5 hashing. + -- + -- This is a sugar function which instanciates a short-lived v3 UUID factory. + -- It is an expensive operation, and intensive generation using the same + -- namespaces should prefer allocating their own long-lived factory with + -- `factory_v3`. + -- + -- @param[type=string] namespace (must be a valid UUID according to `is_valid`) + -- @param[type=string] name + -- @treturn string `uuid`: a v3 (namespaced) UUID. + -- @treturn string `err`: a string describing an error + -- @usage + -- local uuid = require 'resty.jit-uuid' + -- + -- local u = uuid.generate_v3('e6ebd542-06ae-11e6-8e82-bba81706b27d', 'hello') + -- ---> 3db7a435-8c56-359d-a563-1b69e6802c78 + function _M.generate_v3(namespace, name) + local fact, err = _M.factory_v3(namespace) + if not fact then + return nil, err + end + + return fact(name) + end + + + --- Generate a v5 UUID. + -- v5 UUIDs are created from a namespace and a name (a UUID and a string). + -- The same name and namespace result in the same UUID. The same name and + -- different namespaces result in different UUIDs, and vice-versa. + -- The resulting UUID is derived using SHA-1 hashing. + -- + -- This is a sugar function which instanciates a short-lived v5 UUID factory. + -- It is an expensive operation, and intensive generation using the same + -- namespaces should prefer allocating their own long-lived factory with + -- `factory_v5`. + -- + -- @param[type=string] namespace (must be a valid UUID according to `is_valid`) + -- @param[type=string] name + -- @treturn string `uuid`: a v5 (namespaced) UUID. + -- @treturn string `err`: a string describing an error + -- @usage + -- local uuid = require 'resty.jit-uuid' + -- + -- local u = uuid.generate_v5('e6ebd542-06ae-11e6-8e82-bba81706b27d', 'hello') + -- ---> 4850816f-1658-5890-8bfd-1ed14251f1f0 + function _M.generate_v5(namespace, name) + local fact, err = _M.factory_v5(namespace) + if not fact then + return nil, err + end + + return fact(name) + end + + else + function _M.factory_v3() error('v3 UUID generation only supported in ngx_lua', 2) end + function _M.generate_v3() error('v3 UUID generation only supported in ngx_lua', 2) end + function _M.factory_v5() error('v5 UUID generation only supported in ngx_lua', 2) end + function _M.generate_v5() error('v5 UUID generation only supported in ngx_lua', 2) end + end +end + + +return setmetatable(_M, { + __call = _M.generate_v4 +}) \ No newline at end of file diff --git a/lib/skywalking/util.lua b/lib/skywalking/util.lua index ca0d01c..b16ecf2 100644 --- a/lib/skywalking/util.lua +++ b/lib/skywalking/util.lua @@ -85,7 +85,7 @@ math.randomseed(random_seed()) local newID -- for Nginx Lua -local ok, uuid = pcall(require, "lua-resty-jit-uuid") +local ok, uuid = pcall(require, "resty.jit-uuid") if ok then uuid.seed() newID = function() From e8913ebd53cf0af06b6818f6cbcc84bf2e0fc57b Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Wed, 8 Apr 2020 19:00:51 +0800 Subject: [PATCH 20/21] fix properties data format --- lib/skywalking/management.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/skywalking/management.lua b/lib/skywalking/management.lua index 64e9fda..ccca53e 100644 --- a/lib/skywalking/management.lua +++ b/lib/skywalking/management.lua @@ -20,7 +20,8 @@ local _M = {} -- Return Services as service register parameter function _M.newReportInstanceProperties(serviceName, serviceInstance) local allProperties = { - language = "Lua" + key = "language", + value = "lua" } return { From ed625cae7a7ae5c02a028439dc7cd60efcfa2b17 Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Thu, 9 Apr 2020 15:20:11 +0800 Subject: [PATCH 21/21] add adapt backend version explain --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index ab2c756..87b9ba6 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,9 @@ http { # Download Please head to the [releases page](http://skywalking.apache.org/downloads/) to download a release of Apache SkyWalking. +* 0.1.0 release requires SkyWalking 7 +* 0.2.0+ releases require SkyWalking 8 + # Compatible backend SkyWalking OAP begins to support LUA agent in 7.0.0 release.