Skip to content

Commit afc3d1e

Browse files
authored
Add Logs for Opentelemetry (#951)
1 parent df1fa07 commit afc3d1e

File tree

3 files changed

+71
-28
lines changed

3 files changed

+71
-28
lines changed

dotnet/src/dotnetcore/GxClasses/Services/LogService/GXLogService.cs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using GeneXus.Configuration;
23
using Microsoft.Extensions.Logging;
34

@@ -7,15 +8,25 @@ public static class GXLogService
78
{
89
private static string AZURE_APPLICATION_INSIGHTS_LOG = "AZUREAPPLICATIONINSIGHTS";
910
const string OTEL_AZUREMONITOR_EXPORTER = "OTEL_AZUREMONITOR_EXPORTER";
11+
const string OPENTELEMETRY = "OPENTELEMETRY";
12+
internal static string OTEL_LOGS_EXPORTER = "OTEL_LOGS_EXPORTER";
1013
const string LOG_OUTPUT = "LOG_OUTPUT";
14+
1115
public static ILoggerFactory GetLogFactory()
1216
{
13-
if (Config.GetValueOf(LOG_OUTPUT, out string logProvider))
14-
{
15-
if (logProvider == OTEL_AZUREMONITOR_EXPORTER)
16-
return AzureAppInsightsLogProvider.GetAzureMonitorLoggerFactory();
17-
else if (logProvider == AZURE_APPLICATION_INSIGHTS_LOG)
18-
return AzureAppInsightsLogProvider.GetLoggerFactory();
17+
string otelLogEnvVar = Environment.GetEnvironmentVariable(OTEL_LOGS_EXPORTER);
18+
if (string.IsNullOrEmpty(otelLogEnvVar) || !otelLogEnvVar.ToLower().Equals("none"))
19+
{
20+
if (Config.GetValueOf(LOG_OUTPUT, out string logProvider))
21+
{
22+
if (logProvider == OTEL_AZUREMONITOR_EXPORTER)
23+
return OpentelemetryLogProvider.GetAzureMonitorLoggerFactory();
24+
else if (logProvider == AZURE_APPLICATION_INSIGHTS_LOG)
25+
return OpentelemetryLogProvider.GetAzureAppInsightsLoggerFactory();
26+
else
27+
if (logProvider == OPENTELEMETRY)
28+
return OpentelemetryLogProvider.GetOpentelemetryLoggerFactory();
29+
}
1930
}
2031
return null;
2132
}
Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.InteropServices;
24
using Azure.Monitor.OpenTelemetry.Exporter;
35
using Microsoft.Extensions.Logging;
46
using OpenTelemetry.Logs;
7+
using OpenTelemetry.Resources;
58

69
namespace GeneXus.Services.Log
710
{
8-
public class AzureAppInsightsLogProvider : ILoggerFactory
11+
public class OpentelemetryLogProvider : ILoggerFactory
912
{
1013
private static string APPLICATIONINSIGHTS_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING";
1114
private const string LOG_LEVEL_ENVVAR = "GX_LOG_LEVEL";
@@ -25,7 +28,8 @@ public static ILoggerFactory GetAzureMonitorLoggerFactory()
2528
builder.AddOpenTelemetry(options =>
2629
{
2730
options.AddAzureMonitorLogExporter(o => o.ConnectionString = appInsightsConnection);
28-
options.AddConsoleExporter();
31+
if (GenerateOtelLogsToConsole())
32+
options.AddConsoleExporter();
2933
}).SetMinimumLevel(loglevel);
3034
});
3135
}
@@ -42,7 +46,7 @@ public static ILoggerFactory GetAzureMonitorLoggerFactory()
4246
return loggerFactory;
4347
}
4448

45-
public static ILoggerFactory GetLoggerFactory()
49+
public static ILoggerFactory GetAzureAppInsightsLoggerFactory()
4650
{
4751
string appInsightsConnection = Environment.GetEnvironmentVariable(APPLICATIONINSIGHTS_CONNECTION_STRING);
4852
try
@@ -71,6 +75,23 @@ public static ILoggerFactory GetLoggerFactory()
7175

7276
return loggerFactory;
7377
}
78+
79+
public static ILoggerFactory GetOpentelemetryLoggerFactory()
80+
{
81+
LogLevel loglevel = GetLogLevel();
82+
loggerFactory = LoggerFactory.Create(builder => builder.AddOpenTelemetry(logging =>
83+
{
84+
var resourceBuilder = ResourceBuilder.CreateDefault()
85+
.AddTelemetrySdk();
86+
87+
logging.SetResourceBuilder(resourceBuilder);
88+
if (GenerateOtelLogsToConsole())
89+
logging.AddConsoleExporter();
90+
91+
})
92+
.SetMinimumLevel(loglevel));
93+
return loggerFactory;
94+
}
7495
private static LogLevel GetLogLevel()
7596
{
7697
string loglevelvalue = Environment.GetEnvironmentVariable(LOG_LEVEL_ENVVAR);
@@ -79,7 +100,7 @@ private static LogLevel GetLogLevel()
79100
{
80101
if (!Enum.TryParse<LogLevel>(loglevelvalue, out loglevel))
81102
{
82-
CustomLogLevel customLogLevel = CustomLogLevel.Info;
103+
CustomLogLevel customLogLevel = CustomLogLevel.info;
83104
if (Enum.TryParse<CustomLogLevel>(loglevelvalue, out customLogLevel))
84105
{
85106
loglevel = toLogLevel(customLogLevel);
@@ -91,6 +112,13 @@ private static LogLevel GetLogLevel()
91112
return loglevel;
92113
}
93114

115+
private static bool GenerateOtelLogsToConsole()
116+
{
117+
string otelLogsEnvVar = Environment.GetEnvironmentVariable(GXLogService.OTEL_LOGS_EXPORTER);
118+
if (string.IsNullOrEmpty(otelLogsEnvVar)) { return false; }
119+
return otelLogsEnvVar.ToLower().Contains("console") || otelLogsEnvVar.ToLower().Contains("logging");
120+
}
121+
94122
public void AddProvider(ILoggerProvider provider)
95123
{
96124
loggerFactory.AddProvider(provider);
@@ -105,25 +133,25 @@ public ILogger CreateLogger(string name)
105133
}
106134
private enum CustomLogLevel
107135
{
108-
None,
109-
All,
110-
Debug,
111-
Info,
112-
Warn,
113-
Error,
114-
Fatal
136+
none,
137+
all,
138+
debug,
139+
info,
140+
warn,
141+
error,
142+
fatal
115143
}
116144
private static LogLevel toLogLevel(CustomLogLevel customLogLevel)
117145
{
118146
switch (customLogLevel)
119147
{
120-
case CustomLogLevel.None: return LogLevel.None;
121-
case CustomLogLevel.All: return LogLevel.Trace;
122-
case CustomLogLevel.Debug: return LogLevel.Debug;
123-
case CustomLogLevel.Info: return LogLevel.Information;
124-
case CustomLogLevel.Warn: return LogLevel.Warning;
125-
case CustomLogLevel.Error: return LogLevel.Error;
126-
case CustomLogLevel.Fatal: return LogLevel.Critical;
148+
case CustomLogLevel.none: return LogLevel.None;
149+
case CustomLogLevel.all: return LogLevel.Trace;
150+
case CustomLogLevel.debug: return LogLevel.Debug;
151+
case CustomLogLevel.info: return LogLevel.Information;
152+
case CustomLogLevel.warn: return LogLevel.Warning;
153+
case CustomLogLevel.error: return LogLevel.Error;
154+
case CustomLogLevel.fatal: return LogLevel.Critical;
127155
default: return LogLevel.Information;
128156
}
129157
}

dotnet/src/dotnetframework/GxClasses/Diagnostics/Log.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using log4net;
44
using System.Collections.Concurrent;
55

6+
67
#if NETCORE
78
using GeneXus.Services.Log;
89
using Microsoft.Extensions.Logging;
@@ -25,10 +26,8 @@ private enum LogLevel
2526
}
2627

2728
private const string LoggerPrefix = "$";
28-
private static readonly string DefaultRepository = LogManager.GetRepository().Name;
2929
private static readonly string DefaultUserLogNamespace = Config.GetValueOf("USER_LOG_NAMESPACE", LogConfiguration.USER_LOG_TOPIC);
30-
private static readonly IGXLogger GlobalLog = new GXLoggerLog4Net(LogManager.GetLogger(DefaultRepository, DefaultUserLogNamespace));
31-
private static ConcurrentDictionary<string, IGXLogger> LoggerDictionary = new ConcurrentDictionary<string, IGXLogger>() { [string.Empty] = GlobalLog };
30+
private static ConcurrentDictionary<string, IGXLogger> LoggerDictionary = new ConcurrentDictionary<string, IGXLogger>() {};
3231
internal static IGXLogger GetLogger(string topic)
3332
{
3433
if (LoggerDictionary.TryGetValue(topic, out IGXLogger logger))
@@ -37,7 +36,12 @@ internal static IGXLogger GetLogger(string topic)
3736
}
3837
else
3938
{
40-
string loggerName = topic.StartsWith(LoggerPrefix) ? topic.Substring(1) : $"{DefaultUserLogNamespace}.{topic.Trim()}";
39+
string loggerName;
40+
if (!string.IsNullOrEmpty(topic))
41+
loggerName = topic.StartsWith(LoggerPrefix) ? topic.Substring(1) : $"{DefaultUserLogNamespace}.{topic.Trim()}";
42+
else
43+
loggerName = DefaultUserLogNamespace;
44+
4145
logger = GXLoggerFactory.GetLogger(loggerName);
4246
LoggerDictionary.TryAdd(topic, logger);
4347
return logger;

0 commit comments

Comments
 (0)