Criar uma assinatura com SMTs

Neste documento, explicamos como criar uma assinatura do Pub/Sub com transformações de mensagem única (SMTs, na sigla em inglês).

Com as SMTs de assinatura, é possível fazer modificações leves nos dados e atributos das mensagens diretamente no Pub/Sub. Esse recurso permite a limpeza, filtragem ou conversão de formato de dados antes que as mensagens sejam entregues a um cliente assinante.

Para criar uma assinatura com SMTs, use o console Google Cloud , a Google Cloud CLI, a biblioteca de cliente ou a API Pub/Sub.

Antes de começar

Papéis e permissões necessárias

Para receber as permissões necessárias para criar uma assinatura com SMTs, peça ao administrador para conceder a você o papel do IAM de Editor do Pub/Sub (roles/pubsub.editor) no projeto. Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Esse papel predefinido contém as permissões necessárias para criar uma assinatura com SMTs. Para acessar as permissões exatas necessárias, expanda a seção Permissões necessárias:

Permissões necessárias

As seguintes permissões são necessárias para criar uma assinatura com SMTs:

  • Conceda a permissão para criar uma assinatura no projeto: pubsub.subscriptions.create

Essas permissões também podem ser concedidas com funções personalizadas ou outros papéis predefinidos.

Dependendo do tipo de assinatura, talvez sejam necessárias mais permissões. Para saber a lista exata de permissões, consulte o documento que discute a criação da assinatura específica. Por exemplo, se você estiver criando uma assinatura do BigQuery com SMTs, consulte a página Criar assinaturas do BigQuery.

Se você criar uma assinatura em um projeto diferente do tópico, será necessário conceder o papel roles/pubsub.subscriber ao principal do projeto que contém a assinatura no projeto que contém o tópico.

É possível configurar o controle de acesso no nível do projeto e no nível do recurso individual.

Criar uma assinatura com SMTs

Antes de criar uma assinatura com SMTs, consulte a documentação sobre Propriedades de uma assinatura.

Para criar uma assinatura do Pub/Sub com um ou mais SMTs, siga estas etapas.

Console

  1. No console Google Cloud , acesse a página Assinaturas do Pub/Sub.

    Acessar "Assinaturas"

  2. Clique em Criar assinatura.

    A página Criar assinatura é aberta.

  3. No campo ID da assinatura, insira um ID para a assinatura. Para mais informações sobre como nomear assinaturas, consulte as diretrizes de nomenclatura.

  4. Em Transformações, clique em Adicionar uma transformação.

  5. Insira um nome de função. Por exemplo, redactSSN.

  6. Se você não quiser que a SMT seja ativada imediatamente, selecione Desativar transformação. Quando essa opção é selecionada, o SMT é criado com a assinatura, mas não é executado em mensagens recebidas. Depois que a assinatura for criada, você poderá editar a assinatura para ativar o SMT.

  7. Na área de texto, insira o código da SMT. Exemplo:

    function redactSSN(message, metadata) {
      const data = JSON.parse(message.data);
      delete data['ssn'];
      message.data = JSON.stringify(data);
      return message;
    }
    
  8. Opcional. Para validar a SMT, clique em Validar. Se o SMT for válido, a mensagem "Validation passed" será exibida. Caso contrário, uma mensagem de erro será mostrada.

  9. Para adicionar outra transformação, clique em Adicionar uma transformação e repita as etapas anteriores.

    Para organizar os SMTs em uma ordem específica, clique em Mover para cima ou Mover para baixo. Para remover um SMT, clique em Excluir.

  10. Opcional. Para testar uma SMT em uma mensagem de amostra, siga estas etapas:

    1. Clique em Testar transformações.

    2. Na janela Transformação de teste, selecione a função que você quer testar.

    3. Na janela Mensagem de entrada, digite uma mensagem de exemplo.

    4. Para adicionar um atributo à mensagem, clique em Adicionar um atributo e insira a chave e o valor dele. É possível adicionar vários atributos.

    5. Clique em Testar. O resultado da aplicação da SMT na mensagem é mostrado em Mensagem de saída.

    6. Para fechar a janela Testar transformações, clique em Fechar.

    Se você criar mais de uma SMT, poderá testar toda a sequência de transformações da seguinte maneira:

    1. Teste o primeiro SMT na sequência, conforme descrito nas etapas anteriores.
    2. Selecione o próximo SMT. A mensagem de entrada é preenchida previamente com a mensagem de saída do teste anterior.
    3. Continue testando as SMTs em ordem para garantir que toda a sequência funcione conforme o esperado.
  11. Clique em Criar para criar a assinatura.

