Add alarm generation when application is slow
[ric-plt/lib/rmr.git] / src / rmr / common / src / alarm.c
1 // : vi ts=4 sw=4 noet :
2 /*
3 ==================================================================================
4         Copyright (c) 2021 Nokia
5         Copyright (c) 2021      AT&T Intellectual Property.
6
7    Licensed under the Apache License, Version 2.0 (the "License");
8    you may not use this file except in compliance with the License.
9    You may obtain a copy of the License at
10
11            http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18 ==================================================================================
19 */
20
21 /*
22 ------------------------------------------------------------------------------
23 Mnemonic:       alarm.c
24 Abstract:       The RMR housekeeping thread (route table collection) is also responsible
25                         for sending a small number of alarm messages to the alarm system.
26                         To avoid extra overhead, the alarm library is NOT included; this
27                         module provides the alarm generation support for the housekeeping
28                         thread.
29
30 Date:           19 February 2021
31                         HBD-EKD
32 Author:         E. Scott Daniels
33
34 ------------------------------------------------------------------------------
35 */
36
37 #ifndef alarm_static_c
38 #define alarm_static_c
39
40 #include <errno.h>
41 #include <stdio.h>
42 #include <unistd.h>
43 #include <string.h>
44 #include <stdlib.h>
45 #include <memory.h>
46 #include <netdb.h>
47 #include <pthread.h>
48
49 #include <rmr.h>
50 #include <RIC_message_types.h>
51 #include <rmr_logging.h>
52
53
54 extern const char* __progname;                  // runtime supplies (we have no acccess to argv[0]
55
56 /*
57         Generate the endpoint for the arlarm system. We assume that it is defined
58         by two environment variables: ALARM_MGR_SERVICE_NAME and ALARM_MGR_SERVICE_PORT.
59         If the name is not given, we assume 127.0.0.1 (we don't use localhost for
60         to avoid the double meaning within some flavours' hosts files). If the port
61         is not given, we assume the default RMR port of 4560.
62
63         The string returned must be freed by the caller.
64 */
65 static char* uta_alarm_endpt( ) {
66         char    wbuf[300];                                                                                      // enough room for max name of 256 + :port
67         const char* et;                                                                                         // environment token
68         const char* addr = "service-ricplt-alarmmanager-rmr";           // defaults
69         const char* port = "4560";
70
71     if( (et = getenv( ENV_AM_NAME )) != NULL ) {
72         addr = et;
73     }
74
75     if( (et = getenv( ENV_AM_PORT )) != NULL ) {
76         port = et;
77     }
78
79         wbuf[sizeof(wbuf)-1] = 0;                               // guarentee it is nil terminated if too long
80         snprintf( wbuf, sizeof( wbuf ) -1, "%s:%s", addr, port );
81     return strdup( wbuf );
82 }
83
84 /*
85         Send the message as an alarm. We will create a wormhole as we cannot depend
86         on having a routing table that is valid. This send does NOT allocate a new
87         message to return to the caller.
88 */
89 static void uta_alarm_send( void* vctx, rmr_mbuf_t* msg ) {
90         static int      whid = -1;
91         static int      ok2log = 0;             // if we must log to stderr, do it seldomly; this is the next spot in time where logging is ok
92         char*   ept;
93         int             now;
94
95         if( whid < 0 ) {
96                 ept = uta_alarm_endpt();
97                 if( (whid = rmr_wh_open( vctx, ept )) < 0 ) {
98                         if( (now = time( NULL )) >      ok2log ) {
99                                 ok2log = now + 60;
100                         }
101                         rmr_vlog( RMR_VL_WARN, "unable to open wormhole for alarms: %s\n", ept );
102                         free( ept );
103                         return;
104                 }
105                 rmr_vlog( RMR_VL_INFO, "alarm wormhole opened to: %s\n", ept );
106                 free( ept );
107         }
108
109         if( msg != NULL ) {
110                 msg = rmr_wh_send_msg( vctx, whid, msg );
111                 rmr_free_msg( msg );
112         }
113 }
114
115
116 /*
117         Builds an alarm message for the kind of action. Alarm message is palced in
118         the given buffer using the buffer length (blen) to truncate. A convenience
119         pointer to the buffer is returned and will be nil on error.
120
121         Kind is an ALARM_* constant ANDed with ALARM_RAISE or ALARM_CLEAR.
122         Problem ID (prob_id) is an integer assigned by the caller and should
123         match when calling to clear the alarm.
124
125         Info is the message text that is added to the alarm; nil terminated string.
126 */
127 static void uta_alarm( void* vctx, int kind, int prob_id, char* info ) {
128         rmr_mbuf_t*     msg;
129         int used;
130         char*   maction = "CLEAR";
131
132         if( (msg = rmr_alloc_msg( vctx, 2048 )) == NULL ) {
133                 return;
134         }
135
136         if( kind & ALARM_RAISE ) {
137                 maction = "RAISE";
138         }
139
140         if( info == NULL ) {
141                 info = "unspecific RMR issue";
142         }
143
144         used = snprintf( msg->payload, 2047,
145                 "{  "
146                 "\"managedObjectId\": null, "                                   // there is no object for rmr alarms
147                 "\"applicationId\": \"%s\", "
148                 "\"specificProblem\": %d, "                                             // problem id
149                 "\"perceivedSeverity\": \"WARNING\", "                  // all RMR messages are warnings
150                 "\"identifyingInfo\": \"%s\", "
151                 "\"additionalInfo\": null, "
152                 "\"AlarmAction\": \"%s\", "
153                 "\"AlarmTime\": %lld"
154                 " }",
155
156                 __progname,                                                                             // see comment above
157                 prob_id,
158                 info,
159                 maction,                                                                                // raise/clear
160                 mstime()                                                                                // use logging module's timestamp generator
161         );
162
163         msg->len = strlen( msg->payload );
164         msg->state = RMR_OK;
165         msg->sub_id = -1;
166         msg->mtype = RIC_ALARM;
167         uta_alarm_send( vctx, msg );
168 }
169
170
171
172 #endif