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

        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())
                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())
                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.ctx.exitSpan = nil
                end
            }

            log_by_lua_block {
                if ngx.ctx.entrySpan ~= nil then
                    ngx.ctx.entrySpan:finish()
                    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
            }
        }

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

        location /skywalking/register/service {
            default_type text/html;
            content_by_lua_block {
                local registeredInfo = {}
                registeredInfo[1] = {key="Service Name", value=1}
                ngx.say(require('cjson').encode(registeredInfo))
            }
        }
    }
}