Search in sources :

Example 26 with SpanContext

use of io.opentracing.SpanContext in project hono by eclipse.

the class ProtonBasedRequestResponseCommandClient method sendCommand.

/**
 * Sends a command to a device and expects a response.
 * <p>
 * A device needs to be (successfully) registered before a client can upload
 * any data for it. The device also needs to be connected to a protocol adapter
 * and needs to have indicated its intent to receive commands.
 *
 * @param tenantId The tenant that the device belongs to.
 * @param deviceId The device to send the command to.
 * @param command The name of the command.
 * @param contentType The type of the data submitted as part of the command or {@code null} if unknown.
 * @param data The input data to the command or {@code null} if the command has no input data.
 * @param replyId An arbitrary string which gets used for the response link address in the form of
 *            <em>command_response/${tenantId}/${replyId}</em>. If it is {@code null} then an unique
 *                identifier generated using {@link UUID#randomUUID()} is used.
 * @param properties The headers to include in the command message as AMQP application properties.
 * @param timeout The duration after which the send command request times out. If the timeout is {@code null}
 *                then the default timeout value of {@value DEFAULT_COMMAND_TIMEOUT_IN_MS} ms is used.
 *                If the timeout duration is set to 0 then the send command request never times out.
 * @param context The currently active OpenTracing span context that is used to trace the execution of this
 *            operation or {@code null} if no span is currently active.
 * @return A future indicating the result of the operation.
 *         <p>
 *         The future will succeed if a response with status 2xx has been received from the device.
 *         If the response has no payload, the future will complete with a DownstreamMessage that has a {@code null} payload.
 *         <p>
 *         Otherwise, the future will fail with a {@link ServiceInvocationException} containing
 *         the (error) status code. Status codes are defined at
 *         <a href="https://www.eclipse.org/hono/docs/api/command-and-control">Command and Control API</a>.
 * @throws NullPointerException if any of tenantId, deviceId or command are {@code null}.
 * @throws IllegalArgumentException if the timeout duration value is &lt; 0
 */
public Future<DownstreamMessage<AmqpMessageContext>> sendCommand(final String tenantId, final String deviceId, final String command, final String contentType, final Buffer data, final String replyId, final Map<String, Object> properties, final Duration timeout, final SpanContext context) {
    Objects.requireNonNull(tenantId);
    Objects.requireNonNull(deviceId);
    Objects.requireNonNull(command);
    final long timeoutInMs = Optional.ofNullable(timeout).map(t -> {
        if (t.isNegative()) {
            throw new IllegalArgumentException("command timeout duration must be >= 0");
        }
        return t.toMillis();
    }).orElse(DEFAULT_COMMAND_TIMEOUT_IN_MS);
    final Span currentSpan = newChildSpan(context, "send command and receive response");
    return getOrCreateClient(tenantId, replyId).map(client -> {
        client.setRequestTimeout(timeoutInMs);
        return client;
    }).compose(client -> {
        final String messageTargetAddress = AddressHelper.getTargetAddress(CommandConstants.NORTHBOUND_COMMAND_REQUEST_ENDPOINT, tenantId, deviceId, connection.getConfig());
        return client.createAndSendRequest(command, messageTargetAddress, properties, data, contentType, this::mapCommandResponse, currentSpan);
    }).recover(error -> {
        Tags.HTTP_STATUS.set(currentSpan, ServiceInvocationException.extractStatusCode(error));
        TracingHelper.logError(currentSpan, error);
        return Future.failedFuture(error);
    }).compose(result -> {
        if (result == null) {
            return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST));
        } else {
            final DownstreamMessage<AmqpMessageContext> commandResponseMessage = result.getPayload();
            setTagsForResult(currentSpan, result);
            if (result.isError()) {
                final String detailMessage = commandResponseMessage.getPayload() != null && commandResponseMessage.getPayload().length() > 0 ? commandResponseMessage.getPayload().toString(StandardCharsets.UTF_8) : null;
                return Future.failedFuture(StatusCodeMapper.from(result.getStatus(), detailMessage));
            }
            return Future.succeededFuture(commandResponseMessage);
        }
    }).onComplete(r -> currentSpan.finish());
}
Also used : HttpURLConnection(java.net.HttpURLConnection) CacheDirective(org.eclipse.hono.util.CacheDirective) DownstreamMessage(org.eclipse.hono.application.client.DownstreamMessage) ProtonDelivery(io.vertx.proton.ProtonDelivery) LoggerFactory(org.slf4j.LoggerFactory) ClientErrorException(org.eclipse.hono.client.ClientErrorException) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) Tags(io.opentracing.tag.Tags) StatusCodeMapper(org.eclipse.hono.client.StatusCodeMapper) Duration(java.time.Duration) Map(java.util.Map) Message(org.apache.qpid.proton.message.Message) TracingHelper(org.eclipse.hono.tracing.TracingHelper) HonoConnection(org.eclipse.hono.client.HonoConnection) CommandConstants(org.eclipse.hono.util.CommandConstants) AbstractRequestResponseServiceClient(org.eclipse.hono.client.amqp.AbstractRequestResponseServiceClient) Logger(org.slf4j.Logger) RequestResponseResult(org.eclipse.hono.util.RequestResponseResult) RequestResponseClient(org.eclipse.hono.client.amqp.RequestResponseClient) CachingClientFactory(org.eclipse.hono.client.impl.CachingClientFactory) AddressHelper(org.eclipse.hono.util.AddressHelper) UUID(java.util.UUID) MessageHelper(org.eclipse.hono.util.MessageHelper) Future(io.vertx.core.Future) StandardCharsets(java.nio.charset.StandardCharsets) ApplicationProperties(org.apache.qpid.proton.amqp.messaging.ApplicationProperties) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) Buffer(io.vertx.core.buffer.Buffer) Optional(java.util.Optional) Span(io.opentracing.Span) SendMessageSampler(org.eclipse.hono.client.SendMessageSampler) DownstreamMessage(org.eclipse.hono.application.client.DownstreamMessage) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Span(io.opentracing.Span)

