Skip to content

Conversation

yhabteab
Copy link
Member

@yhabteab yhabteab commented Aug 6, 2025

This PR introduces a new notifications package to our Icinga Go library. The package is designed to handle common
Icinga Notifications related tasks, that can be used by any Icinga Notifications source. It provides a set of functions and types that simplify and centralize the interaction with Icinga Notifications API. Within the root of this package, you will find the following files:

  • client.go: This file contains the actual client implementation with a custom HTTP round tripper that handles
    the necessary authentication before sending the final request to the Icinga API.
  • config.go: This file defines the configuration structure that every Icinga Notifications source is required to provide.
  • xhttp_headers.go: This file contains our custom HTTP header constants only that should be used by the Icinga
    Notifications sources to ensure consistency and compatibility with the Icinga API. Currently, it includes only
    X-Icinga-Rules-Version header, which is used to specify the version of the rules that are being used by the source and
    X-Icinga-Rules-Id header, which is used to specify the unique identifier of the rules that are being used by the source.
    Of course, in order to be consistent with the HTTP header naming conventions in Icinga Web 2, both custom headers
    are prefixed with X-Icinga-.

The event package within the notifications package contains common event related types and utilities that should
be used by any Icinga Notifications source as well as by the Icinga Notifications daemon itself.

The change list appears to be quite big, but don't be fooled by it :). Most of them are just unit tests and autogenerated
code. The actual code changes are quite minimal and focused on the new functionality described above.

Oops, did I say autogenerated code? Yes, I did ;)! The notifications package makes use of the Go stringer tool to implement the String() method for the event.Type and event.Severity types in an efficient manner. So, don't be surprised to see the autogenerated files in the event package.

Oh, and one more thing: most of the work was done by Alvar in the Icinga DB repository, so I just had to outsource it to the Icinga Go library with some minor adjustments. So, credit goes to him for the majority of the work.


This PR is required by

@cla-bot cla-bot bot added the cla/signed CLA is signed by all contributors of a PR label Aug 6, 2025
@yhabteab yhabteab force-pushed the notifications branch 2 times, most recently from 609ec3f to 82eff34 Compare August 6, 2025 16:06
@julianbrost
Copy link
Contributor

I'm not sure if this is the right place to add this. The reasoning probably is similar to Icinga/icinga-notifications#304. One thing to consider here: do we expect external projects using this eventually? In this case, this would create dependency updates for them even though if nothing relevant to them changed. So I think having a separate repository with independent versioning for this is also worth considering.

@yhabteab yhabteab force-pushed the notifications branch 2 times, most recently from e4215c5 to 55c038b Compare August 7, 2025 15:16
@lippserd
Copy link
Member

I'm not sure if this is the right place to add this. The reasoning probably is similar to Icinga/icinga-notifications#304. One thing to consider here: do we expect external projects using this eventually? In this case, this would create dependency updates for them even though if nothing relevant to them changed. So I think having a separate repository with independent versioning for this is also worth considering.

I like this idea. How about a MIT licensed go-icinga-notifications project with this code, and the channel base?

@oxzi oxzi added this to the 0.8.0 milestone Aug 28, 2025
@oxzi
Copy link
Member

oxzi commented Sep 2, 2025

After today's discussion to keep these changes in the IGL, I have skimmed the PR once again. In general, it looks good to me. However, it should be merged together with its sibling PRs as otherwise fix-up PRs would follow here.

@yhabteab yhabteab force-pushed the notifications branch 2 times, most recently from 64209e7 to f54aa70 Compare September 5, 2025 11:08
@yhabteab
Copy link
Member Author

yhabteab commented Sep 5, 2025

Changed the tabular test cases to use testutils.TestCase instead of a custom one!

oxzi added a commit to Icinga/icingadb that referenced this pull request Sep 5, 2025
- Bump IGL to latest changes in Icinga/icinga-go-library#145.
- Allow specifying which pipeline keys are relevant, ignore others.
- Allow specifying which pipeline key should be parsed in which type.
- Create history.DowntimeHistoryMeta as a chimera combining
  history.DowntimeHistory and history.HistoryDowntime to allow access
  event_type, distinguishing between downtime_start and downtime_end.
- Trace times for submission steps in the worker. Turns out, the single
  threaded worker blocks roughly two seconds for each
  Client.ProcessEvent method call. This might sum up to minutes if lots
  of events are processed at once. My current theory is that the delay
  results in the expensive bcrypt hash comparison on Notifications.
oxzi added a commit to Icinga/icingadb that referenced this pull request Sep 5, 2025
- Bump IGL to latest changes in Icinga/icinga-go-library#145.
- Allow specifying which pipeline keys are relevant, ignore others.
- Allow specifying which pipeline key should be parsed in which type.
- Create history.DowntimeHistoryMeta as a chimera combining
  history.DowntimeHistory and history.HistoryDowntime to allow access
  event_type, distinguishing between downtime_start and downtime_end.
- Trace times for submission steps in the worker. Turns out, the single
  threaded worker blocks roughly two seconds for each
  Client.ProcessEvent method call. This might sum up to minutes if lots
  of events are processed at once. My current theory is that the delay
  results in the expensive bcrypt hash comparison on Notifications.
