This page describes the advanced configuration properties for the AppDynamics .NET Agent for Linux you use to enable the .NET Agent to work without Docker. Before you start instrumenting your applications with the .NET Agent, you must use the current version of the .NET Core 2.0+. See .NET Agent Configuration Properties.

Agent Configuration File

The agent configuration file is similar to the one used to configure .NET Core Agent on Windows.

Once you have deployed the agent, you can customize the instrumentation of your application.

You can edit the AppDynamicsConfig.json file using this information:

{
  "controller": {
    "host": "controller.saas.appdynamics.com",
    "port": 443,
    "account": "account-name",
    "password": "access-key",
    "ssl": true
    "proxy" : {
        "host": "proxy-host",
        "port": 9090,
           "authentication": {
              "username": "proxy-user",
              "password": "proxy-password"
         }
      }
  },
  "application": {
    "name": "My Application",
    "tier": "Sample tier",
    "node": "Instance1",
	"reusenodename": "true",
	"nodenameprefix": "prefix"
  },
  "analytics": {
	"host": "localhost",
	"port": 9090
  },
  "feature": [
    "FULL_AGENT"
  ]
}
CODE

The .NET Agent for Linux supports reuse node name configuration to help manage monitoring environments where there are many CLRs with short life spans. The CLR node names are reused to avoid a proliferation of differently named nodes in AppDynamics. Include the "reusenodename": "true" configuration, with "nodenameprefix": "prefix" to enable reuse node name without having to supply a specific node name.

You can also use environment variables to configure reuse node name, such as ENV APPDYNAMICS_AGENT_REUSE_NODE_NAME=true and ENV APPDYNAMICS_AGENT_REUSE_NODE_NAME_PREFIX=<prefix>.

Configure Using AppDynamicsConfig.json: If you are configuring your agent using environment variables with the json configuration file, or just with the json configuration file, you must include the FULL_AGENT feature in the json file; otherwise, the agent will not work.
,
  "feature": [
    "FULL_AGENT"
  ]

FULL_AGENT feature mode is automatically enabled when configuring the agent just using environment variables.

.NET Agent for Linux does not support extended functionality, such as specifying instrumentors and allowlisting. Do not specify these if you copy the configuration from .NET Core Agent on Windows.

Configuration Options

You can enable the agent to work without Docker. However, you must ensure that the OS is supported by the current agent.

  1. Make these files available to the application. They can be located next to the application files or in a separate folder:

    • AppDynamics.Agent.netstandard.dll

    • libappdprofiler.so

    • libappdprofiler_musl.so

    • libappdprofiler_glibc.so

  2. Create these environment variables by adding them to your application:

    Environment Variable NameValue
    CORECLR_PROFILER{57e1aa68-2229-41aa-9931-a6e93bbc64d8}
    CORECLR_ENABLE_PROFILING1
    CORECLR_PROFILER_PATHPath to the libappdprofilerdynamic library. For example, <application_folder_path>/libappdprofiler.so
    See Using .NET Core for Linux SDK to determine the location of the libappdprofiler.so library.

    You can create environment variables on multiple levels so it is important that you set them in the context of the monitored application:

    • Environment variables are inherited from global host level.
    • Environment variables are parent process or service.
    • Environment variables are set prior to the start of the application using the shell script or similar.
  3. Place the agent configuration file next to the appropriate binaries. There are two supported options:

    • Global agent configuration file - You can place the AppDynamicsConfig.json file next to the agent binaries. This method ensures that the default option to monitor each application configured is used for the agent.

      The .NET Agent for Linux does not support overriding node name in the agent configuration. Therefore, monitoring multiple applications on the same host using global configuration is not supported. Only the first application reports.

    • Local agent configuration - You can place the [appname].AppDynamicsConfig.json file next to the application binaries, where [appname] should match your application DLL/EXE name. Using this option, you can attach AppDynamics configuration to the application package and deploy it as a bundle. It is activated when you set the proper environment variables and the agent binaries are present.

      Local agent configuration has higher priority than global configuration.

Log Configuration Options

By default, you can use the boost log for both the profiler and the .NET Agent. Logging occurs even if no log file exists. By default, these three log files are created: 

  • Agent Log - Filename is Agent_%N.log and the default log level is INFO.
  • Profiler Log - Filename is Profiler_%N.log and the default log level is INFO.
  • Warn Log - Filename is Warn_%N.log and the default log level is WARN.

