Send an event to log, pub/sub, user notification script. * * 'level' is the log level for logging. Only LL_WARNING events will trigger * the execution of the user notification script. * * 'type' is the message type, also used as a pub/sub channel name. * * 'ri', is the redis instance target of this event if applicable, and is * used to obtain the path of the notification script to execute.
| 694 | * Any other specifier after "%@" is processed by printf itself. |
| 695 | */ |
| 696 | void sentinelEvent(int level, const char *type, sentinelRedisInstance *ri, |
| 697 | const char *fmt, ...) { |
| 698 | va_list ap; |
| 699 | char msg[LOG_MAX_LEN]; |
| 700 | robj *channel, *payload; |
| 701 | |
| 702 | /* Handle %@ */ |
| 703 | if (fmt[0] == '%' && fmt[1] == '@') { |
| 704 | sentinelRedisInstance *master = (ri->flags & SRI_MASTER) ? |
| 705 | NULL : ri->master; |
| 706 | |
| 707 | if (master) { |
| 708 | snprintf(msg, sizeof(msg), "%s %s %s %d @ %s %s %d", |
| 709 | sentinelRedisInstanceTypeStr(ri), |
| 710 | ri->name, announceSentinelAddr(ri->addr), ri->addr->port, |
| 711 | master->name, announceSentinelAddr(master->addr), master->addr->port); |
| 712 | } else { |
| 713 | snprintf(msg, sizeof(msg), "%s %s %s %d", |
| 714 | sentinelRedisInstanceTypeStr(ri), |
| 715 | ri->name, announceSentinelAddr(ri->addr), ri->addr->port); |
| 716 | } |
| 717 | fmt += 2; |
| 718 | } else { |
| 719 | msg[0] = '\0'; |
| 720 | } |
| 721 | |
| 722 | /* Use vsprintf for the rest of the formatting if any. */ |
| 723 | if (fmt[0] != '\0') { |
| 724 | va_start(ap, fmt); |
| 725 | vsnprintf(msg+strlen(msg), sizeof(msg)-strlen(msg), fmt, ap); |
| 726 | va_end(ap); |
| 727 | } |
| 728 | |
| 729 | /* Log the message if the log level allows it to be logged. */ |
| 730 | if (level >= cserver.verbosity) |
| 731 | serverLog(level,"%s %s",type,msg); |
| 732 | |
| 733 | /* Publish the message via Pub/Sub if it's not a debugging one. */ |
| 734 | if (level != LL_DEBUG) { |
| 735 | channel = createStringObject(type,strlen(type)); |
| 736 | payload = createStringObject(msg,strlen(msg)); |
| 737 | pubsubPublishMessage(channel,payload); |
| 738 | decrRefCount(channel); |
| 739 | decrRefCount(payload); |
| 740 | } |
| 741 | |
| 742 | /* Call the notification script if applicable. */ |
| 743 | if (level == LL_WARNING && ri != NULL) { |
| 744 | sentinelRedisInstance *master = (ri->flags & SRI_MASTER) ? |
| 745 | ri : ri->master; |
| 746 | if (master && master->notification_script) { |
| 747 | sentinelScheduleScriptExecution(master->notification_script, |
| 748 | type,msg,NULL); |
| 749 | } |
| 750 | } |
| 751 | } |
| 752 | |
| 753 | /* This function is called only at startup and is used to generate a |
no test coverage detected