From abfd60730fee107737ec3c7e61230e4ad89aa1f7 Mon Sep 17 00:00:00 2001
From: tison <alexandre.tison@synchrotron-soleil.fr>
Date: Mon, 14 Apr 2025 16:23:27 +0200
Subject: [PATCH 1/4] Modified pom for JTango V10 tests

---
 pom.xml | 210 +++++++++++++++++++++++++++++---------------------------
 1 file changed, 108 insertions(+), 102 deletions(-)

diff --git a/pom.xml b/pom.xml
index f0db043..86c4766 100755
--- a/pom.xml
+++ b/pom.xml
@@ -1,106 +1,112 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
-	xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-	<modelVersion>4.0.0</modelVersion>
-	
-	<parent>
-		<artifactId>java-updated-versions</artifactId>
-		<groupId>fr.soleil.maven.parent</groupId>
-		<version>0-SNAPSHOT</version>
-	</parent>
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0">
+    <modelVersion>4.0.0</modelVersion>
 
-	<groupId>fr.soleil.deviceservers</groupId>
-	<artifactId>TangoParser</artifactId>
-	<version>3.3.10</version>
-	<name>TangoParser</name>
-	<description>TangoParser Device</description>
-	
-	<developers>
-		<developer>
-			<id>abeille</id>
-			<name>Gwenaelle Abeille</name>
-			<email>gwenaelle.abeille@synchrotron-soleil.fr</email>
-			<organization>Synchrotron Soleil</organization>
-			<organizationUrl>http://www.synchrotron-soleil.fr</organizationUrl>
-			<roles>
-				<role>Java Developer</role>
-			</roles>
-			<timezone>1</timezone>
-		</developer>
-	</developers>
-	
-	<scm>
-		<connection>scm:git:git@gitlab.synchrotron-soleil.fr:software-control-system/tango-devices/calculation/tangoparser.git</connection>
-		<developerConnection>scm:git:git@gitlab.synchrotron-soleil.fr:software-control-system/tango-devices/calculation/tangoparser.git</developerConnection>
-		<url>https://gitlab.synchrotron-soleil.fr/software-control-system/tango-devices/calculation/tangoparser</url>
-	</scm>
-	
-	<build>
-		<plugins>
-			<plugin>
-				<artifactId>maven-surefire-plugin</artifactId>
-				<configuration>
-					<includes>
-						<include>**/Test*.java</include>
-						<include>**/*Test.java</include>
-						<include>**/*TestCase.java</include>
-						<include>**/*Test*.java</include>
-					</includes>
-					<systemProperties>
-						<property>
-							<name>TANGO_HOST</name>
-							<value>${env.TANGO_HOST}</value>
-						</property>
-						<property>
-							<name>org.tango.server.checkalarms</name>
-							<value>false</value>
-						</property>
-					</systemProperties>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-	<dependencies>
-		<dependency>
-			<groupId>org.scijava</groupId>
-			<artifactId>jep</artifactId>
-			<exclusions>
-				<exclusion>
-					<artifactId>jama</artifactId>
-					<groupId>jama</groupId>
-				</exclusion>
-			</exclusions>
-		</dependency>
-		<dependency>
-			<groupId>gov.nist.math</groupId>
-			<artifactId>jama</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.tango-controls</groupId>
-			<artifactId>JTangoClientLang</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.tango-controls</groupId>
-			<artifactId>JTangoServer</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.commons</groupId>
-			<artifactId>commons-math3</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>com.google.guava</groupId>
-			<artifactId>guava</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
+    <parent>
+        <artifactId>java-updated-versions</artifactId>
+        <groupId>fr.soleil.maven.parent</groupId>
+        <version>0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>fr.soleil.deviceservers</groupId>
+    <artifactId>TangoParser</artifactId>
+    <version>3.3.10</version>
+    <name>TangoParser</name>
+    <description>TangoParser Device</description>
+
+    <developers>
+        <developer>
+            <id>abeille</id>
+            <name>Gwenaelle Abeille</name>
+            <email>gwenaelle.abeille@synchrotron-soleil.fr</email>
+            <organization>Synchrotron Soleil</organization>
+            <organizationUrl>http://www.synchrotron-soleil.fr</organizationUrl>
+            <roles>
+                <role>Java Developer</role>
+            </roles>
+            <timezone>1</timezone>
+        </developer>
+    </developers>
+
+    <scm>
+        <connection>
+            scm:git:git@gitlab.synchrotron-soleil.fr:software-control-system/tango-devices/calculation/tangoparser.git
+        </connection>
+        <developerConnection>
+            scm:git:git@gitlab.synchrotron-soleil.fr:software-control-system/tango-devices/calculation/tangoparser.git
+        </developerConnection>
+        <url>https://gitlab.synchrotron-soleil.fr/software-control-system/tango-devices/calculation/tangoparser</url>
+    </scm>
+
+    <properties>    <!--<jtango.version>9.7.3-SNAPSHOT</jtango.version>-->
+        <jtango.version>10.0.0-SNAPSHOT</jtango.version>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <includes>
+                        <include>**/Test*.java</include>
+                        <include>**/*Test.java</include>
+                        <include>**/*TestCase.java</include>
+                        <include>**/*Test*.java</include>
+                    </includes>
+                    <systemProperties>
+                        <property>
+                            <name>TANGO_HOST</name>
+                            <value>${env.TANGO_HOST}</value>
+                        </property>
+                        <property>
+                            <name>org.tango.server.checkalarms</name>
+                            <value>false</value>
+                        </property>
+                    </systemProperties>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.scijava</groupId>
+            <artifactId>jep</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>jama</artifactId>
+                    <groupId>jama</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>gov.nist.math</groupId>
+            <artifactId>jama</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.tango-controls</groupId>
+            <artifactId>JTangoServer</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-math3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
 </project>
-- 
GitLab


From a89d15d3c710ec246148634a2e80c398bac5db81 Mon Sep 17 00:00:00 2001
From: tison <alexandre.tison@synchrotron-soleil.fr>
Date: Mon, 14 Apr 2025 16:42:22 +0200
Subject: [PATCH 2/4] Added info attribute (DevInfo)

---
 .../java/fr/soleil/tango/server/tangoparser/TangoParser.java  | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/main/java/fr/soleil/tango/server/tangoparser/TangoParser.java b/src/main/java/fr/soleil/tango/server/tangoparser/TangoParser.java
index 6eab748..8b27294 100755
--- a/src/main/java/fr/soleil/tango/server/tangoparser/TangoParser.java
+++ b/src/main/java/fr/soleil/tango/server/tangoparser/TangoParser.java
@@ -44,6 +44,7 @@ import org.tango.server.annotation.State;
 import org.tango.server.annotation.Status;
 import org.tango.server.annotation.TransactionType;
 import org.tango.server.attribute.AttributeConfiguration;
+import org.tango.server.attribute.DeviceInfoAttribute;
 import org.tango.server.attribute.IAttributeBehavior;
 import org.tango.server.attribute.log.LogAttribute;
 import org.tango.server.device.DeviceManager;
@@ -516,7 +517,8 @@ public final class TangoParser {
 		// add log attribute
 		dynMngt.addAttribute(new LogAttribute(1000, logger, LoggerFactory.getLogger(DynamicAttributeParser.class),
 				LoggerFactory.getLogger(CacheRefresher.class), LoggerFactory.getLogger(TangoSource.class)));
-
+		// add info attribute
+		dynMngt.addAttribute(device.getDeviceInfoAttribute());
 		initManagement();
 
 		if (scanMode) {
-- 
GitLab


From 86ac9dd1ac95195a71288e2e494372299b216581 Mon Sep 17 00:00:00 2001
From: tison <alexandre.tison@synchrotron-soleil.fr>
Date: Tue, 15 Apr 2025 09:36:08 +0200
Subject: [PATCH 3/4] Testing with OpenTelemetry

---
 .../fr/soleil/tango/parser/AJepParser.java    | 71 ++++++++++++-------
 1 file changed, 46 insertions(+), 25 deletions(-)

diff --git a/src/main/java/fr/soleil/tango/parser/AJepParser.java b/src/main/java/fr/soleil/tango/parser/AJepParser.java
index e744981..be87d54 100755
--- a/src/main/java/fr/soleil/tango/parser/AJepParser.java
+++ b/src/main/java/fr/soleil/tango/parser/AJepParser.java
@@ -9,6 +9,7 @@ import java.util.Map;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
+import fr.esrf.TangoApi.telemetry.*;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import org.lsmp.djep.vectorJep.Dimensions;
@@ -26,6 +27,7 @@ import org.nfunk.jep.SymbolTable;
 import org.nfunk.jep.Variable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.tango.server.ServerManager;
 import org.tango.utils.CaseInsensitiveMap;
 import org.tango.utils.DevFailedUtils;
 
@@ -67,6 +69,7 @@ import fr.soleil.tango.parser.function.spectrum.VSinus;
 public abstract class AJepParser {
 
 	private Logger logger = LoggerFactory.getLogger(AJepParser.class);
+	private final OpenTelemetry openTelemetry;
 	/**
 	 * Use in throw DevFailed
 	 */
