提交 2d29a8f2 编写于 作者: J jonathan pickett

Added support for redirecting Redis logging to the Windows Application log....

Added support for redirecting Redis logging to the Windows Application log. Repurposed --syslog flags for this. See redis.windows.conf for information about the repurposed flags. When redis is running as a service it will use the Windows EventLog by default.
上级 34250336
......@@ -19,6 +19,7 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CLRSupport>false</CLRSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
......@@ -177,6 +178,9 @@
<Project>{170b0909-5f75-467f-9501-c99dec16c6dc}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="..\src\Win32_Interop\resources\EventLog.res" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
......
......@@ -68,16 +68,15 @@ loglevel notice
# output for logging but daemonize, logs will be sent to /dev/null
logfile stdout
# To enable logging to the system logger, just set 'syslog-enabled' to yes,
# and optionally update the other syslog parameters to suit your needs.
# To enable logging to the Windows EventLog, just set 'syslog-enabled' to
# yes, and optionally update the other syslog parameters to suit your needs.
# If Redis is installed and launched as a Windows Service, this will
# automatically be enabled.
# syslog-enabled no
# Specify the syslog identity.
# Specify the source name of the events in the Windows Application log.
# syslog-ident redis
# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
# syslog-facility local0
# Set the number of databases. The default database is DB 0, you can select
# a different one on a per-connection basis using SELECT <dbid> where
# dbid is a number between 0 and 'databases'-1
......
......@@ -27,10 +27,13 @@
#include <malloc.h>
#include <string.h>
#include <process.h>
#include "redis.h"
#ifdef _WIN32
#include "win32_Interop/win32Fixes.h"
#include "win32_Interop/Win32_EventLog.h"
#endif
#include <time.h>
static int verbosity = REDIS_WARNING;
static char* logFile = NULL;
......@@ -89,13 +92,14 @@ void redisLogRaw(int level, const char *msg) {
off = strftime(buf,sizeof(buf),"%d %b %H:%M:%S.",localtime(&tv.tv_sec));
snprintf(buf+off,sizeof(buf)-off,"%03d",(int)tv.tv_usec/1000);
#endif
fprintf(fp,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg);
fprintf(fp,"[%d] %s %c %s\n",(int)_getpid(),buf,c[level],msg);
}
fflush(fp);
if (logFile) fclose(fp);
if (logFile) fclose(fp);
#ifdef _WIN32
// replace with event log or ETW?
LogToEventLog(server.syslog_ident, msg);
#else
if (server.syslog_enabled) syslog(syslogLevelMap[level], "%s", msg);
#endif
......@@ -152,6 +156,3 @@ err:
;#pragma once
LanguageNames=(EnglishUS=0x409:MSG00409)
MessageId=0x0
SymbolicName=MSG_INFO_1
Severity=Informational
Facility=Application
Language=EnglishUS
%1
.
MessageId=0x1
SymbolicName=MSG_WARNING_1
Severity=Warning
Facility=Application
Language=EnglishUS
%1
.
MessageId=0x2
SymbolicName=MSG_ERROR_1
Severity=Error
Facility=Application
Language=EnglishUS
%1
.
MessageId=0x3
SymbolicName=MSG_SUCCESS_1
Severity=Success
Facility=Application
Language=EnglishUS
%1
.
#include <Windows.h>
#include <string>
#include <iostream>
using namespace std;
#include "Win32_EventLog.h"
#include "EventLog.h"
class RedisEventLog {
public:
static RedisEventLog& getInstance() {
static RedisEventLog instance; // Instantiated on first use. Guaranteed to be destroyed.
return instance;
}
private:
std::string eventLogName;
RedisEventLog() {
}
~RedisEventLog() {
UninstallEventLogSource();
}
RedisEventLog(RedisEventLog const&); // Don't implement to guarantee singleton semantics
void operator=(RedisEventLog const&); // Don't implement to guarantee singleton semantics
void UninstallEventLogSource() {
const std::string keyPath(
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" + this->eventLogName);
DWORD last_error = RegDeleteKeyA(HKEY_LOCAL_MACHINE, keyPath.c_str());
if (ERROR_SUCCESS != last_error) {
std::cerr << "Failed to uninstall source: " << last_error << endl;
}
}
void InstallEventLogSource() {
const std::string keyPath(
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" + this->eventLogName);
HKEY key;
DWORD last_error = RegCreateKeyExA(
HKEY_LOCAL_MACHINE,
keyPath.c_str(),
0,
0,
REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE,
0,
&key,
0);
char result[MAX_PATH];
GetModuleFileNameA(NULL, result, MAX_PATH);
std::string appPath = result;
if (ERROR_SUCCESS == last_error) {
DWORD last_error;
const DWORD types_supported = EVENTLOG_ERROR_TYPE |
EVENTLOG_WARNING_TYPE |
EVENTLOG_INFORMATION_TYPE;
last_error = RegSetValueExA(
key,
"EventMessageFile",
0,
REG_SZ,
(const BYTE *)appPath.c_str(),
(DWORD)(appPath.length()));
if (ERROR_SUCCESS == last_error) {
last_error = RegSetValueExA(key,
"TypesSupported",
0,
REG_DWORD,
(const BYTE*)&types_supported,
sizeof(types_supported));
}
if (ERROR_SUCCESS != last_error) {
std::cerr << "Failed to install source values: "
<< last_error << "\n";
}
RegCloseKey(key);
} else {
std::cerr << "Failed to install source: " << last_error << "\n";
}
}
public:
void EnsureInitialization(LPCSTR eventLogName) {
if (this->eventLogName.length() == 0) {
this->eventLogName = eventLogName;
InstallEventLogSource();
}
}
void LogMessageToEventLog(LPCSTR msg, const WORD type) {
DWORD eventID;
switch (type) {
case EVENTLOG_ERROR_TYPE:
eventID = MSG_ERROR_1;
break;
case EVENTLOG_WARNING_TYPE:
eventID = MSG_WARNING_1;
break;
case EVENTLOG_INFORMATION_TYPE:
eventID = MSG_INFO_1;
break;
default:
std::cerr << "Unrecognized type: " << type << "\n";
eventID = MSG_INFO_1;
break;
}
HANDLE hEventLog = RegisterEventSourceA(0, this->eventLogName.c_str());
if (0 == hEventLog) {
std::cerr << "Failed open source '" << this->eventLogName << "': " << GetLastError() << endl;
} else {
if (FALSE == ReportEventA(
hEventLog,
type,
0,
eventID,
0,
1,
0,
&msg,
0)) {
std::cerr << "Failed to write message: " << GetLastError() << endl;
}
DeregisterEventSource(hEventLog);
}
}
};
extern "C" void LogToEventLog(const char* eventLogName, const char* msg) {
try {
RedisEventLog::getInstance().EnsureInitialization(eventLogName);
RedisEventLog::getInstance().LogMessageToEventLog(msg, EVENTLOG_INFORMATION_TYPE);
} catch (...) {
}
}
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void LogToEventLog(const char* logName, const char* msg);
#ifdef __cplusplus
}
#endif
......@@ -14,6 +14,7 @@
<ClCompile Include="..\RedisLog.c" />
<ClCompile Include="win32fixes.c" />
<ClCompile Include="Win32_dlmalloc.c" />
<ClCompile Include="Win32_EventLog.cpp" />
<ClCompile Include="Win32_FDAPI.cpp" />
<ClCompile Include="Win32_fdapi_crt.cpp" />
<ClCompile Include="Win32_QFork.cpp" />
......@@ -27,6 +28,7 @@
<ClInclude Include="..\redisLog.h" />
<ClInclude Include="win32fixes.h" />
<ClInclude Include="Win32_dlmalloc.h" />
<ClInclude Include="Win32_EventLog.h" />
<ClInclude Include="Win32_FDAPI.h" />
<ClInclude Include="Win32_fdapi_crt.h" />
<ClInclude Include="Win32_QFork.h" />
......@@ -38,6 +40,18 @@
<ClInclude Include="win32_wsiocp.h" />
<ClInclude Include="WS2tcpip.h" />
</ItemGroup>
<ItemGroup>
<CustomBuild Include="EventLog.mc">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">md resources
mc.exe -A -b -c -h . -r resources EventLog.mc
rc.exe -foresources/EventLog.res resources/EventLog.rc</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">EventLog.h</Outputs>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<Resource Include="resources\EventLog.res" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{8C07F811-C81C-432C-B334-1AE6FAECF951}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
......
......@@ -27,6 +27,7 @@ extern "C"
{
#endif
BOOL RunningAsService();
BOOL HandleServiceCommands(int argc, char **argv);
BOOL ServiceStopIssued();
......
......@@ -75,6 +75,7 @@ HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE;
vector<string> serviceRunArguments;
SERVICE_STATUS_HANDLE g_StatusHandle;
const ULONGLONG cThirtySeconds = 30 * 1000;
BOOL g_isRunningAsService = FALSE;
extern "C" int main(int argc, char** argv);
......@@ -398,6 +399,7 @@ extern "C" BOOL HandleServiceCommands(int argc, char **argv) {
ServiceUninstall();
return TRUE;
} else if (servicearg == "--service-run") {
g_isRunningAsService = TRUE;
BuildServiceRunArguments(argc, argv);
ServiceRun();
return TRUE;
......@@ -433,3 +435,7 @@ extern "C" BOOL ServiceStopIssued() {
return (WaitForSingleObject(g_ServiceStopEvent, 0) == WAIT_OBJECT_0) ? TRUE : FALSE;
}
extern "C" BOOL RunningAsService() {
return g_isRunningAsService;
}
......@@ -1327,7 +1327,11 @@ void initServerConfig() {
server.saveparams = NULL;
server.loading = 0;
server.logfile = zstrdup(REDIS_DEFAULT_LOGFILE);
server.syslog_enabled = REDIS_DEFAULT_SYSLOG_ENABLED;
#ifdef _WIN32
server.syslog_enabled = RunningAsService() ? 1 : REDIS_DEFAULT_SYSLOG_ENABLED;
#else
server.syslog_enabled = REDIS_DEFAULT_SYSLOG_ENABLED;
#endif
server.syslog_ident = zstrdup(REDIS_DEFAULT_SYSLOG_IDENT);
server.syslog_facility = LOG_LOCAL0;
server.daemonize = REDIS_DEFAULT_DAEMONIZE;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册