Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

** DO NOT MERGE ** Test build #2056

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/Agent/NewRelic/Agent/Core/AgentManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ public static IAgentManager Instance
/// </remarks>
private AgentManager()
{
Log.Initialize(new NewRelic.Core.Logging.FileLogger(new configurationLog().GetFullLogFileName()));

Log.Info("AgentManager() constructor");

_container = AgentServices.GetContainer();
AgentServices.RegisterServices(_container);

Expand All @@ -99,6 +103,7 @@ private AgentManager()

configuration config = null;

Log.Info("Initializing ConfigurationLoader");
try
{
config = ConfigurationLoader.Initialize();
Expand All @@ -118,13 +123,17 @@ private AgentManager()

LoggerBootstrapper.ConfigureLogger(config.LogConfig);

Log.Info("Checking AgentEnabled...");
AssertAgentEnabled(config);

Log.Info("Subscribing to Shutdown signal");
EventBus<KillAgentEvent>.Subscribe(OnShutdownAgent);

Log.Info("Initializing extensions");
//Initialize the extensions loader with extensions folder based on the the install path
ExtensionsLoader.Initialize(AgentInstallConfiguration.InstallPathExtensionsDirectory);

Log.Info("Resolving API and wrapper services");
// Resolve all services once we've ensured that the agent is enabled
// The AgentApiImplementation needs to be resolved before the WrapperService, because
// resolving the WrapperService triggers an agent connect but it doesn't instantiate
Expand All @@ -136,15 +145,19 @@ private AgentManager()
var agentApi = _container.Resolve<IAgentApi>();
_wrapperService = _container.Resolve<IWrapperService>();

Log.Info("Resolving AutoStart");
//We need to attempt to auto start the agent once all services have resolved
_container.Resolve<IConnectionManager>().AttemptAutoStart();

Log.Info("Starting services");
AgentServices.StartServices(_container);

Log.Info("API setup");
// Setup the internal API first so that AgentApi can use it.
InternalApi.SetAgentApiImplementation(agentApi);
AgentApi.SetSupportabilityMetricCounters(_container.Resolve<IApiSupportabilityMetricCounters>());

Log.Info("Initialize()");
Initialize();
_isInitialized = true;
}
Expand All @@ -165,6 +178,7 @@ private void Initialize()
var nativeMethods = _container.Resolve<INativeMethods>();
var instrumentationService = _container.Resolve<IInstrumentationService>();

Log.Info("Staring thread profiler");
_threadProfilingService = new ThreadProfilingService(_container.Resolve<IDataTransportService>(), nativeMethods);

var commandService = _container.Resolve<CommandService>();
Expand All @@ -176,6 +190,7 @@ private void Initialize()
new InstrumentationUpdateCommand(instrumentationService)
);

Log.Info("Starting services");
StartServices();
LogInitialized();
}
Expand Down
11 changes: 6 additions & 5 deletions src/Agent/NewRelic/Agent/Core/Logging/LoggerBootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public static void ConfigureLogger(ILogConfig config)

Log.Logger = configuredLogger;

NewRelic.Core.Logging.Log.Initialize(new Logger());
//NewRelic.Core.Logging.Log.Initialize(new NewRelic.Core.Logging.FileLogger(config.GetFullLogFileName()));
}

