Application Entry Point#
In Go, the main()
function is the entry point of the binary application and is defined in the main.go
file of our application:
Application version#
As you can see, the main
function is rather simple. First, we handle the version
CLI flag to make sure our application can return its version when asked.
Application config has a version-command
field that indicates which command needs to be executed to get the application version. In our case, the version
field is set to greeter --version
and we just went through the handler of this flag.
In SR Linux CLI we can get the version of the greeter
app by executing the greeter --version
command:
--{ + running }--[ ]--
A:greeter# show system application greeter
+---------+------+---------+-------------+--------------------------+
| Name | PID | State | Version | Last Change |
+=========+======+=========+=============+==========================+
| greeter | 4676 | running | dev-a6f880b | 2023-11-29T21:29:04.243Z |
+---------+------+---------+-------------+--------------------------+
Why the version is dev-a6f880b
?
Attentive readers might have noticed that the version of the greeter
app is dev-a6f880b
instead of v0.0.0-
following the version
and commit
variables values in main.go
file. This is because we setting the values for these variables at build time using the Go linker flags in the run.sh
script:
These variables are then set to the correct values when we build the application with Goreleaser.
Setting up the Logger#
Logging is an important part of any application. It aids the developer in debugging the application and provides valuable information about the application's state for its users.
We create the logger before initializing the application so that we can pass it to the application and use it to log the application's state.
Logging from the NDK application is a separate topic that is covered in the Logging section of this guide.
Context, gRPC Requests and Metadata#
Moving down the main
function, we create the context that will drive the lifecycle of our greeter application.
Once the context is created we attach the metadata to it. The metadata is a map of key-value pairs that will be sent along with the gRPC requests.
The NDK service uses the metadata to identify the application from which the request was sent.
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ctx = metadata.AppendToOutgoingContext(ctx, "agent_name", greeter.AppName)
The metadata must be attached to the parent context and it should has the agent_name
key with the value of the application name. The application name in the metadata doesn't have to match anything, but should be unique among all the applications that are registered with the Application Manager.
Exit Handler#
Another important part of the application lifecycle is the exit handler. In the context of the NDK application life cycle the exit handler is a function that is called when the application receives Interrupt or SIGTERM signals.
The exit handler is a good place to perform cleanup actions like closing the open connections, releasing resources, etc.
We execute exitHandler
function passing it the cancel function of the context:
This function is non-blocking as it spawns a goroutine that waits for the registered signals and then execute the cancel
function of the context. This will propagate the cancellation signal to all the child contexts and our application reacts to it.
greeter/app.go | |
---|---|
We will cover the func (a *App) Start()
function properly when we get there, but for now, it is important to highlight how cancellation of the main context is intercepted in this function and leading to a.stop()
call.
The a.stop()
function is responsible to perform the graceful shutdown of the application.
Following the Graceful Exit section we first unregister the agent with the NDK manager and then closing all connections that our app had opened.
Initializing the Application#
And finally in the main function we initialize the greeter application and start it:
This is where the application logic starts to kick in. Let's turn the page and start digging into it in the next chapter.