The log configuration is read during the profiler initialization. Before the log configuration is read, some logs are printed to the console. 

This table describes the properties that you can configure in the log configuration file.

Log PropertyDescription
max_size Maximum total size of stored files, in bytes. Default value is 10485760 bytes (10 MB).
  • Maximum capacity per logger is: max_size * max_files.
  • Rotation occurs when the file size reaches max_size.

For example, if you configure the Agent log using the default values for max_size and max_files:

  • When a log file (Agent_0.log) reaches its max_size (10 MB), a new file named (Agent_1.log) is created. 
  • Once it reaches the maximum number of files, the older file is deleted and a new file is created. The log directory is updated with a new set of files [Agent_1.log, Agent_2.log, ...... Agent_9.log, Agent_10.log], Agent_0.log is deleted, and a new file named Agent_10.log is created.

If the log directory contains the log files from a previous run, then the newly initiated agent creates a log file using an incremental value from the previous run. For example, If the previous run has two agent logs, Agent_0.log and Agent_1.log, then the newly initiated Agent creates Agent_3.log.

max_filesMaximum total number of stored files. Default value is 10.
directory 

The root directory. It accepts both relative and absolute path; however, no environment variable is accepted. Default value is %TEMP%/appd/dotnet.

filename 

The file name. By default, no process ID is included in the file name; however, you can include and configure the process ID in the filename (%P). For example, if you configure the filename as Log_%P_%N.log, then the filename appears as Log_1123_0.Log (where 1123 is the process ID). Default value is Agent_%N.log (where %N represents the incremental value starting from 0).

exclude_tidDetermines whether to include the native thread ID in the log file. Default value is false
level 

The minimum log level. Accepts these values: Trace, Debug, Info, Warn, Error, and Fatal. Default value is Info. These values are case-insensitive.

channel 

This field accepts:

  • Fully qualified class name.
  • Class name with wildcard ( * ) at the start, end, or at both the ends of the name.
  • Empty channel name, or .* or * These values are used as the default channel names.

To incorporate any changes you made to the logging configuration, you must restart the application. The auto-reload feature for logging configuration is not supported.

Log Content Example

This log example shows content for the Agent_0.log file: 

Agent_0.log

2021-05-24 15:26:03.741862 2056 11672 3 INFO [com.appdynamics.LifetimeManager] Initializing via agent bootstrap
CODE

Whereas: 

  • 2021-05-24 15:26:03.741862 is the timestamp.
  • 2056 is the process ID. 
  • 11672 is the native thread ID.
  • 3 is the managed thread ID.
  • INFO is the log level.
  • com.appdynamics.LifetimeManager is the channel name.
  • Initializing via agent bootstrap is the log content.

Log Structure

This log example contains two processes: 11120 and 76890. Based on the log configuration, each process has its own set of log files.

  • If process 11120 is initiated first, then it may create Agent_0.log (for Agent logs) and Profiler_0.log (for Profiler logs). 
  • When process 76890 is initiated, then it may create Agent_1.log (for Agent logs) and Profiler_1.log (for Profiler logs).
  • Whichever log file reaches its maximum size first, its next log file is created by adding an incremental number to the file name. Log ordering is not maintained and differs for each process.

    Logs

    Profiler_0.log 
    Profiler_1.log 
    Warn_0.log 
    BusinessTransactionsLog_0.log 
    ....
    .... 
    .... 
    Agent_0.log 
    Agent_1.log 
    Profiler_2.log 
    .... 
    .... 
    .... 
    Agent_2.log 
    CODE

Supported Features

This table describes the supported Boost log features: 

FeatureDescription

Log order rules

No rules are processed after a final rule matches.

Rules are applied:

    • Based on the order of the logging configuration in the AppDynamicsConfig.json file.
    • When the log message channel name matches the channel name of the log configuration.
    • When the severity of the log message =< the level of the log configuration.

However, if the log is written using the first logger, and the channel name is matched using the second logger with a wildcard, the second logger will not write messages to log files. 

level Minimal level to log.
Wildcard character ( * )
  • If the wildcard is in the middle of a word (for example, com.*.test), then it is used as the default channel name ( * )
  • You can include a wildcard at:
    • The beginning (for example, *.appdynamics.test
    • The end (for example, com.appdynamics.*)
    • Both the beginning and end (for example, *.appdynamics.*)


Log Order Rules Examples

For this log order rules example, there are N loggers: logger1, logger2 ... loggerN.

where loggerN depends on logger(N-1) ... logger1.
and logger(N-1) depends on logger(N-2) ...logger1, and so on.

  1. Example A: The "ByteCode" log is part of the "AgentLog". As a result, no logging occurs through ByteCode logger. This is based on the order of the logging configuration in the AppDynamicsConfig.json file.

      {"filename" : "RESTHearbeat", "level" : "Info", "channel" : "com.appdynamics.REST.HeartBeatLog" },
      {"filename" : "AgentLog", "level" : "Info", "channel" : "*" },
      {"filename" : "ByteCode","level" : "Info","channel" : "com.appdynamics.bci.*" }
    CODE

    Example B: The "RESTHeartbeat" log is part of "REST". As a result, the "RESTHeartbeat" log is ignored.

      {"filename" : "REST", "level" : "Info", "channel" : "com.appdynamics.REST.*" },
      {"filename" : "RESTHeartbeat", "level" : "Info", "channel" : "com.appdynamics.REST.HeartBeatLog" }
    CODE
  2. Although "RESTHeartbeat" and "REST" log have the exact same channel name, only the minLogLevel of the first logger is considered. In this case, it is "Info".

      {"filename" : "REST", "level" : "Info", "channel" : "com.appdynamics.REST.HeartBeatLog" },
      {"filename" : "RESTHeartbeat", "level" : "Trace", "channel" : "com.appdynamics.REST.HeartBeatLog" }
    CODE
  3. Channels not written through loggers "RESTHearbeat" and "ByteCode" are written through the "AgentLog" logger.

    The AgentLog will not have any entries from RESTHeartbeat or ByteCode.

      {"filename" : "RESTHearbeat", "level" : "Info", "channel" : "com.appdynamics.REST.HeartBeatLog" },
      {"filename" : "ByteCode", "level" : "Info", "channel" : "com.appdynamics.bci.*" }, 
      {"filename" : "AgentLog","level" : "Info","channel" : "*" }
    CODE

Log Configuration Examples

This example shows how to set logging configuration. Each log file can have its own set of configurations.

AppDynamicsConfig.json

{
  "controller": {
    "host": "......"
  },
  "application": {
    "name": "..."
  },
  "log": [
    {
      "filename": "WarnLog",
      "level": "WARN",
      "channel": "*"
    },
    {
      "filename": "Profiler",
      "level": "INFO",
      "directory": "/tmp/appd/logs",
      "channel": "appd.agent.Profiler"
    },
    {
      "filename": "BusinessTransactionsLog",
      "level": "INFO",
      "channel": "com.appdynamics.BusinessTransactions"
    },
    {
      "filename": "RESTHearbeat",
      "level": "INFO",
      "channel": "com.appdynamics.REST.HeartBeatLog"
    },
    {
      "filename": "ByteCode",
      "level": "INFO",
      "channel": "com.appdynamics.bci.*"
    },
    {
      "filename": "RESTCommunications",
      "level": "INFO",
      "channel": "com.appdynamics.REST.*"
    },
    {
      "filename": "RESTCommunications",
      "level": "INFO",
      "channel": "com.appdynamics.METRICS.MetricSender"
    },
    {
      "filename": "SamplingTrace",
      "level": "TRACE",
      "channel": "com.appdynamics.ManagedAgentAPI.DumpStats"
    },
    {
      "filename": "Analytics",
      "level": "INFO",
      "channel": "com.appdynamics.ee.service.analytics.Analytics",
      "max_size": 31457280,
      "max_files": 2,
      "directory": "./logs",
      "exclude_tid": false
    },
    {
      "filename": "Agent",
      "level": "INFO",
      "channel": "*"
    }
  ]
}
CODE

This example shows multiple log entries for the same file (both the directory and filename have the same value). The file log configuration uses the first entry, and all subsequent configuration for max_sizemax_files and exclude_tid is ignored.

AppDynamicsConfig.json

{
     "filename": "agent",
     "level": "TRACE",
     "max_size":1000,
     "max_files":2,
     "channel": "com.appdynamics.METRICS.MetricSender"
    },
    {
     "filename": "agent",
     "level": "DEBUG",
     "max_size":2000,
     "max_files":2,
     "channel": "com.appdynamics.METRICS.*"
    },
    {
     "filename": "agent",
     "level": "INFO",
     "max_size":3000,
     "max_files":1,
     "channel": "com.appdynamics.*"
    }
}
CODE