@@ -103,6 +106,14 @@ public abstract class AJepParser {
 		this.constants = constants;
 		this.dataSource = dataSource;
 
+		this.openTelemetry = new OpenTelemetry(deviceName);
+		this.openTelemetry.setTangoDeviceName(deviceName);
+		this.openTelemetry.setTangoProcessId(ServerManager.getInstance().getPid());
+		this.openTelemetry.setTangoHostName(ServerManager.getInstance().getHostName());
+		this.openTelemetry.setTangoServerName(ServerManager.getInstance().getServerName());
+		this.openTelemetry.setTangoProcessKind(EProcessKind.SERVER);
+		this.openTelemetry.init();
+
 		jep = new VectorJep();
 		jep.addStandardFunctions();
 		jep.addStandardConstants();
@@ -254,36 +265,46 @@ public abstract class AJepParser {
 			locker.lock();
 		}
 		try {
-			// get results for tango attributes
-			for (final String variableName : variables.values()) {
-				if(!tangoVariable.containsKey(variableName)) {
-					final AttributeResult r = dataSource.getResult(sourceName, variableName);
-					if (r != null) {
-						final Object value = r.getValue();
-						final DevFailed e = r.getError();
-						if (e != null && attributes.containsValue(variableName)) {
-							throw e;
-						} else if (value != null) {
-							tangoVariable.put(variableName, value);
-							jep.addVariable(variableName, fromStandardToJepType(value));
-							logger.debug("add tango result : {}={}", variableName, value);
+			TangoContext ctx = openTelemetry.handleServer();
+			TangoSpan span = ctx.buildSpan("getValue (Eq)", sourceName, expressions); // static Method ?
+			try (TangoScope scope = span.makeCurrent()) {
+				// get results for tango attributes
+				for (final String variableName : variables.values()) {
+					if(!tangoVariable.containsKey(variableName)) {
+						final AttributeResult r = dataSource.getResult(sourceName, variableName);
+						if (r != null) {
+							final Object value = r.getValue();
+							final DevFailed e = r.getError();
+							if (e != null && attributes.containsValue(variableName)) {
+								throw e;
+							} else if (value != null) {
+								tangoVariable.put(variableName, value);
+								jep.addVariable(variableName, fromStandardToJepType(value));
+								logger.debug("add tango result : {}={}", variableName, value);
+							}
 						}
+					} else {
+						final Object value = tangoVariable.get(variableName);
+						jep.addVariable(variableName, fromStandardToJepType(value));
 					}
-				} else {
-					final Object value = tangoVariable.get(variableName);
-					jep.addVariable(variableName, fromStandardToJepType(value));
 				}
-			}
 
-			// get results for variables
-			for (final AJepParser variable : variablesJepToRead.values()) {
-				final Object r = variable.getValue(lock, tangoVariable);
-				logger.debug("get input variable {} = {}", variable, r);
-				jep.addVariable(variable.getName(), fromStandardToJepType(r));
+				// get results for variables
+				for (final AJepParser variable : variablesJepToRead.values()) {
+					final Object r = variable.getValue(lock, tangoVariable);
+					logger.debug("get input variable {} = {}", variable, r);
+					jep.addVariable(variable.getName(), fromStandardToJepType(r));
+				}
+				Object lastWriteResult = parse(name, expressions);
+				lastWriteResult = fromJepToStandardType(lastWriteResult);
+				return lastWriteResult;
+			} catch (final Exception e) {
+				span.recordException(e);
+                throw DevFailedUtils.newDevFailed(e);
+            } finally {
+				span.end();
 			}
-			Object lastWriteResult = parse(name, expressions);
-			lastWriteResult = fromJepToStandardType(lastWriteResult);
-			return lastWriteResult;
+
 		} finally {
 			if (lock) {
 				locker.unlock();
-- 
GitLab


From de9c8fe9052c6675bec3dc200a4d475d825815a4 Mon Sep 17 00:00:00 2001
From: tison <alexandre.tison@synchrotron-soleil.fr>
Date: Wed, 16 Apr 2025 16:24:15 +0200
Subject: [PATCH 4/4] Added OpenTelemetry traces for any GetValue

---
 .../fr/soleil/tango/parser/AJepParser.java    |  10 +-
 .../tango/parser/datasource/TangoSource.java  | 157 +++++++++++-------
 .../tangoparser/DynamicAttributeParser.java   |  30 +++-
 3 files changed, 130 insertions(+), 67 deletions(-)

diff --git a/src/main/java/fr/soleil/tango/parser/AJepParser.java b/src/main/java/fr/soleil/tango/parser/AJepParser.java
index be87d54..7711c92 100755
--- a/src/main/java/fr/soleil/tango/parser/AJepParser.java
+++ b/src/main/java/fr/soleil/tango/parser/AJepParser.java
@@ -1,11 +1,7 @@
 package fr.soleil.tango.parser;
 
 import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -266,10 +262,11 @@ public abstract class AJepParser {
 		}
 		try {
 			TangoContext ctx = openTelemetry.handleServer();
-			TangoSpan span = ctx.buildSpan("getValue (Eq)", sourceName, expressions); // static Method ?
+			TangoSpan span = ctx.buildSpan("getValue", sourceName, variables.values().toArray(new String[0])); // static Method ?
 			try (TangoScope scope = span.makeCurrent()) {
 				// get results for tango attributes
 				for (final String variableName : variables.values()) {
+					span.startProcessing(variableName);
 					if(!tangoVariable.containsKey(variableName)) {
 						final AttributeResult r = dataSource.getResult(sourceName, variableName);
 						if (r != null) {
@@ -287,6 +284,7 @@ public abstract class AJepParser {
 						final Object value = tangoVariable.get(variableName);
 						jep.addVariable(variableName, fromStandardToJepType(value));
 					}
+					span.endProcessing(variableName);
 				}
 
 				// get results for variables
diff --git a/src/main/java/fr/soleil/tango/parser/datasource/TangoSource.java b/src/main/java/fr/soleil/tango/parser/datasource/TangoSource.java
index a28de87..1330314 100755
--- a/src/main/java/fr/soleil/tango/parser/datasource/TangoSource.java
+++ b/src/main/java/fr/soleil/tango/parser/datasource/TangoSource.java
@@ -7,10 +7,12 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.TreeMap;
 
+import fr.esrf.TangoApi.telemetry.*;
 import org.lsmp.djep.vectorJep.values.MVector;
 import org.lsmp.djep.vectorJep.values.Matrix;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.tango.server.ServerManager;
 import org.tango.utils.DevFailedUtils;
 
 import fr.esrf.Tango.AttrDataFormat;
@@ -35,17 +37,34 @@ public class TangoSource {
 	private final AttributeResults attributeData = new AttributeResults();
 	private final Map<String, TangoGroupAttribute> writeGroups = new TreeMap<String, TangoGroupAttribute>();
 	private final boolean isSynchronous;
+	private final OpenTelemetry openTelemetry;
 
 	TangoSource(final String deviceName, final String name, final boolean isSynchronous) {
 		this.deviceName = deviceName.toLowerCase(Locale.ENGLISH);
 		this.name = name.toLowerCase(Locale.ENGLISH);
 		this.isSynchronous = isSynchronous;
+
+		this.openTelemetry = new OpenTelemetry(this.deviceName);
+		this.openTelemetry.setTangoDeviceName(this.deviceName);
+		this.openTelemetry.setTangoProcessId(ServerManager.getInstance().getPid());
+		this.openTelemetry.setTangoHostName(ServerManager.getInstance().getHostName());
+		this.openTelemetry.setTangoServerName(ServerManager.getInstance().getServerName());
+		this.openTelemetry.setTangoProcessKind(EProcessKind.SERVER);
+		this.openTelemetry.init();
 	}
 
 	TangoSource() {
 		this.deviceName = "";
 		this.name = "";
 		this.isSynchronous = false;
+
+		this.openTelemetry = new OpenTelemetry(deviceName);
+		this.openTelemetry.setTangoDeviceName(deviceName);
+		this.openTelemetry.setTangoProcessId(ServerManager.getInstance().getPid());
+		this.openTelemetry.setTangoHostName(ServerManager.getInstance().getHostName());
+		this.openTelemetry.setTangoServerName(ServerManager.getInstance().getServerName());
+		this.openTelemetry.setTangoProcessKind(EProcessKind.SERVER);
+		this.openTelemetry.init();
 	}
 
 	/**
@@ -83,9 +102,20 @@ public class TangoSource {
 
 	public synchronized void refresh() throws DevFailed {
 		logger.debug("read attributes for {}", attributeData);
-		if (!isEmpty()) {
-			readGroup.readAync();
-			getResults();
+		TangoContext ctx = openTelemetry.handleServer();
+		TangoSpan span = ctx.buildSpan("refresh", deviceName, ""); // static Method ?
+		try (TangoScope scope = span.makeCurrent()) {
+			span.startProcessing("");
+			if (!isEmpty()) {
+				readGroup.readAync();
+				getResults();
+			}
+			span.endProcessing("");
+		} catch (Exception e) {
+			span.recordException(e);
+		}
+		finally {
+			span.end();
 		}
 	}
 
@@ -98,66 +128,77 @@ public class TangoSource {
 		final DeviceAttribute[] results = readGroup.getReadAsyncReplies();
 		// final Iterator<AttributeResult> it = attributeData.values().iterator();
 		final String[] attributeNames = attributeData.getAllAttributes();
-		for (int i = 0; i < results.length; i++) {
-			// final AttributeResult result = it.next();
-			final String attributeName = attributeNames[i];
-			// final String attributeName = result.getName();
-			final AttrDataFormat format = attributeData.getFormat(attributeName);
-			// reset last error
-			attributeData.setAttributeResult(attributeName, null);
-			attributeData.resetAttributeResultError(attributeName);
-			if (results[i] != null) {
-				try {
-					final int type = results[i].getType();
-					if (format.equals(AttrDataFormat.SCALAR)) {
-						Object tmpReadValue = InsertExtractUtils.extractRead(results[i], AttrDataFormat.SCALAR);
-						if (tmpReadValue instanceof DevState) {
-							tmpReadValue = ((DevState) tmpReadValue).value();
-						}
-						attributeData.setAttributeResult(attributeName, tmpReadValue);
-					} else if (format.equals(AttrDataFormat.SPECTRUM)) {
-						if (type == TangoConst.Tango_DEV_STRING) {
-							throw DevFailedUtils.newDevFailed("TYPE_ERROR", "array of strings not supported");
-						} else if (type == TangoConst.Tango_DEV_BOOLEAN) {
-							throw DevFailedUtils.newDevFailed("TYPE_ERROR", "array of boolean not supported");
-						}
-						final Object tmpReadValue = InsertExtractUtils.extractRead(results[i], AttrDataFormat.SPECTRUM);
-						final MVector vect = new MVector(Array.getLength(tmpReadValue));
-						for (int j = 0; j < Array.getLength(tmpReadValue); j++) {
-							vect.setEle(j, Array.get(tmpReadValue, j));
-						}
-						attributeData.setAttributeResult(attributeName, vect);
-					} else {
-						if (format.equals(AttrDataFormat.FMT_UNKNOWN)) {
-							throw DevFailedUtils.newDevFailed("TYPE_ERROR", "Unknown format");
-						} else if (type == TangoConst.Tango_DEV_STRING) {
-							throw DevFailedUtils.newDevFailed("TYPE_ERROR", "images of strings not supported");
-						} else if (type == TangoConst.Tango_DEV_BOOLEAN) {
-							throw DevFailedUtils.newDevFailed("TYPE_ERROR", "images of boolean not supported");
-						}
-						final Object tmpReadValue = InsertExtractUtils.extractRead(results[i], AttrDataFormat.IMAGE);
-						int dim1 = Array.getLength(tmpReadValue);
-						int dim2 = 0;
-						if (dim1 > 0) {
-							Object subArray = Array.get(tmpReadValue, 0);
-							dim2 = Array.getLength(subArray);
-						}
-						Matrix matrix = (Matrix) Matrix.getInstance(dim1, dim2);
-						for (int j = 0; j < dim1; j++) {
-							Object subArray = Array.get(tmpReadValue, j);
-							for (int k = 0; k < dim2; k++) {
-								matrix.setEle(j, k, Array.get(subArray, k));
+		TangoContext ctx = openTelemetry.handleServer();
+		TangoSpan span = ctx.buildSpan("getResults", deviceName, attributeNames); // static Method ?
+		try (TangoScope scope = span.makeCurrent()) {
+			for (int i = 0; i < results.length; i++) {
+				span.startProcessing(attributeNames[i]);
+				// final AttributeResult result = it.next();
+				final String attributeName = attributeNames[i];
+				// final String attributeName = result.getName();
+				final AttrDataFormat format = attributeData.getFormat(attributeName);
+				// reset last error
+				attributeData.setAttributeResult(attributeName, null);
+				attributeData.resetAttributeResultError(attributeName);
+				if (results[i] != null) {
+					try {
+						final int type = results[i].getType();
+						if (format.equals(AttrDataFormat.SCALAR)) {
+							Object tmpReadValue = InsertExtractUtils.extractRead(results[i], AttrDataFormat.SCALAR);
+							if (tmpReadValue instanceof DevState) {
+								tmpReadValue = ((DevState) tmpReadValue).value();
+							}
+							attributeData.setAttributeResult(attributeName, tmpReadValue);
+						} else if (format.equals(AttrDataFormat.SPECTRUM)) {
+							if (type == TangoConst.Tango_DEV_STRING) {
+								throw DevFailedUtils.newDevFailed("TYPE_ERROR", "array of strings not supported");
+							} else if (type == TangoConst.Tango_DEV_BOOLEAN) {
+								throw DevFailedUtils.newDevFailed("TYPE_ERROR", "array of boolean not supported");
+							}
+							final Object tmpReadValue = InsertExtractUtils.extractRead(results[i], AttrDataFormat.SPECTRUM);
+							final MVector vect = new MVector(Array.getLength(tmpReadValue));
+							for (int j = 0; j < Array.getLength(tmpReadValue); j++) {
+								vect.setEle(j, Array.get(tmpReadValue, j));
+							}
+							attributeData.setAttributeResult(attributeName, vect);
+						} else {
+							if (format.equals(AttrDataFormat.FMT_UNKNOWN)) {
+								throw DevFailedUtils.newDevFailed("TYPE_ERROR", "Unknown format");
+							} else if (type == TangoConst.Tango_DEV_STRING) {
+								throw DevFailedUtils.newDevFailed("TYPE_ERROR", "images of strings not supported");
+							} else if (type == TangoConst.Tango_DEV_BOOLEAN) {
+								throw DevFailedUtils.newDevFailed("TYPE_ERROR", "images of boolean not supported");
+							}
+							final Object tmpReadValue = InsertExtractUtils.extractRead(results[i], AttrDataFormat.IMAGE);
+							int dim1 = Array.getLength(tmpReadValue);
+							int dim2 = 0;
+							if (dim1 > 0) {
+								Object subArray = Array.get(tmpReadValue, 0);
+								dim2 = Array.getLength(subArray);
+							}
+							Matrix matrix = (Matrix) Matrix.getInstance(dim1, dim2);
+							for (int j = 0; j < dim1; j++) {
+								Object subArray = Array.get(tmpReadValue, j);
+								for (int k = 0; k < dim2; k++) {
+									matrix.setEle(j, k, Array.get(subArray, k));
+								}
 							}
+							attributeData.setAttributeResult(attributeName, matrix);
 						}
-						attributeData.setAttributeResult(attributeName, matrix);
+					} catch (final DevFailed e) {
+						attributeData.setAttributeResultError(attributeName, e);
 					}
-				} catch (final DevFailed e) {
-					attributeData.setAttributeResultError(attributeName, e);
+				} else {
+					attributeData.setAttributeResultError(attributeName,
+							DevFailedUtils.newDevFailed("Device down for " + attributeName));
 				}
-			} else {
-				attributeData.setAttributeResultError(attributeName,
-						DevFailedUtils.newDevFailed("Device down for " + attributeName));
+				span.endProcessing(attributeNames[i]);
 			}
+		} catch (final Exception e) {
+			span.recordException(e);
+			throw DevFailedUtils.newDevFailed(e);
+		} finally {
+			span.end();
 		}
 	}
 
diff --git a/src/main/java/fr/soleil/tango/server/tangoparser/DynamicAttributeParser.java b/src/main/java/fr/soleil/tango/server/tangoparser/DynamicAttributeParser.java
index ad6ab8e..b82c50e 100755
--- a/src/main/java/fr/soleil/tango/server/tangoparser/DynamicAttributeParser.java
+++ b/src/main/java/fr/soleil/tango/server/tangoparser/DynamicAttributeParser.java
@@ -5,10 +5,12 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import fr.esrf.TangoApi.telemetry.*;
 import org.apache.commons.lang3.ArrayUtils;
 import org.nfunk.jep.ParseException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.tango.server.ServerManager;
 import org.tango.server.StateMachineBehavior;
 import org.tango.server.attribute.AttributeConfiguration;
 import org.tango.server.attribute.AttributePropertiesImpl;
@@ -48,6 +50,8 @@ public final class DynamicAttributeParser implements IWriteLockAttributeBehaviou
 	private boolean writingLock = false;
 	private Object writeValue;
 
+	private final OpenTelemetry openTelemetry;
+
 	public DynamicAttributeParser(final String deviceName, final AttributeConfiguration config,
 			final String expressionsR, final List<String> expressionsW, final BiMap<String, String> variables,
 			Map<String, ParserConstant> constants, List<TangoParserCustomFunction> functions,
@@ -69,6 +73,14 @@ public final class DynamicAttributeParser implements IWriteLockAttributeBehaviou
 		this.config = config;
 		final AttributePropertiesImpl attributeProperties = new AttributePropertiesImpl();
 
+		this.openTelemetry = new OpenTelemetry(deviceName);
+		this.openTelemetry.setTangoDeviceName(deviceName);
+		this.openTelemetry.setTangoProcessId(ServerManager.getInstance().getPid());
+		this.openTelemetry.setTangoHostName(ServerManager.getInstance().getHostName());
+		this.openTelemetry.setTangoServerName(ServerManager.getInstance().getServerName());
+		this.openTelemetry.setTangoProcessKind(EProcessKind.SERVER);
+		this.openTelemetry.init();
+
 		// config.setMemorized(true);
 		this.isSynchronous = sourceGroup.isSynchronous();
 		final AttrWriteType attrWryteType = config.getWritable();
@@ -154,10 +166,22 @@ public final class DynamicAttributeParser implements IWriteLockAttributeBehaviou
 
 	@Override
 	public AttributeValue getValue() throws DevFailed {
-		if (isSynchronous) {
-			launchRefresh(true);
+		TangoContext ctx = openTelemetry.handleServer();
+		TangoSpan span = ctx.buildSpan("getValue", dataSource.getDeviceName(), getConfiguration().getName()); // static Method ?
+		try (TangoScope scope = span.makeCurrent()) {
+			span.startProcessing(getConfiguration().getName());
+			if (isSynchronous) {
+				launchRefresh(true);
+			}
+			refreshValue(true);
+			span.endProcessing(getConfiguration().getName());
+		}
+		catch (final Exception e) {
+			span.recordException(e);
+		}
+		finally {
+			span.end();
 		}
-		refreshValue(true);
 		return value;
 	}
 
-- 
GitLab