Search in sources :

Example 76 with SpanContext

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));
}
Also used : CoapExchange(org.eclipse.californium.core.server.resources.CoapExchange) Exchange(org.eclipse.californium.core.network.Exchange) SpanContext(io.opentracing.SpanContext) Request(org.eclipse.californium.core.coap.Request) Option(org.eclipse.californium.core.coap.Option) Binary(io.opentracing.propagation.Binary) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 77 with SpanContext

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());
}
Also used : HttpURLConnection(java.net.HttpURLConnection) CacheDirective(org.eclipse.hono.util.CacheDirective) LifecycleChange(org.eclipse.hono.notification.deviceregistry.LifecycleChange) DecodeException(io.vertx.core.json.DecodeException) DeviceChangeNotification(org.eclipse.hono.notification.deviceregistry.DeviceChangeNotification) LoggerFactory(org.slf4j.LoggerFactory) ClientErrorException(org.eclipse.hono.client.ClientErrorException) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) Cache(com.github.benmanes.caffeine.cache.Cache) Constants(org.eclipse.hono.util.Constants) Tags(io.opentracing.tag.Tags) StatusCodeMapper(org.eclipse.hono.client.StatusCodeMapper) DeviceRegistrationClient(org.eclipse.hono.client.registry.DeviceRegistrationClient) Map(java.util.Map) RegistrationResult(org.eclipse.hono.util.RegistrationResult) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) HonoConnection(org.eclipse.hono.client.HonoConnection) AbstractRequestResponseServiceClient(org.eclipse.hono.client.amqp.AbstractRequestResponseServiceClient) AllDevicesOfTenantDeletedNotification(org.eclipse.hono.notification.deviceregistry.AllDevicesOfTenantDeletedNotification) Logger(org.slf4j.Logger) RequestResponseClient(org.eclipse.hono.client.amqp.RequestResponseClient) CachingClientFactory(org.eclipse.hono.client.impl.CachingClientFactory) ServerErrorException(org.eclipse.hono.client.ServerErrorException) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) RegistrationConstants(org.eclipse.hono.util.RegistrationConstants) MessageHelper(org.eclipse.hono.util.MessageHelper) Future(io.vertx.core.Future) ApplicationProperties(org.apache.qpid.proton.amqp.messaging.ApplicationProperties) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) AnnotatedCacheKey(org.eclipse.hono.client.util.AnnotatedCacheKey) Buffer(io.vertx.core.buffer.Buffer) Span(io.opentracing.Span) SendMessageSampler(org.eclipse.hono.client.SendMessageSampler) NotificationEventBusSupport(org.eclipse.hono.notification.NotificationEventBusSupport) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) JsonObject(io.vertx.core.json.JsonObject) ClientErrorException(org.eclipse.hono.client.ClientErrorException) ServerErrorException(org.eclipse.hono.client.ServerErrorException) AnnotatedCacheKey(org.eclipse.hono.client.util.AnnotatedCacheKey) Span(io.opentracing.Span) Map(java.util.Map) DecodeException(io.vertx.core.json.DecodeException) AnnotatedCacheKey(org.eclipse.hono.client.util.AnnotatedCacheKey)

Example 78 with SpanContext

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);
}
Also used : HttpURLConnection(java.net.HttpURLConnection) CacheDirective(org.eclipse.hono.util.CacheDirective) LifecycleChange(org.eclipse.hono.notification.deviceregistry.LifecycleChange) Json(io.vertx.core.json.Json) DecodeException(io.vertx.core.json.DecodeException) DeviceChangeNotification(org.eclipse.hono.notification.deviceregistry.DeviceChangeNotification) LoggerFactory(org.slf4j.LoggerFactory) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Cache(com.github.benmanes.caffeine.cache.Cache) Constants(org.eclipse.hono.util.Constants) StatusCodeMapper(org.eclipse.hono.client.StatusCodeMapper) CredentialsClient(org.eclipse.hono.client.registry.CredentialsClient) JsonObject(io.vertx.core.json.JsonObject) HonoConnection(org.eclipse.hono.client.HonoConnection) AbstractRequestResponseServiceClient(org.eclipse.hono.client.amqp.AbstractRequestResponseServiceClient) AllDevicesOfTenantDeletedNotification(org.eclipse.hono.notification.deviceregistry.AllDevicesOfTenantDeletedNotification) CredentialsChangeNotification(org.eclipse.hono.notification.deviceregistry.CredentialsChangeNotification) Logger(org.slf4j.Logger) CredentialsResult(org.eclipse.hono.util.CredentialsResult) RequestResponseClient(org.eclipse.hono.client.amqp.RequestResponseClient) CachingClientFactory(org.eclipse.hono.client.impl.CachingClientFactory) MessageHelper(org.eclipse.hono.util.MessageHelper) RequestResponseApiConstants(org.eclipse.hono.util.RequestResponseApiConstants) Future(io.vertx.core.Future) CredentialsConstants(org.eclipse.hono.util.CredentialsConstants) ApplicationProperties(org.apache.qpid.proton.amqp.messaging.ApplicationProperties) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) AnnotatedCacheKey(org.eclipse.hono.client.util.AnnotatedCacheKey) Buffer(io.vertx.core.buffer.Buffer) Span(io.opentracing.Span) SendMessageSampler(org.eclipse.hono.client.SendMessageSampler) NotificationEventBusSupport(org.eclipse.hono.notification.NotificationEventBusSupport) CredentialsObject(org.eclipse.hono.util.CredentialsObject) JsonObject(io.vertx.core.json.JsonObject) CredentialsResult(org.eclipse.hono.util.CredentialsResult) ClientErrorException(org.eclipse.hono.client.ClientErrorException) AnnotatedCacheKey(org.eclipse.hono.client.util.AnnotatedCacheKey) Span(io.opentracing.Span) AnnotatedCacheKey(org.eclipse.hono.client.util.AnnotatedCacheKey)

