You can build simple Icinga 2 setups where everything is checked and notified 24×7. If you are planning with bigger setups and multiple user groups being notified on problems, you’ll certainly get the task to filter specific time ranges or notification types. Or you’ll consider partial check times e.g. when a service is definitely not available and you don’t want your SLA reporting faked with downtimes.
One common thing is to limit the notifications sent to users to “9 to 5”. The configuration requires the following addition:

  • TimePeriod object named “9to5” (available in the example configuration in timeperiods.conf)
  • Referenced as “period” attribute in your Notification object or apply rule

Human beings don’t work 5 days a week and 52 weeks over the whole year. Vacation is needed, finding some rest without any work. And you obviously don’t want to get notified about Icinga problems during that period of time. In addition to that there are several days or hours where no-one wants to get notified except for the 24×7 support (new year’s eve, christmas, etc.).

In Icinga 1 we had so-called Timeperiod excludes for that. The calculation (current time inside the time period?) and checks were considerably buggy. Icinga 2 pre-calculates the available time segments for the current day beforehand. Once there are additional includes and excludes defined, Icinga 2 needs to ensure to properly merge those segments.
Imagine that you want to exclude the generic “holidays” time period from your default notifications. Define a new TimePeriod object and add the time range definitions. We’ve updated the documentation to add more details on the specific syntax as well.

object TimePeriod "holidays" {
  import "legacy-timeperiod"
  ranges = {
    "january 1" = "00:00-24:00"                 //new year's day
    "july 4" = "00:00-24:00"                    //independence day
    "december 25" = "00:00-24:00"               //christmas
    "december 31" = "18:00-24:00"               //new year's eve (6pm+)
    "2017-04-16" = "00:00-24:00"                //easter 2017
    "monday -1 may" = "00:00-24:00"             //memorial day (last monday in may)
    "monday 1 september" = "00:00-24:00"        //labor day (1st monday in september)
    "thursday 4 november" = "00:00-24:00"       //thanksgiving (4th thursday in november)

Going further, your NOC team should only get notified from 9 to 6 (where their reaction onto ticket costs extra money). Add a secondary TimePeriod object you’ll like to exclude, called “weekends-excluded”.

object TimePeriod "weekends-excluded" {
  import "legacy-timeperiod"
  ranges = {
    "saturday"  = "00:00-09:00,18:00-24:00"
    "sunday"    = "00:00-09:00,18:00-24:00"

Now combine the two exclusions into your generic “prod-notification” TimePeriod object.

object TimePeriod "prod-notification" {
  import "legacy-timeperiod"
  excludes = [ "holidays", "weekends-excluded" ]
  ranges = {
    "monday"    = "00:00-24:00"
    "tuesday"   = "00:00-24:00"
    "wednesday" = "00:00-24:00"
    "thursday"  = "00:00-24:00"
    "friday"    = "00:00-24:00"
    "saturday"  = "00:00-24:00"
    "sunday"    = "00:00-24:00"

The important part here: “excludes” is defined as an array of TimePeriod object names. The order is important for merging the available time range segments. You can of course try to create custom ranges statically inside the “ranges” attribute.
Your notification template hierarchy using the default “mail-service-notification” template could look like this:

template "prod-notification" {
  period = "prod-notification"
apply Notification "mail-service-prod-notification" to Service {
  import "mail-service-notification"
  import "prod-notification"
  users = [ ... ] //user object names as array, or a reference to an exiting host/service array as custom attribute
  assign where ...//define your pattern match

If the time period matches but your co-worker is on holiday, you can filter away the notification at the User object level too.

object TimePeriod "devop-blerim-holidays" {
  import "legacy-timeperiod"
  ranges = {
    "january 10" = "00:00-24:00" //edit this on demand, in advance when co-workers planned their holidays
object TimePeriod "devop-blerim-notification" {
  includes = [ "24x7" ]
  excludes = [ "devop-blerim-holidays" ]
  prefer_includes = false
object User "devop-blerim" {
  period = "devon-blerim-notification"
  //more attributes, state/type filters

Important note: If you are using includes and excludes at the same time, you need to define the default merge strategy with “prefer_includes“. This defaults to true.
In case you want to test whether the current timestamp is inside the defined TimePeriod object time range, Icinga 2 offers the “is_inside” runtime attribute. You can either query that from the REST API endpoint /v1/objects/timeperiods or using object accessor methods to e.g. define dynamic thresholds.
There are presumingly more use cases out there – let us know how you are using the Timeperiod excludes and includes in your setup! Additional details can be found in the documentation.
A huge shoutout to Philipp Dallig for his feature contribution. Grant him a beer or two if you like the new TimePeriod exclude/include possibilities in Icinga 2 v2.5!
If you want to learn more about Icinga 2 and its possibilities, join us at the upcoming Icinga Camps – Belgrade, Stockholm, San Diego and Berlin.