gcloud

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. Crie um arquivo YAML ou JSON que defina uma ou mais SMTs. Se você tiver mais de uma SMT, elas serão executadas nas mensagens na ordem em que forem listadas.

    Confira um exemplo de arquivo de transformação YAML:

    - javascriptUdf:
        code: >
            function redactSSN(message, metadata) {
              const data = JSON.parse(message.data);
              delete data['ssn'];
              message.data = JSON.stringify(data);
              return message;
            }
        functionName: redactSSN
    
  3. Opcional. Para validar uma SMT, execute o comando gcloud pubsub message-transforms validate:

    gcloud pubsub message-transforms validate \
      --message-transform-file=TRANSFORM_FILE
    

    Substitua:

    • TRANSFORM_FILE: o caminho para um arquivo YAML ou JSON que define um único SMT. Se você estiver criando várias SMTs, valide cada uma delas individualmente.
  4. Opcional. Para testar um ou mais SMTs em uma mensagem de amostra do Pub/Sub, execute o comando gcloud pubsub message-transforms test:

    gcloud pubsub message-transforms test \
      --message-transforms-file=TRANSFORMS_FILE \
      --message=MESSAGE \
      --attribute=ATTRIBUTES
    

    Substitua:

    • TRANSFORMS_FILE: o caminho para um arquivo YAML ou JSON que define um ou mais SMTs.
    • MESSAGE: o corpo da mensagem de exemplo.
    • ATTRIBUTES: opcional. Uma lista separada por vírgulas de atributos de mensagem. Cada atributo é um par de chave-valor formatado como KEY="VALUE".

    O comando executa as SMTs em ordem, usando a saída de cada uma como a entrada para a próxima. O comando gera os resultados de cada etapa.

  5. Para criar a assinatura, execute o comando gcloud pubsub subscriptions create:

    gcloud pubsub subscriptions create SUBSCRIPTION_ID \
        --topic=projects/PROJECT_ID/topics/TOPIC_ID \
        --message-transforms-file=TRANSFORMS_FILE
    

    Substitua:

    • SUBSCRIPTION_ID: o ID ou nome da assinatura que você quer criar. Para diretrizes sobre como nomear uma assinatura, consulte Nomes de recursos. O nome de uma assinatura é imutável.

    • PROJECT_ID: o ID do projeto que contém o tópico.

    • TOPIC_ID: o ID do tópico a ser assinado.

    • TRANSFORMS_FILE: o caminho para o arquivo YAML ou JSON que define um ou mais SMTs.

  6. Java

    Antes de tentar essa amostra, siga as instruções de configuração do Java em Guia de início rápido: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Pub/Sub Java.

    import com.google.cloud.pubsub.v1.SubscriptionAdminClient;
    import com.google.pubsub.v1.JavaScriptUDF;
    import com.google.pubsub.v1.MessageTransform;
    import com.google.pubsub.v1.ProjectSubscriptionName;
    import com.google.pubsub.v1.ProjectTopicName;
    import com.google.pubsub.v1.Subscription;
    import java.io.IOException;
    
    public class CreateSubscriptionWithSmtExample {
      public static void main(String... args) throws Exception {
        // TODO(developer): Replace these variables before running the sample.
        String projectId = "your-project-id";
        String topicId = "your-topic-id";
        String subscriptionId = "your-subscription-id";
    
        createSubscriptionWithSmtExample(projectId, topicId, subscriptionId);
      }
    
      public static void createSubscriptionWithSmtExample(
          String projectId, String topicId, String subscriptionId) throws IOException {
    
        // UDF that removes the 'ssn' field, if present
        String code =
            "function redactSSN(message, metadata) {"
                + "  const data = JSON.parse(message.data);"
                + "  delete data['ssn'];"
                + "  message.data = JSON.stringify(data);"
                + "  return message;"
                + "}";
        String functionName = "redactSSN";
    
        JavaScriptUDF udf =
            JavaScriptUDF.newBuilder().setCode(code).setFunctionName(functionName).build();
        MessageTransform transform = MessageTransform.newBuilder().setJavascriptUdf(udf).build();
    
        try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
    
          ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);
          ProjectSubscriptionName subscriptionName =
              ProjectSubscriptionName.of(projectId, subscriptionId);
    
          Subscription subscription =
              subscriptionAdminClient.createSubscription(
                  Subscription.newBuilder()
                      .setName(subscriptionName.toString())
                      .setTopic(topicName.toString())
                      // Add the UDF message transform
                      .addMessageTransforms(transform)
                      .build());
    
          System.out.println("Created subscription with SMT: " + subscription.getAllFields());
        }
      }
    }

    Python

    Antes de tentar esse exemplo, siga as instruções de configuração do Python em Guia de início rápido: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Pub/Sub Python.

    from google.cloud import pubsub_v1
    from google.pubsub_v1.types import JavaScriptUDF, MessageTransform
    
    # TODO(developer): Choose an existing topic.
    # project_id = "your-project-id"
    # topic_id = "your-topic-id"
    # subscription_id = "your-subscription-id"
    
    publisher = pubsub_v1.PublisherClient()
    subscriber = pubsub_v1.SubscriberClient()
    topic_path = publisher.topic_path(project_id, topic_id)
    subscription_path = subscriber.subscription_path(project_id, subscription_id)
    
    code = """function redactSSN(message, metadata) {
                const data = JSON.parse(message.data);
                delete data['ssn'];
                message.data = JSON.stringify(data);
                return message;
                }"""
    udf = JavaScriptUDF(code=code, function_name="redactSSN")
    transforms = [MessageTransform(javascript_udf=udf)]
    
    with subscriber:
        subscription = subscriber.create_subscription(
            request={
                "name": subscription_path,
                "topic": topic_path,
                "message_transforms": transforms,
            }
        )
        print(f"Created subscription with SMT: {subscription}")

    Go

    O exemplo a seguir usa a versão principal da biblioteca de cliente do Go Pub/Sub (v2). Se você ainda estiver usando a biblioteca v1, consulte o guia de migração para a v2. Para conferir uma lista de exemplos de código da v1, consulte os exemplos de código descontinuados.

    Antes de tentar esse exemplo, siga as instruções de configuração do Go em Guia de início rápido: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Pub/Sub Go.

    import (
    	"context"
    	"fmt"
    	"io"
    
    	"cloud.google.com/go/pubsub/v2"
    	"cloud.google.com/go/pubsub/v2/apiv1/pubsubpb"
    )
    
    // createSubscriptionWithSMT creates a subscription with a single message transform function applied.
    func createSubscriptionWithSMT(w io.Writer, projectID, topicID, subID string) error {
    	// projectID := "my-project-id"
    	// topicID := "my-topic"
    	// subID := "my-sub"
    	ctx := context.Background()
    	client, err := pubsub.NewClient(ctx, projectID)
    	if err != nil {
    		return fmt.Errorf("pubsub.NewClient: %w", err)
    	}
    	defer client.Close()
    
    	code := `function redactSSN(message, metadata) {
    			const data = JSON.parse(message.data);
    			delete data['ssn'];
    			message.data = JSON.stringify(data);
    			return message;
    		}`
    
    	transform := &pubsubpb.MessageTransform{
    		Transform: &pubsubpb.MessageTransform_JavascriptUdf{
    			JavascriptUdf: &pubsubpb.JavaScriptUDF{
    				FunctionName: "redactSSN",
    				Code:         code,
    			},
    		},
    	}
    
    	sub := &pubsubpb.Subscription{
    		Name:              fmt.Sprintf("projects/%s/subscriptions/%s", projectID, subID),
    		Topic:             fmt.Sprintf("projects/%s/topics/%s", projectID, topicID),
    		MessageTransforms: []*pubsubpb.MessageTransform{transform},
    	}
    	sub, err = client.SubscriptionAdminClient.CreateSubscription(ctx, sub)
    	if err != nil {
    		return fmt.Errorf("CreateSubscription: %w", err)
    	}
    	fmt.Fprintf(w, "Created subscription with message transform: %v\n", sub)
    	return nil
    }
    

Como as SMTs interagem com outros recursos de assinatura

Se a assinatura usar SMTs e filtros integrados do Pub/Sub, o filtro será aplicado antes da SMT. Isso tem as seguintes implicações:

  • Se o SMT alterar os atributos da mensagem, o filtro do Pub/Sub não será aplicado ao novo conjunto de atributos.
  • Sua SMT não será aplicada a mensagens filtradas pelo filtro do Pub/Sub.

Se o SMT filtrar mensagens, fique atento ao impacto no monitoramento do backlog de assinaturas. Se você alimentar a assinatura em um pipeline do Dataflow, não filtre as mensagens usando o SMT, porque isso interrompe o escalonamento automático do Dataflow.

A seguir