Example 79 with SpanContext

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());
}
Also used : HttpURLConnection(java.net.HttpURLConnection) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Status(io.vertx.ext.healthchecks.Status) FieldLevelEncryption(org.eclipse.hono.deviceregistry.util.FieldLevelEncryption) HealthCheckHandler(io.vertx.ext.healthchecks.HealthCheckHandler) HealthCheckProvider(org.eclipse.hono.service.HealthCheckProvider) References(io.opentracing.References) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) RegistryManagementConstants(org.eclipse.hono.util.RegistryManagementConstants) Logger(org.slf4j.Logger) Tracer(io.opentracing.Tracer) Promise(io.vertx.core.Promise) MongoClient(io.vertx.ext.mongo.MongoClient) UUID(java.util.UUID) Future(io.vertx.core.Future) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) CredentialsDto(org.eclipse.hono.service.management.credentials.CredentialsDto) IndexOptions(io.vertx.ext.mongo.IndexOptions) Optional(java.util.Optional) Span(io.opentracing.Span) FindOptions(io.vertx.ext.mongo.FindOptions) UpdateOptions(io.vertx.ext.mongo.UpdateOptions) MongoDbDocumentBuilder(org.eclipse.hono.deviceregistry.mongodb.utils.MongoDbDocumentBuilder) FindOptions(io.vertx.ext.mongo.FindOptions) JsonObject(io.vertx.core.json.JsonObject) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Span(io.opentracing.Span) UpdateOptions(io.vertx.ext.mongo.UpdateOptions)

Example 80 with SpanContext

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());
}
Also used : HttpURLConnection(java.net.HttpURLConnection) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Status(io.vertx.ext.healthchecks.Status) FieldLevelEncryption(org.eclipse.hono.deviceregistry.util.FieldLevelEncryption) HealthCheckHandler(io.vertx.ext.healthchecks.HealthCheckHandler) HealthCheckProvider(org.eclipse.hono.service.HealthCheckProvider) References(io.opentracing.References) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) RegistryManagementConstants(org.eclipse.hono.util.RegistryManagementConstants) Logger(org.slf4j.Logger) Tracer(io.opentracing.Tracer) Promise(io.vertx.core.Promise) MongoClient(io.vertx.ext.mongo.MongoClient) UUID(java.util.UUID) Future(io.vertx.core.Future) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) CredentialsDto(org.eclipse.hono.service.management.credentials.CredentialsDto) IndexOptions(io.vertx.ext.mongo.IndexOptions) Optional(java.util.Optional) Span(io.opentracing.Span) FindOptions(io.vertx.ext.mongo.FindOptions) UpdateOptions(io.vertx.ext.mongo.UpdateOptions) MongoDbDocumentBuilder(org.eclipse.hono.deviceregistry.mongodb.utils.MongoDbDocumentBuilder) JsonObject(io.vertx.core.json.JsonObject) Span(io.opentracing.Span)

Aggregations

SpanContext (io.opentracing.SpanContext)118 Span (io.opentracing.Span)81 Future (io.vertx.core.Future)70 Tracer (io.opentracing.Tracer)60 Objects (java.util.Objects)57 HttpURLConnection (java.net.HttpURLConnection)56 JsonObject (io.vertx.core.json.JsonObject)55 TracingHelper (org.eclipse.hono.tracing.TracingHelper)55 Logger (org.slf4j.Logger)54 LoggerFactory (org.slf4j.LoggerFactory)54 List (java.util.List)51 Promise (io.vertx.core.Promise)45 Optional (java.util.Optional)45 Map (java.util.Map)40 ClientErrorException (org.eclipse.hono.client.ClientErrorException)39 MessageHelper (org.eclipse.hono.util.MessageHelper)33 UUID (java.util.UUID)31 Collectors (java.util.stream.Collectors)31 HashMap (java.util.HashMap)25 Vertx (io.vertx.core.Vertx)24