oxzi added a commit to Icinga/icinga-notifications that referenced this pull request Sep 5, 2025
Synchronize codebase against latest version of
Icinga/icinga-go-library#145, containing package changes.
oxzi added a commit to Icinga/icingadb that referenced this pull request Sep 5, 2025
- Bump IGL to latest changes in Icinga/icinga-go-library#145.
- Allow specifying which pipeline keys are relevant, ignore others.
- Allow specifying which pipeline key should be parsed in which type.
- Create history.DowntimeHistoryMeta as a chimera combining
  history.DowntimeHistory and history.HistoryDowntime to allow access
  event_type, distinguishing between downtime_start and downtime_end.
- Trace times for submission steps in the worker. Turns out, the single
  threaded worker blocks roughly two seconds for each
  Client.ProcessEvent method call. This might sum up to minutes if lots
  of events are processed at once. My current theory is that the delay
  results in the expensive bcrypt hash comparison on Notifications.
@oxzi oxzi self-assigned this Sep 9, 2025
@oxzi
Copy link
Member

oxzi commented Sep 9, 2025

Removed the custom HTTP headers and moved the rules to the Event struct to address Icinga/icinga-notifications#324 (comment).

oxzi added a commit to Icinga/icingadb that referenced this pull request Sep 9, 2025
- Bump IGL to latest changes in Icinga/icinga-go-library#145.
- Allow specifying which pipeline keys are relevant, ignore others.
- Allow specifying which pipeline key should be parsed in which type.
- Create history.DowntimeHistoryMeta as a chimera combining
  history.DowntimeHistory and history.HistoryDowntime to allow access
  event_type, distinguishing between downtime_start and downtime_end.
- Trace times for submission steps in the worker. Turns out, the single
  threaded worker blocks roughly two seconds for each
  Client.ProcessEvent method call. This might sum up to minutes if lots
  of events are processed at once. My current theory is that the delay
  results in the expensive bcrypt hash comparison on Notifications.
oxzi added a commit to Icinga/icinga-notifications that referenced this pull request Sep 9, 2025
Synchronize codebase against latest version of
Icinga/icinga-go-library#145, containing package changes.
@oxzi oxzi removed their assignment Sep 9, 2025
@yhabteab yhabteab self-assigned this Sep 10, 2025
As this is intended to be an user facing API, the API documentation was
a bit extended. Furthermore, some types were simplified.

For example, RulesResp was replaced by a simple string. For an
implementation, this struct did not hold any further required
information not already being part of the map.
@oxzi oxzi requested a review from julianbrost October 2, 2025 08:04
@oxzi oxzi marked this pull request as draft October 9, 2025 08:09
sukhwinder33445 and others added 26 commits October 9, 2025 11:53
…lues (name, url, etc) are moved into this struct and used accordingly
- Introduce a plugin table to store plugin related info. On daemon start the plugin table is upserted.
- Each plugin defines its own required form elements for config as configOption(s).
- Configured channels start and maintain there plugin.
- The Upsert() func is no longer required because Info{} contains all that properties.
- Fix reciver param name of Info.TableName() method.
- Remove type from GetInfo to make it non-configurable. The file name should always be used as the type.
The "Tags" and "Extra Tags" printed in the plugin.FormatMessage were
directly read from their map, thus having no order. This resulted in the
same NotificationRequest being represented by different messages due to
the unordered map.

This change was the result of investigating Go's new rangefunc
experiment[0]. The utilization of this novel language feature - which can
also be indirectly used in the absence of `GOEXPERIMENT=rangefunc` - ensures
that the map is traversed in key order.

Closes #177.

[0]: https://go.dev/wiki/RangefuncExperiment
In a nutshell, the newly introduced plugin.PopulateDefaults function
populates all fields of a Plugin-implementing struct with those fields
from Info.ConfigAttributes where ConfigOption.Default is set. Thus, a
single function call before parsing the user-submitted configuration
within the Plugin.SetConfig method sets default values.

As a result of the discussion between the Go and the Web team,
summarized in #205, Web does not store key-value pairs to be omitted.

Prior, an already JSON-encoded version of the ConfigOption slice was
present in plugin.Info. Thus, this data wasn't easily available anymore.
As the new code now needs to access this field, it was changed and a
custom sql driver.Valuer was implemented for a slice type.

While working on this, all ConfigOptions were put in the same order as
the struct fields.

Requires <Icinga/icinga-notifications-web#230>.

Closes #205.
With a release approaching, the Channels documentation got more
information about how the Channel system actually work and how to build
your own channels.

The internal/changes/examples JSON files were inlined to ease the
readability and updated, as they contained partially outdated
information.

For the pkg/plugin part, some API documentation was added as this might
get used by external users.
With #64 and
#127 being merged, most
of the internal/utils package is moved to the IGL and can be removed
here. This is another step to unify our Go codebase.
@oxzi oxzi marked this pull request as ready for review October 9, 2025 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla/signed CLA is signed by all contributors of a PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants