Tagging ADK for .NET

The Tagging ADK for .NET is used for protocol tagging only. In contrast with the Native ADK, it provides no means for instrumenting code, because instrumentation is provided by various .NET sensors. It is part of the Agent Development Kit (ADK). For basic tagging concepts, see Agent Development Kit (ADK).

Using the Tagging ADK

Setup and prerequisite

After installation of the ADK package, the .NET ADK library is located in <installation-dir>\adk\lib64\DynaTraceADK20.dll.

Add the respective reference to the ADK library in your .NET project.

Initialize the ADK

The initialization step is required once per process, on the client side as well as on the server side.

After successful initialization, the DynaTraceADKFactory lets you create a tagging object, which serves as the interface to the Agent.

using DynaTrace.DynaTraceADK;
// []
//
// initialize the ADK factory (once on process startup)
DynaTraceADKFactory.initialize();

Create a tagging object, which serves as a thin layer between the application and the Agent.

Tagging tagging = DynaTraceADKFactory.createTagging();

To free up resources allocated by the DynaTraceADKFactory, uninitialize the factory before your application quits.

// Uninitializing on process shutdown is necessary in order to disconnect properly from AppMon Server/Collector
// and to free up allocated resources
DynaTraceADKFactory.uninitialize();

The DynaTraceADKFactory is defined as follows:

namespace DynaTrace.DynaTraceADK {
	/// <summary>
	/// <see cref="DynaTraceADKFactory" /> creates an instance of an AppMon ADK.
	/// </summary>
	public class DynaTraceADKFactory {
		/// <summary>
		/// Initializes the <see cref="DynaTraceADKFactory" />
		/// </summary>
		public static void initialize() {
			DynaTraceADKFactoryImpl.initialize();
		}

		/// <summary>
		/// Creates an instance of <see cref="Tagging" />
		/// </summary>
		/// <returns>a <see cref="Tagging" /> instance</returns>
		public static Tagging createTagging() {
			return DynaTraceADKFactoryImpl.createTagging();
		}

		/// <summary>
		/// Uninitializes the <see cref="DynaTraceADKFactory" />
		/// </summary>
		public static void uninitialize() {
			DynaTraceADKFactoryImpl.uninitialize();
		}
	}
}

Tag a request

Complete the following steps to tag a remote call.

Client-Side (Caller)

  1. Retrieve the current AppMon TraceTag.
  2. Specify the location at which to include the server-side path, by inserting a link.
  3. Send the AppMon TraceTag along with the request to the server-side

Server-Side (Callee)

  1. Read the remote AppMon TraceTag.
  2. Place this tag on the server side.
  3. Start the server-side PurePath and continue processing.
  4. Mark the end of the server-side PurePath, after the request was processed.

Retrieve the TraceTag on the client side

You can retrieve the TraceTag either as a byte array or as a string. You can also use a predefined custom tag.

Option 1: byte array
byte[] dtTag = tagging.getTag();

Option 2: string
string tagAsString = tagging.getTagAsString();

Option 3: custom tagging
// assume that some kind of unique id exists
byte[] requestId = protocolData.getRequestId();
CustomTag customTag = tagging.createCustomTag(requestId);

The getTag must be called each time before issuing a remote call to the server side, even if it's still in the same transaction to the same server. The tag that is retrieved by getTag identifies just one call and cannot be reused.

When using custom tags, any request or message ID that is used to identify the remote call must be unique. Another call requires a new, unique identifier.

The next step on the client side is to specify where in the PurePath to include the server-side path, and whether the invocation is synchonous or asynchronous. You may or may not specify the AppMon tag. If you omit the tag parameter, the ADK internally uses the current one, which is identical to the recently retrieved TraceTag.

Important

Calling an ADK function between getTag* and linkClientPurePath is not permitted. If it is necessary to use any other calls between them, or if there are other instrumented methods in between, it is required to specify the AppMon TraceTag explicitly.

Use cases

Synchronous use case, using current trace tag:

tagging.linkClientPath(false);

Asynchronous use case, specifying the trace tag explicitly:

tagging.linkClientPath(true, dtTag);

Asynchronous use case, using a custom tag. In this case the tag must be specified:

tagging.linkClientPath(true, customTag);

Warning

Make sure that linkClientPath() is invoked before startServerPath(): call linkClientPurePath before actually transmitting the tag data to the server.

Calling any ADK functions between getTag/getTagAsString and linkClientPath is not permitted, unless you specify the AppMon TraceTag explicitly in the tagging.linkClientPath() call.

Place the TraceTag on the server side

You can set the TraceTag either as a byte array or as a string, depending on how you retrieved the tag on the client side.

Warning

Make sure that you set the tag before you start or end the server-side subpath.

Option 1: byte array
byte[] tag = [read trace tag];
tagging.setTag(tag);

A custom tag is always handled as a byte array:

byte[] customTag = [get the id from the request];
tagging.setCustomTag(customTag);

Option 2: string
string tagAsString = [read trace tag];
tagging.setTagFromString(tagAsString);

Mark the server-side path's beginning and end

On the server side, you must specify where your path starts and ends. Enclose the actual processing code with startServerPurePath() and endServerPurePath().

public void waitForRequest() {  }

public void execute(Request req) {  }

public void handleRequest(Request req) {
  tagging.setTag(req.getTag());
  tagging.startServerPurePath();
  execute(req);
  tagging.endServerPurePath();
}

public void run() {
  while(true) {
    Request req = waitForRequest();
    handleRequest(req);
  }
}

The tagging interface

The Tagging object provides all methods that an application needs to attach to or continue PurePaths.

namespace DynaTrace.DynaTraceADK {
	/// <summary>
	/// <see cref="Tagging" /> provides the user with everything needed for
	/// implementing tagging for proprietary protocols.
	/// Use <see cref="DynaTraceADKFactory" /> to acquire an instance
	/// </summary>
	public interface Tagging {
		/// <summary>
		/// Gets the current tag on the client side represented
		/// as byte array for serialization by the user.
		/// </summary>
		/// <returns>a byte array representing the tag</returns>
		byte [] getTag();

		/// <summary>
		/// Gets the current tag on the client side represented
		/// as string for serialization by the user.
		/// </summary>
		/// <returns>a string representing the tag</returns>
		string getTagAsString();

		/// <summary>
		/// Sets the tag on the server side from a byte array as
		/// deserialized by the user.
		/// </summary>
		/// <param name="tag">a byte array representing the tag</param>
		void setTag(byte [] tag);

		/// <summary>
		/// Sets the tag on the server side from a string as
		/// deserialized by the user.
		/// </summary>
		/// <param name="tag">a strin representing the tag</param>
		void setTagFromString(string tag);

		/// <summary>
		/// Inserts a synchronous or asynchronous link on the client side.
		/// </summary>
		/// <param name="asynchronous">true if asynchronous, false if synchronous</param>
		/// <remarks>
		/// There cannot be any instrumented calls between  <see cref="M:getTag()" />
		/// resp. <see cref="M:getTagAsString()" /> and this call.
		/// </remarks>
		void linkClientPurePath(bool asynchronous);

		/// <summary>
        /// Inserts a synchronous or asynchronous link on the client side.
        /// </summary>summary>
        /// <param name="asynchronous">true if asynchronous, false if synchronous</param>
        /// <param name="tag">specify a certain tag to be linked with (this allows
        ///   having instrumented calls between {@link #getTag()} and this call).
        ///   The tag can be specified either as byte array or as string.</param>
        void linkClientPurePath(bool asynchronous, object tag);

		/// <summary>
		/// Starts a server-side PurePath
		/// </summary>
		void startServerPurePath();

		/// <summary>
		/// Ends a server-side PurePath
		/// </summary>
		void endServerPurePath();

		/// <summary>
		/// Convert a tag to its string format
		/// </summary>
        /// <param name="tag">dynaTrace tag as byte array</param>
        /// <returns>the dynaTrace tag's string representation</returns>
        string convertTagToString(byte[] tag);

		/// <summary>
		/// Convert a dynaTrace string tag to it's byte representation
		/// </summary>
        /// <param name="tag">tag in string format</param>
        /// <returns>the tag's byte array representation</returns>
        byte[] convertStringToTag(string tag);

		/// <summary>
		/// Check if specified tag is valid.
		/// </summary>
        /// <param name="tag">dynaTrace tag</param>
        /// <returns>true, if the specified tag is a valid tag</returns>
        bool isTagValid(object tag);

        /// <summary>Create a custom tag object</summary>
        /// <param name="tagData">byte array containing the custom tag</param>
        /// <returns>CustomTag object</returns>
        CustomTag createCustomTag(byte[] tagData);

		/// <summary>
        /// Set specified custom tag at server side. The function has the same
        /// functionality as setTag(), but allows to continue a PurePath by using
        /// the specified custom tag.
		/// </summary>
        /// <param name="customTag">Custom tag to be continued</param>
        void setCustomTag(byte[] customTag);

    }

    /// <summary>
    /// Custom tagging: wrapper class for custom tags
    /// </summary>
    public interface CustomTag {
        /// <summary>
        /// Get current custom tag as byte array
        /// </summary>
        /// <returns>custom tag if present, null otherwise</returns>
        byte[] getTag();

        /// <summary>
        /// Get string representation of this custom tag in the format <currentTag>:<prevTag>
        /// </summary>
        /// <returns>hex string representation of this tag</returns>
        string asString();
    }
}