Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add templating for title and message fields #1057

Closed
wants to merge 10 commits into from

Conversation

wunter8
Copy link
Contributor

@wunter8 wunter8 commented Mar 18, 2024

Here's an initial working implementation, based on #171.

Right now, only the message and title fields can be templated, each using their own header (since this seemed like the quickest way to get something working).

In a future iteration, I think allowing other fields to be templated (e.g., priority, actions, attachment url, topic?, etc.) would be cool.

In that version, I was imagining an X-Template header that includes probably a JSON string for the different fields of a message (e.g., {"message":"${field.value} is ${field2}", "title":"An error occurred on ${hostname}", "priority":${error.level}, "attachment":"${error.screenshot.url}"})

@wunter8
Copy link
Contributor Author

wunter8 commented Mar 19, 2024

I updated the code to use the existing message and title fields.

Right now, if the message body is not valid JSON, the message and title fields will just contain the original template placeholders without anything being replaced and without any errors thrown. Let me know if you think this should change. (See line 2671 of server/server_test.go for an example (TestServer_MessageTemplate_MalformedJSONBody))

@codecov-commenter
Copy link

codecov-commenter commented Mar 19, 2024

Codecov Report

Attention: Patch coverage is 90.90909% with 4 lines in your changes are missing coverage. Please review.

Project coverage is 64.93%. Comparing base (4c0ec3f) to head (83356f5).

Files Patch % Lines
server/server.go 90.90% 3 Missing and 1 partial ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1057      +/-   ##
==========================================
+ Coverage   64.86%   64.93%   +0.06%     
==========================================
  Files          60       60              
  Lines        7944     7965      +21     
==========================================
+ Hits         5153     5172      +19     
- Misses       1930     1931       +1     
- Partials      861      862       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Owner

@binwiederhier binwiederhier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fantastic. Very simple and elegant.

The docs should include lots of real world examples; I can do that when I merge it in. Great work!

server/server.go Outdated Show resolved Hide resolved
server/server.go Outdated Show resolved Hide resolved
server/server.go Outdated Show resolved Hide resolved
server/server.go Outdated Show resolved Hide resolved
server/server.go Outdated
query := v[1]
result := gjson.Get(peakedBody, query)
if result.Exists() {
m.Message = strings.ReplaceAll(m.Message, fmt.Sprintf("${%s}", query), result.String())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if result is a number or an array?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works fine. See TestServer_MessageTemplate_FancyGJSON (server/server_test.go:L2742)

@binwiederhier
Copy link
Owner

You should link https://gjson.dev/ in the docs. It's awesome.

Here's a real Grafana alert that I get for ntfy sometimes:

{"receiver":"ntfy\\.example\\.com/alerts","status":"resolved","alerts":[{"status":"resolved","labels":{"alertname":"Load avg 15m too high","grafana_folder":"Node alerts","instance":"10.108.0.2:9100","job":"node-exporter"},"annotations":{"summary":"15m load average too high"},"startsAt":"2024-03-15T02:28:00Z","endsAt":"2024-03-15T02:42:00Z","generatorURL":"localhost:3000/alerting/grafana/NW9oDw-4z/view","fingerprint":"becbfb94bd81ef48","silenceURL":"localhost:3000/alerting/silence/new?alertmanager=grafana\u0026matcher=alertname%3DLoad+avg+15m+too+high\u0026matcher=grafana_folder%3DNode+alerts\u0026matcher=instance%3D10.108.0.2%3A9100\u0026matcher=job%3Dnode-exporter","dashboardURL":"","panelURL":"","values":{"B":18.98211314475876,"C":0},"valueString":"[ var='B' labels={__name__=node_load15, instance=10.108.0.2:9100, job=node-exporter} value=18.98211314475876 ], [ var='C' labels={__name__=node_load15, instance=10.108.0.2:9100, job=node-exporter} value=0 ]"}],"groupLabels":{"alertname":"Load avg 15m too high","grafana_folder":"Node alerts"},"commonLabels":{"alertname":"Load avg 15m too high","grafana_folder":"Node alerts","instance":"10.108.0.2:9100","job":"node-exporter"},"commonAnnotations":{"summary":"15m load average too high"},"externalURL":"localhost:3000/","version":"1","groupKey":"{}:{alertname=\"Load avg 15m too high\", grafana_folder=\"Node alerts\"}","truncatedAlerts":0,"orgId":1,"title":"[RESOLVED] Load avg 15m too high Node alerts (10.108.0.2:9100 node-exporter)","state":"ok","message":"**Resolved**\n\nValue: B=18.98211314475876, C=0\nLabels:\n - alertname = Load avg 15m too high\n - grafana_folder = Node alerts\n - instance = 10.108.0.2:9100\n - job = node-exporter\nAnnotations:\n - summary = 15m load average too high\nSource: localhost:3000/alerting/grafana/NW9oDw-4z/view\nSilence: localhost:3000/alerting/silence/new?alertmanager=grafana\u0026matcher=alertname%3DLoad+avg+15m+too+high\u0026matcher=grafana_folder%3DNode+alerts\u0026matcher=instance%3D10.108.0.2%3A9100\u0026matcher=job%3Dnode-exporter\n"}

Untested, but I think:

https://ntfy.sh/mytopic?template=yes&title=Grafana+alert:+%24%28title%29&message=%24%28message%29

Would lead to this:

Title:

[RESOLVED] Load avg 15m too high Node alerts (10.108.0.2:9100 node-exporter)

Message:

**Resolved**

Value: B=18.98211314475876, C=0
Labels:
 - alertname = Load avg 15m too high
 - grafana_folder = Node alerts
 - instance = 10.108.0.2:9100
 - job = node-exporter
Annotations:
 - summary = 15m load average too high
Source: localhost:3000/alerting/grafana/NW9oDw-4z/view
Silence: localhost:3000/alerting/silence/new?alertmanager=grafana\u0026matcher=alertname%3DLoad+avg+15m+too+high\u0026matcher=grafana_folder%3DNode+alerts\u0026matcher=instance%3D10.108.0.2%3A9100\u0026matcher=job%3Dnode-exporter

@binwiederhier
Copy link
Owner

So elegant and simple. Well done. I'll merge it tomorrow

@wunter8
Copy link
Contributor Author

wunter8 commented Mar 20, 2024

Please have a look at the latest commit (dealing with message sizes). All of the tests still pass, and I added specific message size tests, so I don't think I broke anything. But another set of eyes is always good.

I think adding a custom GJSON modifier to the code would allow us to match values of the HTTP body and convert it to a priority level. I think including that in a separate PR might be good, though. We can release this and people can start using it before we add anything more.

server/server.go Outdated
}
call = readParam(r, "x-call", "call")
if call != "" && (s.config.TwilioAccount == "" || s.userManager == nil) {
return false, false, "", "", false, errHTTPBadRequestPhoneCallsDisabled
print("call: %s", call)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. Forgot to take this out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants