For this document it is assumed that:
- You have a working
go
environment - You can compile and run the
nrdiag
project - You are working off a fork of newrelic-diagnostics-cli
This doc only goes over the minimal mechanics to get a task up and running.
As you read through, you are welcome to substitute the names/locations with ones that are more meaningful to the task you are writing. However, if you run into issues it is strongly encouraged that you follow the steps more verbatim to make sure something didn't get missed; you can rename things again after finishing out the steps here.
For this HOW-TO we'll create a task that checks on how our coffee at work tastes. Looking at the folder structure already in the project, it seems the best place to put our new task would be in the java
folder. Since our coffee maker can produce different brews the correct sub-folder might be jvm
; which obviously stands for "Java Varieties Maker".
The name of the task is often a verb or adjective... think about what your task is doing when it runs or what it describes about the system. In this case, our task will be tasting coffee, so we'll just use "taste" as the name of the task. (We could call it "coffee taster" for the name, but since we're already in the Java category, that seems redundant.)
However, someone else might want to have a task to check the flavor of hot chocolate, so for clarity we're going to name the task in code after the folder structure we're storing it: JavaJVMTaste
seems short and descriptive, that's good!
Make a copy of ./tasks/example/template/minimal_task.go
into ./tasks/java/jvm/taste.go
(note how the task name we choose lines up with the folder structure and filename).
We've got a file, but it still has all the original example names
- Open up your new
taste.go
file. - Look at the first line, where the
package
is defined, and replacetemplate
withjvm
(the package name will always match the folder we're in). - Do a search for
ExampleTemplateMinimalTask
and replace it withJavaJVMTaste
- there should be 5 of these in code and 1 in a comment. (Be sure to replace the comment as well.) - Find the
Identifier()
function and replace"Example/Template/MinimalTask"
with"Java/JVM/Taste"
- Find the
Explain()
method and replace the string being returned with"Samples all the coffee varieties to make sure they taste good."
Now we have a task that doesn't do much, but we should at least be able to compile and run it. However, the Diagnostics CLI doesn't know that it's supposed to run this task yet. So, we have to "register" the new task (note: this registration step is unique to this project; it's not a normal go
thing).
Find the "main" package file for the package/folder your task is in. In our case, this is going to be the file ./tasks/java/jvm/jvm.go
In that file, add another line at the end of the RegisterWith
method:
registrationFunc(JavaJVMTaste{}, true)
Note: if your task is not one that should be run by default, change the true
to false
- the rest of these steps should work fine either way.
From the main directory of the project, type:
go build && ./newrelic-diagnostics-cli -t Java/JVM/Taste
You should see a result that looks something like:
Check Results
-------------------------------------------------
1 results not shown: 1 None
No Issues Found
Whew! Done with the "paperwork"... we can finally get started on the actual task.
If you are getting a compile error, it's likely there is a minor typo somewhere in taste.go
- you'll have to read the compiler complaints and see if you can work out what's wrong.
If it compiled and your result looked more like this:
Check Results
-------------------------------------------------
No valid tasks found! (If you used a '*' with the -t option, be sure to quote or escape the string.)
No Issues Found
This probably means that either:
- Your new task isn't registered correctly in the
jvm.go
file - The name specified on the command line doesn't match what is returned by the
Identifier()
method
You might get a hint of what went wrong by looking at the help screen that lists all registered tasks.
./newrelic-diagnostics-cli -h tasks
Along with all the other output, you should see:
|- Java
| |- Config
| | \- Agent - Detects if the Java agent is installed.
| |
| \- JVM
| |- SysPropCollect - Collects the command line options for each JVM with a running NR Java Agent.
| \- Taste - Samples all the coffee varieties to make sure they taste good.
Go find the Execute()
method. There is a lot of stuff passed in, but we're not going to look at that now. The only thing we care about is that we have to return a Result
.
You should see this:
result := tasks.Result{
Status: tasks.None,
Summary: "I succeeded in doing nothing.",
}
Keep that; it just declares a variable that we'll fill with data and return later. For example, the next line:
return result
Let's do something a little more interesting... let's figure out where we're running from. After all, your perspective can influence your taste for coffee. Try adding this code in between the variable declaration and the return statement:
if hostname, _ := os.Hostname(); hostname == "teapot" {
result.Status = tasks.Failure
result.Summary = "I'm a teapot."
result.URL = "https://httpstatuses.com/418"
result.Payload = 418
} else {
result.Status = tasks.Success
result.Summary = "Everyone likes coffee!"
result.Payload = []string{
"Caffeinated",
"With milk and cream",
"Decaf",
}
}
Note: If you are using gofmt
(or an editor extension that calls it) then you might notice that "os"
shows up in the import
statement at the top of the file. Gofmt recognizes that we referred to the os
package in this new block of code and automatically adds the necessary import.
If you are not running gofmt
... you should. (No really, we want consistency!) But, in the mean time, you can add the import manually to get it to compile.
Run the same commands as above, you should see:
Check Results
-------------------------------------------------
Java/JVM/Taste: Success
No Issues Found
However, if your hostname happens to be "teapot" you'd see:
Check Results
-------------------------------------------------
Java/JVM/Taste: Failure
Issues Found
-------------------------------------------------
Failure
I am a teapot.
See https://httpstatuses.com/418 for more information.
Feel free to change the hostname specified in the if
statement to see if you can get both results.
True... we never removed the default result even though logically it can never be returned. Generally it's a good idea to initialize your variables as a safety measure (yes, go will do that for you, but in our case it doesn't set a reasonable default). Especially while testing you should leave that in - although change the Summary message!. This will help you catch completeness errors for different conditions.
In fact, let's change that message now from "I succeeded in doing nothing."
to "There was no coffee to taste."
. This is a reasonable response if something edge case in our code allows it to complete without setting a new status or summary.
Don't forget to add tests to your Task. For more details about tests, see TESTING.md
We're done with this example!
There are a lot of additional things you can try. Check out our other examples for some ideas and more sample code.
dependent_task.go
- only looks at the status of the dependency to make a decision
dependent_payload_task.go
- uses a type assertion to read the payload of the dependency
See the type assertion logic in dependent_payload_task.go
custom_payload_task.go
custom_payload_json_task.go
copy_files_task.go