# 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.

# This nginx.conf is designed and written for local dev environments
# It will use the blocking startup mode and console logging
worker_processes  1;
daemon off;
error_log /dev/stdout debug;

events {
    worker_connections 1024;
}
http {
    lua_package_path "/Users/wusheng/Documents/GitHub/skywalking-nginx-lua/lib/skywalking/?.lua;;";
    # Buffer represents the register inform and the queue of the finished segment 
    lua_shared_dict tracing_buffer 100m;
    
    # Init is the timer setter and keeper
    # Setup an infinite loop timer to do register and trace report.
    init_worker_by_lua_block {
        local metadata_buffer = ngx.shared.tracing_buffer
        metadata_buffer['serviceName'] = 'Service Name'
        metadata_buffer['serviceInstanceName'] = 'Service Instance Name'

        require("client"):startTimer(metadata_buffer, "http://127.0.0.1:8080/skywalking")
    }

    server {
        listen 8080;

        # This is for local dev only, please do not add this in any production env.
        lua_code_cache off;

        location /ingress {
            default_type text/html;

            rewrite_by_lua_block {
                local TC = require('tracing_context')
                local Layer = require('span_layer')

                local metadata_buffer = ngx.shared.tracing_buffer
                -- Mock the service instance id
                metadata_buffer['serviceId'] = 1
                metadata_buffer['serviceInstId'] = 1

                local tracingContext
                if metadata_buffer['serviceInstId'] ~= nil then
                    tracingContext = TC:new(metadata_buffer['serviceId'], metadata_buffer['serviceInstId'])
                else
                    tracingContext = TC:newNoOP()
                end

                -- Constant pre-defined in SkyWalking main repo
                -- 84 represents Nginx
                local nginxComponentId = 6000

                local contextCarrier = {}
                contextCarrier["sw6"] = ngx.req.get_headers()["sw6"]
                local entrySpan = tracingContext:createEntrySpan(ngx.var.uri, nil, contextCarrier)
                entrySpan:start(ngx.now() * 1000)
                entrySpan:setComponentId(nginxComponentId)
                entrySpan:setLayer(Layer.HTTP)
                
                entrySpan:tag('http.method', ngx.req.get_method())
                entrySpan:tag('http.params', ngx.var.scheme .. '://' .. ngx.var.host .. ngx.var.request_uri )
                
                contextCarrier = {}
                -- Use the same URI to represent incoming and forwarding requests
                -- Change it if you need.
                local upstreamUri = ngx.var.uri
                ------------------------------------------------------
                -- NOTICE, this should be changed manually
                -- This variable represents the upstream logic address
                -- Please set them as service logic name or DNS name
                ------------------------------------------------------
                local upstreamServerName = "upstream_ip:port"
                ------------------------------------------------------
                local exitSpan = tracingContext:createExitSpan(upstreamUri, entrySpan, upstreamServerName, contextCarrier)
                exitSpan:start(ngx.now() * 1000)
                exitSpan:setComponentId(nginxComponentId)
                exitSpan:setLayer(Layer.HTTP)
                
                for name, value in pairs(contextCarrier) do
                    ngx.req.set_header(name, value)
                end

                -- Push the data in the context
                ngx.ctx.tracingContext = tracingContext
                ngx.ctx.entrySpan = entrySpan
                ngx.ctx.exitSpan = exitSpan
            }

            proxy_pass http://127.0.0.1:8080/backend;

            body_filter_by_lua_block {
                -- Finish the exit span when received the first response package from upstream
                if ngx.ctx.exitSpan ~= nil then
                    ngx.ctx.exitSpan:finish(ngx.now() * 1000)
                    ngx.ctx.exitSpan = nil
                end
            }

            log_by_lua_block {
                if ngx.ctx.entrySpan ~= nil then
                    ngx.ctx.entrySpan:finish(ngx.now() * 1000)
                    local status, segment = ngx.ctx.tracingContext:drainAfterFinished()
                    if status then
                        local segmentJson = require('cjson').encode(segment:transform())
                        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'))
                    end
                end
            }
        }

        # ------------------------------------------------------
        # -- Mock backend business service as the upsteeam
        # ------------------------------------------------------
        location /backend {
            default_type text/html;
            content_by_lua_block {
                ngx.say("<p>Backend service for testing only.</p>")
                ngx.say("<p>Backend sw6 received headers: " .. ngx.req.get_headers()["sw6"] .. "</p>")
            }
        }


        # ------------------------------------------------------
        # -- Mock OAP server to provide register and trace collection
        # ------------------------------------------------------
        location /v2/service/register {
            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;

            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))
            }
        }
    }
}