2121package com .microsoft .applicationinsights .agent .bootstrap ;
2222
2323import java .io .File ;
24+ import java .lang .instrument .ClassFileTransformer ;
25+ import java .lang .instrument .IllegalClassFormatException ;
2426import java .lang .instrument .Instrumentation ;
2527import java .net .URL ;
2628import java .nio .file .Path ;
29+ import java .security .ProtectionDomain ;
2730
31+ import ch .qos .logback .classic .Level ;
2832import com .microsoft .applicationinsights .agent .bootstrap .configuration .Configuration ;
29- import com .microsoft .applicationinsights .agent .bootstrap .configuration .ConfigurationBuilder ;
3033import com .microsoft .applicationinsights .agent .bootstrap .configuration .Configuration .SelfDiagnostics ;
34+ import com .microsoft .applicationinsights .agent .bootstrap .configuration .ConfigurationBuilder ;
3135import com .microsoft .applicationinsights .agent .bootstrap .diagnostics .DiagnosticsHelper ;
3236import com .microsoft .applicationinsights .agent .bootstrap .diagnostics .status .StatusFile ;
33- import io .opentelemetry .javaagent .bootstrap .ConfigureLogging ;
3437import io .opentelemetry .javaagent .bootstrap .AgentInitializer ;
38+ import io .opentelemetry .javaagent .bootstrap .ConfigureLogging ;
3539import org .slf4j .Logger ;
3640import org .slf4j .LoggerFactory ;
3741import org .slf4j .MDC ;
@@ -62,41 +66,45 @@ public static void start(Instrumentation instrumentation, URL bootstrapURL) {
6266 boolean success = false ;
6367 Logger startupLogger = null ;
6468 try {
65- File agentJarFile = new File (bootstrapURL .toURI ());
66- DiagnosticsHelper .setAgentJarFile (agentJarFile );
69+ Path agentPath = new File (bootstrapURL .toURI ()). toPath ( );
70+ DiagnosticsHelper .setAgentJarFile (agentPath );
6771 // configuration is only read this early in order to extract logging configuration
68- configuration = ConfigurationBuilder .create (agentJarFile . toPath () );
72+ configuration = ConfigurationBuilder .create (agentPath );
6973 configPath = configuration .configPath ;
7074 lastModifiedTime = configuration .lastModifiedTime ;
71- startupLogger = configureLogging (configuration .preview . selfDiagnostics );
75+ startupLogger = configureLogging (configuration .selfDiagnostics , agentPath );
7276 ConfigurationBuilder .logConfigurationMessages ();
7377 MDC .put (DiagnosticsHelper .MDC_PROP_OPERATION , "Startup" );
7478 AgentInitializer .start (instrumentation , bootstrapURL , false );
79+ startupLogger .info ("ApplicationInsights Java Agent started successfully" );
7580 success = true ;
7681 LoggerFactory .getLogger (DiagnosticsHelper .DIAGNOSTICS_LOGGER_NAME )
7782 .info ("Application Insights Codeless Agent Attach Successful" );
7883 } catch (ThreadDeath td ) {
7984 throw td ;
8085 } catch (Throwable t ) {
8186 if (startupLogger != null ) {
82- startupLogger .error ("Agent failed to start. " , t );
87+ startupLogger .error ("ApplicationInsights Java Agent failed to start" , t );
8388 } else {
8489 t .printStackTrace ();
8590 }
8691 } finally {
8792 try {
88- StatusFile .putValueAndWrite ("AgentInitializedSuccessfully" , success );
93+ StatusFile .putValueAndWrite ("AgentInitializedSuccessfully" , success , startupLogger != null );
8994 } catch (Exception e ) {
90- startupLogger .error ("Error writing status.json" , e ); // lgtm[java/dereferenced-value-may-be-null]
95+ if (startupLogger != null ) {
96+ startupLogger .error ("Error writing status.json" , e );
97+ } else {
98+ e .printStackTrace ();
99+ }
91100 }
92101 MDC .clear ();
93102 }
94103 }
95104
96- private static Logger configureLogging (SelfDiagnostics selfDiagnostics ) {
105+ private static Logger configureLogging (SelfDiagnostics selfDiagnostics , Path agentPath ) {
97106 String logbackXml ;
98107 String destination = selfDiagnostics .destination ;
99- boolean logUnknownDestination = false ;
100108 if (DiagnosticsHelper .isAppServiceCodeless ()) {
101109 // User-accessible IPA log file. Enabled by default.
102110 if ("false" .equalsIgnoreCase (System .getenv (DiagnosticsHelper .IPA_LOG_FILE_ENABLED_ENV_VAR ))) {
@@ -114,58 +122,80 @@ private static Logger configureLogging(SelfDiagnostics selfDiagnostics) {
114122 System .setProperty ("ai.config.appender.etw.location" , "" );
115123 }
116124 logbackXml = "applicationinsights.appsvc.logback.xml" ;
117- } else if (destination == null || destination .equalsIgnoreCase ("console" )) {
118- logbackXml = "applicationinsights.console.logback.xml" ;
125+ } else if (destination == null || destination .equalsIgnoreCase ("file+ console" )) {
126+ logbackXml = "applicationinsights.file-and- console.logback.xml" ;
119127 } else if (destination .equalsIgnoreCase ("file" )) {
120128 logbackXml = "applicationinsights.file.logback.xml" ;
121- } else {
122- logUnknownDestination = true ;
129+ } else if (destination .equalsIgnoreCase ("console" )) {
123130 logbackXml = "applicationinsights.console.logback.xml" ;
131+ } else {
132+ throw new IllegalStateException ("Unknown self-diagnostics destination: " + destination );
124133 }
125134 ClassLoader cl = ConfigureLogging .class .getClassLoader ();
126135 if (cl == null ) {
127136 cl = ClassLoader .getSystemClassLoader ();
128137 }
129138 final URL configurationFile = cl .getResource (logbackXml );
130- System .setProperty ("applicationinsights.logback.configurationFile" , configurationFile .toString ());
131139
132- String logbackDirectory = selfDiagnostics .directory ;
133- String logbackLevel = selfDiagnostics .level ;
134- int logbackMaxFileSizeMB = selfDiagnostics .maxSizeMB ;
140+ Level level = getLevel (selfDiagnostics .level );
135141
136- if (logbackDirectory == null ) {
137- logbackDirectory = System .getProperty ("java.io.tmpdir" );
138- }
139- if (logbackDirectory == null ) {
140- // this should never get to here, but just in case, otherwise setProperty() will fail below
141- logbackDirectory = "." ;
142+ Path logFilePath = agentPath .resolveSibling (selfDiagnostics .file .path );
143+ Path logFileNamePath = logFilePath .getFileName ();
144+ if (logFileNamePath == null ) {
145+ throw new IllegalStateException ("Unexpected empty self-diagnostics file path" );
142146 }
143- System .setProperty ("applicationinsights.logback.directory" , logbackDirectory );
144- System .setProperty ("applicationinsights.logback.level" , logbackLevel );
145- System .setProperty ("applicationinsights.logback.maxFileSize" , logbackMaxFileSizeMB + "MB" );
146- System .setProperty ("applicationinsights.logback.totalSizeCap" , logbackMaxFileSizeMB * 2 + "MB" );
147- if (isDebugOrLower (logbackLevel )) {
148- // never want to log apache http at trace or debug, it's just way to verbose
149- System .setProperty ("applicationinsights.logback.level.org.apache.http" , "info" );
147+ String logFileName = logFileNamePath .toString ();
148+ String rollingFileName ;
149+ int index = logFileName .lastIndexOf ('.' );
150+ if (index != -1 ) {
151+ rollingFileName = logFileName .substring (0 , index ) + ".%i" + logFileName .substring (index );
150152 } else {
151- System . setProperty ( "applicationinsights.logback.level.org.apache.http" , logbackLevel ) ;
153+ rollingFileName = logFileName + ".%i" ;
152154 }
155+ Path rollingFilePath = logFilePath .resolveSibling (rollingFileName );
156+
157+ // never want to log apache http at trace or debug, it's just way to verbose
158+ Level atLeastInfoLevel = getMaxLevel (level , Level .INFO );
159+
160+ Level otherLibsLevel = level == Level .INFO ? Level .WARN : level ;
161+
153162 try {
154- Logger logger = LoggerFactory .getLogger ("com.microsoft.applicationinsights.agent" );
155- if (logUnknownDestination ) {
156- logger .error ("Unknown self-diagnostics destination: {}" , destination );
157- }
158- return logger ;
163+ System .setProperty ("applicationinsights.logback.configurationFile" , configurationFile .toString ());
164+
165+ System .setProperty ("applicationinsights.logback.file.path" , logFilePath .toString ());
166+ System .setProperty ("applicationinsights.logback.file.rollingPath" , rollingFilePath .toString ());
167+ System .setProperty ("applicationinsights.logback.file.maxSize" , selfDiagnostics .file .maxSizeMb + "MB" );
168+ System .setProperty ("applicationinsights.logback.file.maxIndex" , Integer .toString (selfDiagnostics .file .maxHistory ));
169+
170+ System .setProperty ("applicationinsights.logback.level.other" , otherLibsLevel .toString ());
171+ System .setProperty ("applicationinsights.logback.level" , level .levelStr );
172+
173+ System .setProperty ("applicationinsights.logback.level.atLeastInfo" , atLeastInfoLevel .levelStr );
174+
175+ return LoggerFactory .getLogger ("com.microsoft.applicationinsights.agent" );
159176 } finally {
160177 System .clearProperty ("applicationinsights.logback.configurationFile" );
161- System .clearProperty ("applicationinsights.logback.directory" );
178+ System .clearProperty ("applicationinsights.logback.file.path" );
179+ System .clearProperty ("applicationinsights.logback.file.rollingPath" );
180+ System .clearProperty ("applicationinsights.logback.file.maxSize" );
181+ System .clearProperty ("applicationinsights.logback.file.maxIndex" );
162182 System .clearProperty ("applicationinsights.logback.level" );
163- System .clearProperty ("applicationinsights.logback.maxFileSize" );
164- System .clearProperty ("applicationinsights.logback.totalSizeCap" );
165183 System .clearProperty ("applicationinsights.logback.level.org.apache.http" );
166184 }
167185 }
168186
187+ private static Level getMaxLevel (Level level1 , Level level2 ) {
188+ return level1 .isGreaterOrEqual (level2 ) ? level1 : level2 ;
189+ }
190+
191+ private static Level getLevel (String levelStr ) {
192+ Level level = Level .valueOf (levelStr );
193+ if (!level .levelStr .equalsIgnoreCase (levelStr )) {
194+ throw new IllegalStateException ("Unexpected self-diagnostic level: " + levelStr );
195+ }
196+ return level ;
197+ }
198+
169199 private static boolean isDebugOrLower (String level ) {
170200 return level .equalsIgnoreCase ("all" ) || level .equalsIgnoreCase ("trace" ) || level .equalsIgnoreCase ("debug" );
171201 }
0 commit comments