001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.io.hfile.trace;
019
020import static org.apache.hadoop.hbase.trace.HBaseSemanticAttributes.CHECKSUM_KEY;
021import static org.apache.hadoop.hbase.trace.HBaseSemanticAttributes.COMPRESSION_ALGORITHM_KEY;
022import static org.apache.hadoop.hbase.trace.HBaseSemanticAttributes.DATA_BLOCK_ENCODING_KEY;
023import static org.apache.hadoop.hbase.trace.HBaseSemanticAttributes.ENCRYPTION_CIPHER_KEY;
024import static org.apache.hadoop.hbase.trace.HBaseSemanticAttributes.HFILE_NAME_KEY;
025import static org.apache.hadoop.hbase.trace.HBaseSemanticAttributes.READ_TYPE_KEY;
026
027import io.opentelemetry.api.common.AttributesBuilder;
028import io.opentelemetry.context.Context;
029import io.opentelemetry.context.ContextKey;
030import java.util.Objects;
031import java.util.function.Consumer;
032import org.apache.hadoop.hbase.io.hfile.HFileContext;
033import org.apache.hadoop.hbase.trace.HBaseSemanticAttributes.ReadType;
034import org.apache.hadoop.hbase.util.ChecksumType;
035import org.apache.yetus.audience.InterfaceAudience;
036
037/**
038 * <p>
039 * Populate fields on an {@link AttributesBuilder} based on an {@link HFileContext}. Passed around
040 * inside an active {@link Context}, indexed under {@link #CONTEXT_KEY}. The class is designed such
041 * that calls to the {@link #accept(AttributesBuilder)} method are idempotent with regards to the
042 * instance of this class.
043 * </p>
044 * <p>
045 * The true and truly ridiculous class name should be something more like
046 * {@code HFileContext_ContextAttributes_AttributesBuilder_Consumer}.
047 * </p>
048 */
049@InterfaceAudience.Private
050public class HFileContextAttributesBuilderConsumer implements Consumer<AttributesBuilder> {
051
052  /**
053   * Used to place extract attributes pertaining to the {@link HFileContext} that scopes the active
054   * {@link Context}.
055   */
056  public static final ContextKey<Consumer<AttributesBuilder>> CONTEXT_KEY =
057    ContextKey.named("db.hbase.io.hfile.context_attributes");
058
059  private final HFileContext hFileContext;
060
061  private boolean skipChecksum = false;
062  private ReadType readType = null;
063
064  public HFileContextAttributesBuilderConsumer(final HFileContext hFileContext) {
065    this.hFileContext = Objects.requireNonNull(hFileContext);
066  }
067
068  /**
069   * Specify that the {@link ChecksumType} should not be included in the attributes.
070   */
071  public HFileContextAttributesBuilderConsumer setSkipChecksum(final boolean skipChecksum) {
072    this.skipChecksum = skipChecksum;
073    return this;
074  }
075
076  /**
077   * Specify the {@link ReadType} involced in this IO operation.
078   */
079  public HFileContextAttributesBuilderConsumer setReadType(final ReadType readType) {
080    // TODO: this is not a part of the HFileBlock, its context of the operation. Should track this
081    // detail elsewhere.
082    this.readType = readType;
083    return this;
084  }
085
086  @Override
087  public void accept(AttributesBuilder builder) {
088    if (hFileContext.getHFileName() != null) {
089      builder.put(HFILE_NAME_KEY, hFileContext.getHFileName());
090    }
091    if (hFileContext.getCompression() != null) {
092      builder.put(COMPRESSION_ALGORITHM_KEY, hFileContext.getCompression().getName());
093    }
094    if (hFileContext.getDataBlockEncoding() != null) {
095      builder.put(DATA_BLOCK_ENCODING_KEY, hFileContext.getDataBlockEncoding().name());
096    }
097    if (
098      hFileContext.getEncryptionContext() != null
099        && hFileContext.getEncryptionContext().getCipher() != null
100    ) {
101      builder.put(ENCRYPTION_CIPHER_KEY, hFileContext.getEncryptionContext().getCipher().getName());
102    }
103    if (!skipChecksum && hFileContext.getChecksumType() != null) {
104      builder.put(CHECKSUM_KEY, hFileContext.getChecksumType().getName());
105    }
106    if (readType != null) {
107      builder.put(READ_TYPE_KEY, readType.name());
108    }
109  }
110}