Example 27 with SpanContext

use of io.opentracing.SpanContext in project hono by eclipse.

the class ProtonBasedCommandResponseSender method sendCommandResponse.

@Override
public Future<Void> sendCommandResponse(final TenantObject tenant, final RegistrationAssertion device, final CommandResponse response, final SpanContext context) {
    Objects.requireNonNull(tenant);
    Objects.requireNonNull(device);
    Objects.requireNonNull(response);
    final var sender = createSender(response.getTenantId(), response.getReplyToId());
    return sender.recover(thr -> Future.failedFuture(StatusCodeMapper.toServerError(thr))).compose(s -> {
        final Message msg = createDownstreamMessage(response, tenant, device, response.getAdditionalProperties());
        final Span span = newChildSpan(context, "forward Command response");
        if (response.getMessagingType() != getMessagingType()) {
            span.log(String.format("using messaging type %s instead of type %s used for the original command", getMessagingType(), response.getMessagingType()));
        }
        return s.sendAndWaitForOutcome(msg, span);
    }).onSuccess(delivery -> sender.result().close()).mapEmpty();
}
Also used : AddressHelper(org.eclipse.hono.util.AddressHelper) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) ProtonHelper(io.vertx.proton.ProtonHelper) MessageHelper(org.eclipse.hono.util.MessageHelper) CommandResponseSender(org.eclipse.hono.client.command.CommandResponseSender) Future(io.vertx.core.Future) CommandResponse(org.eclipse.hono.client.command.CommandResponse) TenantObject(org.eclipse.hono.util.TenantObject) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) AbstractServiceClient(org.eclipse.hono.client.amqp.AbstractServiceClient) DownstreamAmqpMessageFactory(org.eclipse.hono.client.amqp.DownstreamAmqpMessageFactory) DownstreamMessageProperties(org.eclipse.hono.client.util.DownstreamMessageProperties) StatusCodeMapper(org.eclipse.hono.client.StatusCodeMapper) Map(java.util.Map) Span(io.opentracing.Span) Message(org.apache.qpid.proton.message.Message) SendMessageSampler(org.eclipse.hono.client.SendMessageSampler) HonoConnection(org.eclipse.hono.client.HonoConnection) GenericSenderLink(org.eclipse.hono.client.amqp.GenericSenderLink) CommandConstants(org.eclipse.hono.util.CommandConstants) Message(org.apache.qpid.proton.message.Message) Span(io.opentracing.Span)

Example 28 with SpanContext

use of io.opentracing.SpanContext in project hono by eclipse.

the class MongoDbBasedTenantDao method create.

/**
 * {@inheritDoc}
 */
@Override
public Future<String> create(final TenantDto tenantConfig, final SpanContext tracingContext) {
    Objects.requireNonNull(tenantConfig);
    final Span span = tracer.buildSpan("create Tenant").addReference(References.CHILD_OF, tracingContext).withTag(TracingHelper.TAG_TENANT_ID, tenantConfig.getTenantId()).start();
    final JsonObject newTenantDtoJson = JsonObject.mapFrom(tenantConfig);
    if (LOG.isTraceEnabled()) {
        LOG.trace("creating tenant:{}{}", System.lineSeparator(), newTenantDtoJson.encodePrettily());
    }
    return validateTrustAnchors(tenantConfig, span).compose(ok -> mongoClient.insert(collectionName, newTenantDtoJson)).map(tenantObjectIdResult -> {
        LOG.debug("successfully created tenant [tenant-id: {}, version: {}]", tenantConfig.getTenantId(), tenantConfig.getVersion());
        span.log("successfully created tenant");
        return tenantConfig.getVersion();
    }).recover(error -> {
        if (MongoDbBasedDao.isDuplicateKeyError(error)) {
            TracingHelper.logError(span, "tenant already exists");
            return Future.failedFuture(new ClientErrorException(tenantConfig.getTenantId(), HttpURLConnection.HTTP_CONFLICT, "tenant already exists"));
        } else {
            TracingHelper.logError(span, "error creating tenant", error);
            return mapError(error);
        }
    }).onComplete(r -> span.finish());
}
Also used : HttpURLConnection(java.net.HttpURLConnection) X500Principal(javax.security.auth.x500.X500Principal) Filter(org.eclipse.hono.service.management.Filter) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Constants(org.eclipse.hono.util.Constants) Tenant(org.eclipse.hono.service.management.tenant.Tenant) ArrayList(java.util.ArrayList) Status(io.vertx.ext.healthchecks.Status) Sort(org.eclipse.hono.service.management.Sort) HealthCheckHandler(io.vertx.ext.healthchecks.HealthCheckHandler) HealthCheckProvider(org.eclipse.hono.service.HealthCheckProvider) SearchResult(org.eclipse.hono.service.management.SearchResult) References(io.opentracing.References) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) TenantDto(org.eclipse.hono.service.management.tenant.TenantDto) RegistryManagementConstants(org.eclipse.hono.util.RegistryManagementConstants) Logger(org.slf4j.Logger) Tracer(io.opentracing.Tracer) Promise(io.vertx.core.Promise) TenantWithId(org.eclipse.hono.service.management.tenant.TenantWithId) MongoClient(io.vertx.ext.mongo.MongoClient) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) Future(io.vertx.core.Future) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) List(java.util.List) 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) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Span(io.opentracing.Span)

Example 29 with SpanContext

use of io.opentracing.SpanContext in project hono by eclipse.

the class MongoDbBasedTenantDao method getBySubjectDn.

/**
 * {@inheritDoc}
 */
@Override
public Future<TenantDto> getBySubjectDn(final X500Principal subjectDn, final SpanContext tracingContext) {
    Objects.requireNonNull(subjectDn);
    final String dn = subjectDn.getName(X500Principal.RFC2253);
    final Span span = tracer.buildSpan("get Tenant by subject DN").addReference(References.CHILD_OF, tracingContext).withTag(TracingHelper.TAG_SUBJECT_DN, dn).start();
    return mongoClient.findWithOptions(collectionName, MongoDbDocumentBuilder.builder().withCa(dn).document(), new FindOptions().setLimit(2)).map(matchingDocuments -> {
        if (matchingDocuments.size() == 0) {
            LOG.debug("could not find tenant with matching trust anchor [subject DN: {}]", dn);
            throw new ClientErrorException(HttpURLConnection.HTTP_NOT_FOUND, "no such tenant");
        } else if (matchingDocuments.size() == 1) {
            final JsonObject tenantJsonResult = matchingDocuments.get(0);
            return TenantDto.forRead(tenantJsonResult.getString(Constants.JSON_FIELD_TENANT_ID), tenantJsonResult.getJsonObject(TenantDto.FIELD_TENANT).mapTo(Tenant.class), tenantJsonResult.getInstant(TenantDto.FIELD_CREATED), tenantJsonResult.getInstant(TenantDto.FIELD_UPDATED_ON), tenantJsonResult.getString(TenantDto.FIELD_VERSION));
        } else {
            LOG.debug("found multiple tenants with matching trust anchor [subject DN: {}]", dn);
            throw new ClientErrorException(HttpURLConnection.HTTP_NOT_FOUND, "found multiple tenants with matching trust anchor");
        }
    }).onFailure(t -> TracingHelper.logError(span, "error retrieving tenant", t)).recover(this::mapError).onComplete(r -> span.finish());
}
Also used : HttpURLConnection(java.net.HttpURLConnection) X500Principal(javax.security.auth.x500.X500Principal) Filter(org.eclipse.hono.service.management.Filter) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Constants(org.eclipse.hono.util.Constants) Tenant(org.eclipse.hono.service.management.tenant.Tenant) ArrayList(java.util.ArrayList) Status(io.vertx.ext.healthchecks.Status) Sort(org.eclipse.hono.service.management.Sort) HealthCheckHandler(io.vertx.ext.healthchecks.HealthCheckHandler) HealthCheckProvider(org.eclipse.hono.service.HealthCheckProvider) SearchResult(org.eclipse.hono.service.management.SearchResult) References(io.opentracing.References) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) TenantDto(org.eclipse.hono.service.management.tenant.TenantDto) RegistryManagementConstants(org.eclipse.hono.util.RegistryManagementConstants) Logger(org.slf4j.Logger) Tracer(io.opentracing.Tracer) Promise(io.vertx.core.Promise) TenantWithId(org.eclipse.hono.service.management.tenant.TenantWithId) MongoClient(io.vertx.ext.mongo.MongoClient) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) Future(io.vertx.core.Future) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) List(java.util.List) 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) Tenant(org.eclipse.hono.service.management.tenant.Tenant) ClientErrorException(org.eclipse.hono.client.ClientErrorException) JsonObject(io.vertx.core.json.JsonObject) Span(io.opentracing.Span)

Example 30 with SpanContext

use of io.opentracing.SpanContext in project hono by eclipse.

the class MongoDbBasedTenantDao method update.

/**
 * {@inheritDoc}
 */
@Override
public Future<String> update(final TenantDto newTenantConfig, final Optional<String> resourceVersion, final SpanContext tracingContext) {
    Objects.requireNonNull(newTenantConfig);
    Objects.requireNonNull(resourceVersion);
    final Span span = tracer.buildSpan("update Tenant").addReference(References.CHILD_OF, tracingContext).withTag(TracingHelper.TAG_TENANT_ID, newTenantConfig.getTenantId()).start();
    resourceVersion.ifPresent(v -> TracingHelper.TAG_RESOURCE_VERSION.set(span, v));
    final JsonObject updateTenantQuery = MongoDbDocumentBuilder.builder().withVersion(resourceVersion).withTenantId(newTenantConfig.getTenantId()).document();
    return validateTrustAnchors(newTenantConfig, span).compose(ok -> mongoClient.findOneAndReplaceWithOptions(collectionName, updateTenantQuery, JsonObject.mapFrom(newTenantConfig), new FindOptions(), new UpdateOptions().setReturningNewDocument(true))).compose(updateResult -> {
        if (updateResult == null) {
            return MongoDbBasedDao.checkForVersionMismatchAndFail(newTenantConfig.getTenantId(), resourceVersion, getById(newTenantConfig.getTenantId(), false, span));
        } else {
            LOG.debug("successfully updated tenant [tenant-id: {}]", newTenantConfig.getTenantId());
            span.log("successfully updated tenant");
            return Future.succeededFuture(updateResult.getString(TenantDto.FIELD_VERSION));
        }
    }).recover(error -> {
        if (MongoDbBasedDao.isDuplicateKeyError(error)) {
            LOG.debug("failed to update tenant [{}], tenant alias already in use", newTenantConfig.getTenantId(), error);
            final var exception = new ClientErrorException(newTenantConfig.getTenantId(), HttpURLConnection.HTTP_CONFLICT, "tenant alias already in use");
            TracingHelper.logError(span, exception);
            return Future.failedFuture(exception);
        } else {
            TracingHelper.logError(span, "error updating tenant", error);
            return mapError(error);
        }
    }).onComplete(r -> span.finish());
}
Also used : HttpURLConnection(java.net.HttpURLConnection) X500Principal(javax.security.auth.x500.X500Principal) Filter(org.eclipse.hono.service.management.Filter) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Constants(org.eclipse.hono.util.Constants) Tenant(org.eclipse.hono.service.management.tenant.Tenant) ArrayList(java.util.ArrayList) Status(io.vertx.ext.healthchecks.Status) Sort(org.eclipse.hono.service.management.Sort) HealthCheckHandler(io.vertx.ext.healthchecks.HealthCheckHandler) HealthCheckProvider(org.eclipse.hono.service.HealthCheckProvider) SearchResult(org.eclipse.hono.service.management.SearchResult) References(io.opentracing.References) JsonObject(io.vertx.core.json.JsonObject) TracingHelper(org.eclipse.hono.tracing.TracingHelper) TenantDto(org.eclipse.hono.service.management.tenant.TenantDto) RegistryManagementConstants(org.eclipse.hono.util.RegistryManagementConstants) Logger(org.slf4j.Logger) Tracer(io.opentracing.Tracer) Promise(io.vertx.core.Promise) TenantWithId(org.eclipse.hono.service.management.tenant.TenantWithId) MongoClient(io.vertx.ext.mongo.MongoClient) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) Future(io.vertx.core.Future) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) List(java.util.List) 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)

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