use of io.opentracing.SpanContext in project hono by eclipse.
the class TracingSupportingHonoResourceTest method testHandleRequestExtractsParentTraceContext.
/**
* Verifies that the resource uses the SpanContext extracted from a CoAP request
* as the parent of the newly created Span.
*/
@Test
public void testHandleRequestExtractsParentTraceContext() {
final SpanContext extractedContext = mock(SpanContext.class);
when(tracer.extract(eq(Format.Builtin.BINARY), any(Binary.class))).thenReturn(extractedContext);
final Request request = new Request(Code.POST);
request.getOptions().addOption(new Option(CoapOptionInjectExtractAdapter.OPTION_TRACE_CONTEXT));
final Exchange exchange = newExchange(request);
resource.handleRequest(exchange);
verify(tracer).buildSpan(eq(Code.POST.toString()));
verify(spanBuilder).withTag(eq(Tags.SPAN_KIND.getKey()), eq(Tags.SPAN_KIND_SERVER.toString()));
verify(spanBuilder).addReference(eq(References.CHILD_OF), eq(extractedContext));
}
use of io.opentracing.SpanContext in project hono by eclipse.
the class ProtonBasedDeviceRegistrationClient method assertRegistration.
@Override
public Future<RegistrationAssertion> assertRegistration(final String tenantId, final String deviceId, final String gatewayId, final SpanContext context) {
Objects.requireNonNull(tenantId);
Objects.requireNonNull(deviceId);
final AnnotatedCacheKey<CacheKey> responseCacheKey = new AnnotatedCacheKey<>(new CacheKey(tenantId, deviceId, gatewayId));
final Span span = newChildSpan(context, "assert Device Registration");
TracingHelper.setDeviceTags(span, tenantId, deviceId);
TracingHelper.TAG_GATEWAY_ID.set(span, gatewayId);
return getResponseFromCache(responseCacheKey, span).recover(t -> getOrCreateClient(tenantId).compose(client -> {
final Map<String, Object> properties = createDeviceIdProperties(deviceId);
if (gatewayId != null) {
properties.put(MessageHelper.APP_PROPERTY_GATEWAY_ID, gatewayId);
}
return client.createAndSendRequest(RegistrationConstants.ACTION_ASSERT, properties, null, RegistrationConstants.CONTENT_TYPE_APPLICATION_JSON, this::getRequestResponseResult, span);
}).map(registrationResult -> {
addToCache(responseCacheKey, registrationResult);
return registrationResult;
})).recover(t -> {
Tags.HTTP_STATUS.set(span, ServiceInvocationException.extractStatusCode(t));
TracingHelper.logError(span, t);
return Future.failedFuture(t);
}).map(registrationResult -> {
Tags.HTTP_STATUS.set(span, registrationResult.getStatus());
if (registrationResult.isError()) {
Tags.ERROR.set(span, Boolean.TRUE);
}
switch(registrationResult.getStatus()) {
case HttpURLConnection.HTTP_OK:
final JsonObject payload = registrationResult.getPayload();
try {
return payload.mapTo(RegistrationAssertion.class);
} catch (final DecodeException e) {
if (log.isDebugEnabled()) {
log.debug("registration service returned invalid response:{}{}", System.lineSeparator(), payload.encodePrettily());
}
TracingHelper.logError(span, "registration service returned invalid response", e);
throw new ServerErrorException(HttpURLConnection.HTTP_INTERNAL_ERROR, "registration service returned invalid response");
}
case HttpURLConnection.HTTP_NOT_FOUND:
throw new ClientErrorException(registrationResult.getStatus(), "device unknown or disabled");
case HttpURLConnection.HTTP_FORBIDDEN:
throw new ClientErrorException(registrationResult.getStatus(), "gateway unknown, disabled or not authorized to act on behalf of device");
default:
throw StatusCodeMapper.from(registrationResult);
}
}).onComplete(o -> span.finish());
}
use of io.opentracing.SpanContext in project hono by eclipse.
the class ProtonBasedCredentialsClient method get.
@Override
public Future<CredentialsObject> get(final String tenantId, final String type, final String authId, final JsonObject clientContext, final SpanContext spanContext) {
Objects.requireNonNull(tenantId);
Objects.requireNonNull(type);
Objects.requireNonNull(authId);
Objects.requireNonNull(clientContext);
final int clientContextHashCode;
if (clientContext.isEmpty()) {
clientContextHashCode = clientContext.hashCode();
} else {
// "normalize" JSON so that binary valued properties always
// contain the value's Base64 encoding instead of the raw byte array
// and thus always result in the same hash code
clientContextHashCode = new JsonObject(clientContext.encode()).hashCode();
}
final AnnotatedCacheKey<CacheKey> responseCacheKey = new AnnotatedCacheKey<>(new CacheKey(tenantId, type, authId, clientContextHashCode));
final Span span = newChildSpan(spanContext, "get Credentials");
span.setTag(MessageHelper.APP_PROPERTY_TENANT_ID, tenantId);
span.setTag(TAG_CREDENTIALS_TYPE, type);
span.setTag(TAG_AUTH_ID, authId);
final Future<CredentialsResult<CredentialsObject>> resultTracker = getResponseFromCache(responseCacheKey, span).recover(cacheMiss -> getOrCreateClient(tenantId).compose(client -> {
final JsonObject specification = CredentialsConstants.getSearchCriteria(type, authId).mergeIn(clientContext);
if (LOG.isTraceEnabled()) {
LOG.trace("getting credentials using spec:{}{}", System.lineSeparator(), specification.encodePrettily());
}
return client.createAndSendRequest(CredentialsConstants.CredentialsAction.get.toString(), null, specification.toBuffer(), RequestResponseApiConstants.CONTENT_TYPE_APPLICATION_JSON, this::getRequestResponseResult, span);
}).map(credentialsResult -> {
addResultToCache(responseCacheKey, credentialsResult);
return credentialsResult;
}));
return mapResultAndFinishSpan(resultTracker, result -> {
switch(result.getStatus()) {
case HttpURLConnection.HTTP_OK:
case HttpURLConnection.HTTP_CREATED:
return result.getPayload();
case HttpURLConnection.HTTP_NOT_FOUND:
throw new ClientErrorException(result.getStatus(), "no such credentials");
default:
throw StatusCodeMapper.from(result);
}
}, span);
}
use of io.opentracing.SpanContext in project hono by eclipse.
the class MongoDbBasedCredentialsDao method update.
/**
* {@inheritDoc}
*/
@Override
public Future<String> update(final CredentialsDto credentials, final Optional<String> resourceVersion, final SpanContext tracingContext) {
Objects.requireNonNull(credentials);
Objects.requireNonNull(resourceVersion);
final Span span = tracer.buildSpan("update Credentials").addReference(References.CHILD_OF, tracingContext).withTag(TracingHelper.TAG_TENANT_ID, credentials.getTenantId()).withTag(TracingHelper.TAG_DEVICE_ID, credentials.getDeviceId()).start();
resourceVersion.ifPresent(v -> TracingHelper.TAG_RESOURCE_VERSION.set(span, v));
credentials.getCredentials().stream().forEach(cred -> cred.encryptFields(fieldLevelEncryption));
final JsonObject replaceCredentialsQuery = MongoDbDocumentBuilder.builder().withVersion(resourceVersion).withTenantId(credentials.getTenantId()).withDeviceId(credentials.getDeviceId()).document();
final var document = JsonObject.mapFrom(credentials);
if (LOG.isTraceEnabled()) {
LOG.trace("updating credentials of device [tenant: {}, device-id: {}, resource-version; {}]:{}{}", credentials.getTenantId(), credentials.getDeviceId(), resourceVersion.orElse(null), System.lineSeparator(), document.encodePrettily());
}
return mongoClient.findOneAndReplaceWithOptions(collectionName, replaceCredentialsQuery, document, new FindOptions(), new UpdateOptions().setReturningNewDocument(true)).compose(result -> {
if (result == null) {
return MongoDbBasedDao.checkForVersionMismatchAndFail(String.format("credentials [tenant-id: %s, device-id: %s]", credentials.getTenantId(), credentials.getDeviceId()), resourceVersion, getByDeviceId(credentials.getTenantId(), credentials.getDeviceId()));
} else {
LOG.debug("successfully updated credentials for device [tenant: {}, device-id: {}]", credentials.getTenantId(), credentials.getDeviceId());
span.log("successfully updated credentials");
if (LOG.isTraceEnabled()) {
LOG.trace("new document in DB:{}{}", System.lineSeparator(), result.encodePrettily());
}
return Future.succeededFuture(result.getString(CredentialsDto.FIELD_VERSION));
}
}).recover(error -> {
if (MongoDbBasedDao.isDuplicateKeyError(error)) {
return Future.failedFuture(new ClientErrorException(credentials.getTenantId(), HttpURLConnection.HTTP_CONFLICT, "credentials (type, auth-id) must be unique for device"));
} else {
return Future.failedFuture(error);
}
}).onFailure(error -> {
LOG.debug("error updating credentials", error);
TracingHelper.logError(span, "error updating credentials", error);
}).recover(this::mapError).onComplete(r -> span.finish());
}
use of io.opentracing.SpanContext in project hono by eclipse.
the class MongoDbBasedCredentialsDao method delete.
/**
* {@inheritDoc}
*/
@Override
public Future<Void> delete(final String tenantId, final String deviceId, final Optional<String> resourceVersion, final SpanContext tracingContext) {
Objects.requireNonNull(tenantId);
Objects.requireNonNull(deviceId);
Objects.requireNonNull(resourceVersion);
final Span span = tracer.buildSpan("delete Credentials").addReference(References.CHILD_OF, tracingContext).withTag(TracingHelper.TAG_TENANT_ID, tenantId).withTag(TracingHelper.TAG_DEVICE_ID, deviceId).start();
resourceVersion.ifPresent(v -> TracingHelper.TAG_RESOURCE_VERSION.set(span, v));
final JsonObject removeCredentialsQuery = MongoDbDocumentBuilder.builder().withVersion(resourceVersion).withTenantId(tenantId).withDeviceId(deviceId).document();
return mongoClient.findOneAndDelete(collectionName, removeCredentialsQuery).compose(result -> {
if (result == null) {
return MongoDbBasedDao.checkForVersionMismatchAndFail(String.format("credentials [tenant-id: %s, device-id: %s]", tenantId, deviceId), resourceVersion, getByDeviceId(tenantId, deviceId));
} else {
span.log("successfully deleted credentials");
LOG.debug("successfully deleted credentials for device [tenant: {}, device-id: {}]", tenantId, deviceId);
return Future.succeededFuture((Void) null);
}
}).onFailure(error -> {
LOG.debug("error deleting credentials", error);
TracingHelper.logError(span, "error deleting credentials", error);
}).recover(this::mapError).onComplete(r -> span.finish());
}
Aggregations