private static void EchoInMemoryLogsToConfiguredLogger(ILogger configuredLogger)
Expand Down Expand Up @@ -148,8 +148,9 @@ private static LoggerConfiguration ConfigureEventLogSink(this LoggerConfiguratio
);
});
}
catch
catch (Exception ex )
{
NewRelic.Core.Logging.Log.Warn(ex, "Failed to initialize event log");
// ignored -- there's nothing we can do at this point, as EventLog is our "fallback" logger and if it fails, we're out of luck
}
}
Expand Down Expand Up @@ -213,7 +214,7 @@ private static LoggerConfiguration ConfigureFileSink(this LoggerConfiguration lo
}
catch (Exception ex)
{
Log.Logger.Warning(ex, "Unexpected exception when configuring file sink.");
NewRelic.Core.Logging.Log.Warn(ex, "Unexpected exception when configuring file sink.");

// Fallback to the event log sink if we cannot setup a file logger.
Log.Logger.Warning("Falling back to EventLog sink.");
Expand Down Expand Up @@ -263,7 +264,7 @@ private static LoggerConfiguration ConfigureRollingLogSink(this LoggerConfigurat
}
catch (Exception exception)
{
Log.Logger.Warning(exception, $"Unable to write logfile at \"{fileName}\"");
NewRelic.Core.Logging.Log.Warn(exception, $"Unable to write logfile at \"{fileName}\"");
throw;
}

Expand All @@ -283,7 +284,7 @@ private static LoggerConfiguration ConfigureRollingLogSink(this LoggerConfigurat
}
catch (Exception exception)
{
Log.Logger.Warning(exception, $"Unexpected exception while configuring file logging for \"{fileName}\"");
NewRelic.Core.Logging.Log.Warn(exception, $"Unexpected exception while configuring file logging for \"{fileName}\"");
throw;
}
}
Expand Down
121 changes: 121 additions & 0 deletions src/NewRelic.Core/Logging/FileLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Copyright 2020 New Relic, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

using System;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace NewRelic.Core.Logging
{
public class FileLogger : ILogger
{
private static ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private static string _path;

public FileLogger(string path)
{
_path = path.Replace(".log", $".{Process.GetCurrentProcess().Id}.log");
}

public bool IsDebugEnabled => true;

public bool IsErrorEnabled => true;

public bool IsFinestEnabled => true;

public bool IsInfoEnabled => true;

public bool IsWarnEnabled => true;

private static void LogWrite(string message)
{
_lock.EnterWriteLock();
File.AppendAllText(_path, message);
_lock.ExitWriteLock();
}

private static void FormatLog(string level, string template, params object[] args)
{
if (string.IsNullOrEmpty(template))
return;
string message;
try
{
message = (args == null) || (args.Length == 0) ? template : string.Format(template, args);
}
catch // oops, we must be using Serilog-style logging. just dump the args
{
message = $"{template} /// {string.Join(",", args)}";
}
var pid = Process.GetCurrentProcess().Id;
var tid = Thread.CurrentThread.ManagedThreadId;
// 2023-11-09 20:04:50,248 NewRelic INFO: [pid: 1, tid: 1] Application name from NEW_RELIC_APP_NAME Environment Variable.
string full = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} NewRelic {level.PadLeft(5)}: [pid: {pid} tid: {tid}] {message}\r\n";
LogWrite(full);
}

private static void LogException(Exception e)
{
if (e == null) return;
LogWrite(e?.Message);
LogWrite(e?.StackTrace);
LogWrite("\r\n");
}

public void Debug(Exception exception, string message, params object[] args)
{
Debug(message, args);
LogException(exception);
}

public void Debug(string message, params object[] args)
{
FormatLog("DEBUG", message, args);
}

public void Error(Exception exception, string message, params object[] args)
{
Error(message, args);
LogException(exception);
}

public void Error(string message, params object[] args)
{
FormatLog("ERROR", message, args, args);
}

public void Finest(Exception exception, string message, params object[] args)
{
Finest(message, args);
LogException(exception);
}

public void Finest(string message, params object[] args)
{
FormatLog("FINEST", message, args);
}

public void Info(Exception exception, string message, params object[] args)
{
Info(message, args);
LogException(exception);
}

public void Info(string message, params object[] args)
{
FormatLog("INFO", message, args);
}

public void Warn(Exception exception, string message, params object[] args)
{
Warn(message, args);
LogException(exception);
}

public void Warn(string message, params object[] args)
{
FormatLog("WARN", message, args);
}
}
}