"logging.config" --- Logging configuration
******************************************

**Código-fonte:** Lib/logging/config.py


Important
^^^^^^^^^

Esta página contém apenas informações de referência. Para tutoriais,
por favor consulte

* Tutorial básico

* Tutorial avançado

* Livro de receitas de logging

======================================================================

Esta seção descreve a API para configuração do módulo logging.


Funções de configuração
=======================

Os seguintes função configuram o módulo  logging. Elas estão
localizadas no módulo "logging.config". Seu uso é opcional --- você
pode configurar o módulo logging usando essas funções ou fazendo
chamadas para o API principal (definido no próprio "logging") e
definindo manipuladores que são declarados em "logging" ou
"logging.handlers".

logging.config.dictConfig(config)

   Obtém a configuração de logging de um dicionário. Os conteúdos
   desse dicionário estão descritos abaixo em Esquema do Dicionário de
   Configuração.

   Se um erro for encontrado durante a configuração, esta função
   levantará uma exceção "ValueError", "TypeError", "AttributeError"
   ou "ImportError" com uma mensagem adequadamente descritiva.  A
   seguir está uma lista (possivelmente incompleta) de condições que
   levantarão um erro:

   * Um "level" que não seja uma string ou que seja uma string que não
     corresponda a um nível de logging atual

   * Um valor "propagate" que não seja um booleano.

   * Um id que não tenha um destino correspondente.

   * Um id de manipulador inexistente encontrado durante uma chamada
     incremental.

   * Um nome de logger inválido.

   * Incapacidade de resolver para um objeto interno ou externo.

   A análise é realizada pela classe "DictConfigurator", cujo
   construtor recebe o dicionário usado para a configuração e possui
   um método "configure()". O módulo "logging.config" tem um atributo
   chamável "dictConfigClass" que é inicialmente definido como
   "DictConfigurator". Você pode substituir o valor de
   "dictConfigClass" por uma implementação adequada de sua autoria.

   A função "dictConfig()" chama "dictConfigClass" passando o
   dicionário especificado e, em seguida, chama o método "configure()"
   no objeto devolvido para colocar a configuração em efeito:

      def dictConfig(config):
          dictConfigClass(config).configure()

   For example, a subclass of "DictConfigurator" could call
   "DictConfigurator.__init__()" in its own "__init__()", then set up
   custom prefixes which would be usable in the subsequent
   "configure()" call. "dictConfigClass" would be bound to this new
   subclass, and then "dictConfig()" could be called exactly as in the
   default, uncustomized state.

   Novo na versão 3.2.

logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True, encoding=None)

   Lê a configuração de logging de um arquivo no formato
   "configparser". O formato do arquivo deve ser como descrito em
   Formato do arquivo de configuração. Esta função pode ser chamada
   várias vezes a partir de uma aplicação, permitindo que um usuário
   final selecione entre várias configurações pré-prontas (se o
   desenvolvedor fornecer um mecanismo para apresentar as escolhas e
   carregar a configuração escolhida).

   Parâmetros:
      * **fname** -- A filename, or a file-like object, or an instance
        derived from "RawConfigParser". If a "RawConfigParser"-derived
        instance is passed, it is used as is. Otherwise, a
        "Configparser" is instantiated, and the configuration read by
        it from the object passed in "fname". If that has a
        "readline()" method, it is assumed to be a file-like object
        and read using "read_file()"; otherwise, it is assumed to be a
        filename and passed to "read()".

      * **defaults** -- Defaults to be passed to the ConfigParser can
        be specified in this argument.

      * **disable_existing_loggers** --

        If specified as "False", loggers which
           exist when this call is made are left enabled. The default
           is "True" because this enables old behaviour in a backward-
           compatible way. This behaviour is to disable any existing
           non-root loggers unless they or their ancestors are
           explicitly named in the logging configuration.

        param encoding:
           A codificação usada para abrir o arquivo quando fname é um
           nome de arquivo.

   Alterado na versão 3.4: Uma instância de uma subclasse de
   "RawConfigParser" agora é aceita como um valor para "fname". Isso
   facilita:

      * Uso de um arquivo de configuração onde a configuração de
        logging é apenas parte da configuração geral da aplicação.

      * Uso de uma configuração lida de um arquivo, e então modificada
        pela aplicação que a usa (por exemplo, baseada em parâmetros
        de linha de comando ou outros aspectos do ambiente de tempo de
        execução) antes de ser passada para "fileConfig".

   Novo na versão 3.10: The *encoding* parameter is added.

logging.config.listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None)

   Inicia um servidor soquete na porta especificada e escuta por novas
   configurações. Se nenhuma porta for especificada, o padrão do
   módulo "DEFAULT_LOGGING_CONFIG_PORT" é usado. As configurações de
   logging serão enviadas como um arquivo adequado para processamento
   por "dictConfig()" ou por "fileConfig()". Retorna uma instância de
   "Thread" na qual você pode chamar "start()" para iniciar o
   servidor, e à qual você pode "join()" quando apropriado. Para
   interromper o servidor, chame "stopListening()".

   O argumento "verify", se especificado, deve ser um chamável que
   verifique se os bytes recebidos através do soquete são válidos e
   devem ser processados. Isso pode ser feito criptografando e/ou
   assinando o que é enviado através do soquete, de modo que o
   chamável "verify" possa realizar a verificação de assinatura e/ou a
   descriptografia. O chamável "verify" é chamado com um único
   argumento – os bytes recebidos através do soquete – e deve retornar
   os bytes a serem processados, ou "None" para indicar que os bytes
   devem ser descartados. Os bytes devolvidos podem ser os mesmos que
   os bytes passados (por exemplo, quando apenas a verificação é
   feita), ou podem ser completamente diferentes (talvez se a
   descriptografia for realizada).

   Para enviar uma configuração para o soquete, leia o arquivo de
   configuração e o envie para o soquete como uma sequência de bytes
   precedida por uma string de comprimento de quatro bytes empacotada
   em binário usando "struct.pack('>L', n)".

   Nota:

     Como partes da configuração são passadas por "eval()", o uso
     dessa função pode expor seus usuários a um risco de segurança.
     Embora a função apenas se vincule a um soquete em "localhost" e,
     portanto, não aceite conexões de máquinas remotas, existem
     cenários em que código não confiável pode ser executado sob a
     conta do processo que chama "listen()". Especificamente, se o
     processo que chama "listen()" estiver sendo executado em uma
     máquina multiusuário onde os usuários não confiam uns nos outros,
     um usuário malicioso pode conseguir executar essencialmente
     código arbitrário no processo de um usuário vítima, simplesmente
     conectando-se ao soquete "listen()" da vítima e enviando uma
     configuração que execute qualquer código que o atacante queira
     que seja executado no processo da vítima. Isso é especialmente
     fácil de fazer se a porta padrão for usada, mas não é difícil
     mesmo se uma porta diferente for utilizada. Para evitar o risco
     de isso acontecer, use o argumento "verify" de "listen()" para
     prevenir que configurações não reconhecidas sejam aplicadas.

   Alterado na versão 3.4: O argumento "verify" foi adicionado.

   Nota:

     Se você deseja enviar configurações para o listener que não
     desabilitem os loggers existentes, você precisará usar um formato
     JSON para a configuração, que usará "dictConfig()" para
     configuração. Este método permite que você especifique
     "disable_existing_loggers" como "False" na configuração que você
     envia.

logging.config.stopListening()

   Interrompe o servidor de escuta que foi criado com uma chamada para
   "listen()". Essa função é tipicamente chamada antes de chamar
   "join()" no valor de retorno de "listen()".


Considerações de segurança
==========================

A funcionalidade de configuração de logging tenta oferecer
conveniência, e em parte isso é feito ao oferecer a capacidade de
converter texto presente em arquivos de configuração em objetos Python
usados na configuração de logging — por exemplo, conforme descrito em
Objetos definidos pelo usuário. No entanto, esses mesmos mecanismos
(importar chamáveis de módulos definidos pelo usuário e chamá-los com
parâmetros da configuração) poderiam ser usados para invocar qualquer
código que você desejar, e por essa razão você deve tratar arquivos de
configuração de fontes não confiáveis com extrema cautela e
certificar-se de que nada de ruim pode acontecer se você carregá-los,
antes de realmente carregá-los.


Esquema do Dicionário de Configuração
=====================================

Descrever uma configuração de logging requer listar os vários objetos
a serem criados e as conexões entre eles; por exemplo, você pode criar
um manipulador nomeado 'console' e, em seguida, dizer que o logger
nomeado 'startup' enviará suas mensagens para o manipulador 'console'.
Estes objetos não se limitam àqueles fornecidos pelo módulo "logging",
pois você pode escrever sua própria classe de formatador ou de
manipulador. Os parâmetros para essas classes também podem precisar
incluir objetos externos, como "sys.stderr".  A sintaxe para descrever
esses objetos e conexões é definida abaixo em Conexões de objeto.


Detalhes do Esquema de Dicionário
---------------------------------

O dicionário passado para "dictConfig()" deve conter as chaves a
seguir:

* version - deve ser definido como um valor inteiro representando a
  versão do esquema. O único valor válido atualmente é 1, mas ter esta
  chave permite que o esquema evolua, preservando ainda a
  retrocompatibilidade.

Todas as outras chaves são opcionais, mas se estiverem presentes,
serão interpretadas conforme descrito abaixo. Em todos os casos abaixo
onde um 'dicionário de configuração' é mencionado, ele será verificado
quanto à chave especial "'()'" para consultar se uma instanciação
personalizada é necessária. Se for o caso, o mecanismo descrito em
Objetos definidos pelo usuário abaixo é usado para criar uma
instância; caso contrário, o contexto é usado para determinar o que
instanciar.

* formatters - o valor correspondente será um dicionário em que cada
  chave é um id de formatador e cada valor é um dicionário que
  descreve como configurar a instância correspondente de "Formatter".

  O dicionário de configuração é buscado pelas chaves opcionais a
  seguir que correspondem aos argumentos passados para criar um objeto
  "Formatter":

     * "format"

     * "datefmt"

     * "style"

     * "validate" (desde a versão >=3.8)

  Uma chave opcional "class" indica o nome da classe do formatador
  (como um módulo pontilhado e nome da classe).  Os argumentos de
  instanciação são os mesmos que para "Formatter" portanto, esta chave
  é mais útil para instanciar uma subclasse personalizada de
  :"Formatter".  Por exemplo, a classe alternativa pode apresentar
  tracebacks de exceção em um formato expandido ou condensado. Se o
  seu formatter exigir chaves de configuração diferentes ou extras,
  você deve usar Objetos definidos pelo usuário.

* filters - o valor correspondente será um dicionário no qual cada
  chave é um id de filter e cada valor é um dicionário que descreve
  como configurar a instância Filter correspondente.

  O dicionário de configuração é pesquisado pela chave "name" (que
  assume como padrão a string vazia) e esta é usada para construir uma
  instância de "logging.Filter".

* handlers - o valor correspondente será um dicionário no qual cada
  chave é um id de manipulador e cada valor é um dicionário que
  descreve como configurar a instância de Manipulador correspondente.

  O dicionário de configuração é pesquisado para as chaves a seguir:

  * "class" (obrigatório). Esse é o nome qualificado completo da
    classe do handler.

  * "level" (opcional).  O nível do manipulador.

  * "formatter" (opcional).  O id do formatador para esse manipulador.

  * "filters" (opcional).  Uma lista de ids dos filtros para esse
    manipulador.

  Todas as *outras* chaves são transmitidas como argumento nomeado
  para o construtor do manipulador.  Por exemplo, dado o trecho:

     handlers:
       console:
         class : logging.StreamHandler
         formatter: brief
         level   : INFO
         filters: [allow_foo]
         stream  : ext://sys.stdout
       file:
         class : logging.handlers.RotatingFileHandler
         formatter: precise
         filename: logconfig.log
         maxBytes: 1024
         backupCount: 3

  o manipulador com o id "console" é instanciado como um
  "logging.StreamHandler", usando "sys.stdout" como o fluxo
  subjacente. O manipulador com o id "file" é instanciado como um
  "logging.handlers.RotatingFileHandler" com os argumentos nomeados
  "filename='logconfig.log', maxBytes=1024, backupCount=3".

* *loggers*  -  o valor correspondente será um dicionário no qual cada
  chave é o nome de um registradores e cada valor é um dicionário que
  descreve como configurar a instância de Registrador correspondente.

  O dicionário de configuração é pesquisado para as chaves a seguir:

  * "level" (opcional).  O nível do logger.

  * "propagate" (opcional).  A configuração de propagação do logger.

  * "filters" (opcional).  Uma lista de ids dos filtros para esse
    logger.

  * "handlers" (opcional).  Uma lista de ids dos manipuladores para
    esse logger.

  Os loggers especificados serão configurados de acordo com o nível, a
  propagação, os filtros e os manipuladores especificados.

* *root* - essa será a configuração para o logger raiz. O
  processamento da configuração será igual ao de qualquer logger,
  exceto pelo fato de que a configuração "propagate" não será
  aplicável.

* *incremental* - se a configuração deve ser interpretada como
  incremental à configuração existente.  O padrão deste valor é
  "False", o que significa que a configuração especificada substitui a
  configuração existente com a mesma semântica usada pela configuração
  da API existente "fileConfig()".

  Se o valor especificado for "True", a configuração será processada
  conforme descrito na seção Configuração Incremental.

* *disable_existing_loggers* - se quaisquer loggers não raiz
  existentes devem ser desabilitados. Essa configuração reflete o
  parâmetro de mesmo nome em "fileConfig()". Se ausente, o padrão
  deste parâmetro é "True". Este valor é ignorado se *incremental* for
  "True".


Configuração Incremental
------------------------

É difícil oferecer total flexibilidade para a configuração
incremental.  Por exemplo, como objetos, assim como filtros e
formatadores, são anônimos, depois que uma configuração é definida,
não é possível fazer referência a esse objeto anônimo ao ampliar uma
configuração.

Além disso, não há um argumento convincente para alterar
arbitrariamente o grafo de objetos de loggers, manipuladores, filtros
e formatadores em tempo de execução, depois que uma configuração é
definida; a verbosidade de loggers e manipuladores pode ser controlada
simplesmente ajustando os níveis (e, no caso de loggers, os
sinalizadores de propagação). Alterar o grafo de objetos
arbitrariamente de forma segura é problemático em um ambiente
multithread; embora não seja impossível, os benefícios não compensam a
complexidade que isso acrescentaria à implementação.

Assim, quando a chave "incremental" de um dicionário de configuração
estiver presente e for "True", o sistema ignorará completamente
quaisquer entradas "formatters" e "filters", e processará apenas as
configurações de "level" nas entradas "handlers", e as configurações
de "level" e "propagate" nas entradas "loggers" e "root".

Usar um valor no dicionário de configuração permite que configurações
sejam enviadas pela rede como dicionários pickled para um listener
soquete. Assim, a verbosidade de logging de uma aplicação de longa
execução pode ser alterada ao longo do tempo sem a necessidade de
parar e reiniciar a aplicação.


Conexões de objeto
------------------

O esquema descreve um conjunto de objetos de logging — loggers,
manipuladores, formatadores, filtros — que são conectados uns aos
outros em um grafo de objetos. Assim, o esquema precisa representar
conexões entre os objetos. Por exemplo, suponha que, após configurado,
um determinado logger tenha anexado a si um determinado manipulador.
Para os propósitos desta discussão, podemos dizer que o logger
representa a origem e o manipulador representa o destino de uma
conexão entre os dois. É claro que, nos objetos configurados, isso é
representado pelo logger mantendo uma referência ao manipulador. No
dicionário de configuração, isso é feito atribuindo a cada objeto de
destino um id que o identifica de forma inequívoca e, em seguida,
usando esse id na configuração do objeto de origem para indicar que
existe uma conexão entre o objeto de origem e o objeto de destino com
aquele id.

Então, por exemplo, considere o seguinte trecho de YAML:

   formatters:
     brief:
       # configuration for formatter with id 'brief' goes here
     precise:
       # configuration for formatter with id 'precise' goes here
   handlers:
     h1: #This is an id
      # configuration of handler with id 'h1' goes here
      formatter: brief
     h2: #This is another id
      # configuration of handler with id 'h2' goes here
      formatter: precise
   loggers:
     foo.bar.baz:
       # other configuration for logger 'foo.bar.baz'
       handlers: [h1, h2]

(Observação: o YAML é usado aqui porque é um pouco mais legível do que
o formulário de origem Python equivalente para o dicionário.)

Os ids para loggers são os nomes dos loggers que seriam usados
programaticamente para obter uma referência a esses loggers, por
exemplo, "foo.bar.baz". Os ids para Formatadores e Filtros podem ser
qualquer valor de string (como "brief", "precise" acima) e são
transitórios, no sentido de que só têm significado durante o
processamento do dicionário de configuração e são usados para
determinar conexões entre objetos, não sendo persistidos em nenhum
lugar após a conclusão da chamada de configuração.

O trecho acima indica que o logger nomeado "foo.bar.baz" deve ter dois
manipuladores anexados a ele, que são descritos pelos IDs de
manipulador "h1" e "h2". O formatador para "h1" é o descrito pelo id
"brief", e o formatador para "h2" é o descrito pelo id "precise".


Objetos definidos pelo usuário
------------------------------

O esquema oferece suporte a objetos definidos pelo usuário para
manipuladores, filtros e formatadores.  (Os loggers não precisam ter
tipos diferentes para instâncias diferentes, portanto este esquema de
configuração não provê suporte às classes de loggers definidas pelo
usuário.)

Objetos a serem configurados são descritos por dicionários que
detalham sua configuração. Em alguns casos, o sistema de logging
consegue inferir pelo contexto como um objeto deve ser instanciado,
mas, quando se trata de um objeto definido pelo usuário, o sistema não
saberá como fazer isso. Para oferecer total flexibilidade na
instanciação desses objetos definidos pelo usuário, é necessário
fornecer uma factory — um chamável que recebe um dicionário de
configuração e retorna o objeto instanciado. Isso é sinalizado por um
caminho de importação absoluto para a factory, disponibilizado sob a
chave especial "'()'". Aqui está um exemplo concreto:

   formatters:
     brief:
       format: '%(message)s'
     default:
       format: '%(asctime)s %(levelname)-8s %(name)-15s %(message)s'
       datefmt: '%Y-%m-%d %H:%M:%S'
     custom:
         (): my.package.customFormatterFactory
         bar: baz
         spam: 99.9
         answer: 42

O trecho YAML acima define três formatadores. O primeiro, com id
"brief", é uma instância padrão de "logging.Formatter" com a string de
formato especificado. O segundo, com id "default", tem um formato mais
longo e também define explicitamente o formato de tempo, e resultará
em um "logging.Formatter" inicializado com essas duas strings de
formatação. Em código-fonte Python, os formatadores "brief" e
"default" têm subdicionários de configuração:

   {
     'format' : '%(message)s'
   }

e:

   {
     'format' : '%(asctime)s %(levelname)-8s %(name)-15s %(message)s',
     'datefmt' : '%Y-%m-%d %H:%M:%S'
   }

respectivamente; e como esses dicionários não contêm a chave especial
"'()'", a instanciação é inferida pelo contexto. Como resultado, são
criadas instâncias padrão de "logging.Formatter". O subdicionário de
configuração do terceiro formatador, com o id "custom", é:

   {
     '()' : 'my.package.customFormatterFactory',
     'bar' : 'baz',
     'spam' : 99.9,
     'answer' : 42
   }

e isso contém a chave especial "'()'", o que significa que se deseja
uma instanciação definida pelo usuário. Nesse caso, a função factory
especificada será usada. Se for um chamável real, ele será usado
diretamente — caso contrário, se você especificar uma string (como no
exemplo), o chamável real será localizado usando os mecanismos normais
de importação. O callable será chamado com os itens restantes no
subdicionário de configuração como argumentos nomeados. No exemplo
acima, assume-se que o formatter com id "custom" seja retornado pela
chamada:

   my.package.customFormatterFactory(bar='baz', spam=99.9, answer=42)

Aviso:

  Os valores de chaves como "bar", "spam" e "answer" no exemplo acima
  não devem ser dicionários de configuração nem referências como
  "cfg://foo", ou "ext://bar" porque eles não serão processados pelo
  maquinário de configuração — serão simplesmente passados para a
  função callable como estão.

A chave "'()'" foi usada como chave especial porque não é um nome
válido de parâmetro nomeado e, portanto, não conflita com os nomes dos
argumentos nomeados usados na chamada. O "'()'" também serve como um
mnemônico de que o valor correspondente é um chamável.

You can also specify a special key "'.'" whose value is a dictionary
is a mapping of attribute names to values. If found, the specified
attributes will be set on the user-defined object before it is
returned. Thus, with the following configuration:

   {
     '()' : 'my.package.customFormatterFactory',
     'bar' : 'baz',
     'spam' : 99.9,
     'answer' : 42,
     '.' {
       'foo': 'bar',
       'baz': 'bozz'
     }
   }

o formatador retornado terá o atributo "foo" definido como "'bar'" e o
atributo "baz" definido como "'bozz'".

Aviso:

  Os valores de atributos como "foo" e "baz" no exemplo acima não
  devem ser dicionários de configuração nem referências como
  "cfg://foo" ou "ext://bar" porque eles não serão processados pelo
  maquinário de configuração, mas definidos como valores de atributo
  exatamente como foram fornecidos.


Ordem de configuração de manipuladores
--------------------------------------

Handlers are configured in alphabetical order of their keys, and a
configured handler replaces the configuration dictionary in (a working
copy of) the "handlers" dictionary in the schema. If you use a
construct such as "cfg://handlers.foo", then initially
"handlers['foo']" points to the configuration dictionary for the
handler named "foo", and later (once that handler has been configured)
it points to the configured handler instance. Thus,
"cfg://handlers.foo" could resolve to either a dictionary or a handler
instance. In general, it is wise to name handlers in a way such that
dependent handlers are configured _after_ any handlers they depend on;
that allows something like "cfg://handlers.foo" to be used in
configuring a handler that depends on handler "foo". If that dependent
handler were named "bar", problems would result, because the
configuration of "bar" would be attempted before that of "foo", and
"foo" would not yet have been configured. However, if the dependent
handler were named "foobar", it would be configured after "foo", with
the result that "cfg://handlers.foo" would resolve to configured
handler "foo", and not its configuration dictionary.


Acesso a objetos externos
-------------------------

Há momentos em que uma configuração precisa se referir a objetos
externos à configuração, por exemplo "sys.stderr". Se o dicionário de
configuração for construído usando código Python, isso é simples, mas
surge um problema quando a configuração é fornecida por meio de um
arquivo texto (por exemplo, JSON, YAML). Em um arquivo texto, não há
uma forma padrão de distinguir "sys.stderr" da string literal
"'sys.stderr'".  Para facilitar essa distinção, o sistema de
configuração procura por determinados prefixos especiais em valores de
string e os trata de forma especial. Por exemplo, se a string literal
"'ext://sys.stderr'" for fornecida como um valor na configuração,
então o prefixo "ext://" será removido e o restante do valor será
processado usando os mecanismos normais de importação.

O tratamento desses prefixos é feito de forma análoga ao tratamento de
protocolos: existe um mecanismo genérico para procurar prefixos que
correspondam à expressão regular ^(?P<prefix>[a-z]+)://(?P<suffix>.*),
de modo que, se o "prefix" for reconhecido, o "suffix" é processado de
uma forma dependente do prefixo e o resultado desse processamento
substitui o valor da string. Se o prefixo não for reconhecido, então o
valor da string é mantido como está.


Acesso a objetos internos
-------------------------

Além de objetos externos, às vezes também é necessário fazer
referência a objetos na configuração. Isso será feito de forma
implícita pelo sistema de configuração para coisas que ele conhece.
Por exemplo, o valor em forma de string "'DEBUG'" para um "level" em
um logger ou manipulador será automaticamente convertido para o valor
"logging.DEBUG", e as entradas "handlers", "filters" e "formatter"
receberão um identificador de objeto e o resolverão para o objeto de
destino apropriado.

No entanto, é necessário um mecanismo mais genérico para objetos
definidos pelo usuário que não são conhecidos pelo módulo "logging".
Por exemplo, considere "logging.handlers.MemoryHandler", que recebe um
argumento "target" que é outro manipulador para o qual delegar. Como o
sistema já conhece essa classe, então, na configuração, o "target"
fornecido só precisa ser o id do objeto do manipulador de destino
relevante, e o sistema resolverá esse id para o manipulador
correspondente. Se, porém, um usuário definir um
"my.package.MyHandler" que tenha um manipulador "alternate", o sistema
de configuração não saberia que "alternate" se refere a um
manipulador. Para atender a esse caso, um sistema genérico de
resolução permite que o usuário especifique:

   handlers:
     file:
       # configuration of file handler goes here

     custom:
       (): my.package.MyHandler
       alternate: cfg://handlers.file

A cadeia literal "'cfg://handlers.file'" será resolvida de maneira
análoga às strings com o prefixo "ext://" mas procurando na própria
configuração em vez do espaço de nomes de importação. O mecanismo
permite acesso por ponto ou por índice, de forma semelhante ao que é
fornecido por "str.format". Assim, dado o seguinte trecho:

   handlers:
     email:
       class: logging.handlers.SMTPHandler
       mailhost: localhost
       fromaddr: my_app@domain.tld
       toaddrs:
         - support_team@domain.tld
         - dev_team@domain.tld
       subject: Houston, we have a problem.

in the configuration, the string "'cfg://handlers'" would resolve to
the dict with key "handlers", the string "'cfg://handlers.email" would
resolve to the dict with key "email" in the "handlers" dict, and so
on.  The string "'cfg://handlers.email.toaddrs[1]" would resolve to
"'dev_team@domain.tld'" and the string
"'cfg://handlers.email.toaddrs[0]'" would resolve to the value
"'support_team@domain.tld'". The "subject" value could be accessed
using either "'cfg://handlers.email.subject'" or, equivalently,
"'cfg://handlers.email[subject]'".  The latter form only needs to be
used if the key contains spaces or non-alphanumeric characters.  If an
index value consists only of decimal digits, access will be attempted
using the corresponding integer value, falling back to the string
value if needed.

Dada uma string "cfg://handlers.myhandler.mykey.123", ela será
resolvida como "config_dict['handlers']['myhandler']['mykey']['123']".
Se a string for especificada como
"cfg://handlers.myhandler.mykey[123]", o sistema tentará obter o valor
de "config_dict['handlers']['myhandler']['mykey'][123]" e, caso isso
falhe, recorrerá a
"config_dict['handlers']['myhandler']['mykey']['123']".


Resolução de importações e importadores personalizados
------------------------------------------------------

Import resolution, by default, uses the builtin "__import__()"
function to do its importing. You may want to replace this with your
own importing mechanism: if so, you can replace the "importer"
attribute of the "DictConfigurator" or its superclass, the
"BaseConfigurator" class. However, you need to be careful because of
the way functions are accessed from classes via descriptors. If you
are using a Python callable to do your imports, and you want to define
it at class level rather than instance level, you need to wrap it with
"staticmethod()". For example:

   from importlib import import_module
   from logging.config import BaseConfigurator

   BaseConfigurator.importer = staticmethod(import_module)

Você não precisa envolver com "staticmethod()" se estiver definindo o
chamável de importação em uma *instância* do configurador.


Formato do arquivo de configuração
==================================

The configuration file format understood by "fileConfig()" is based on
"configparser" functionality. The file must contain sections called
"[loggers]", "[handlers]" and "[formatters]" which identify by name
the entities of each type which are defined in the file. For each such
entity, there is a separate section which identifies how that entity
is configured.  Thus, for a logger named "log01" in the "[loggers]"
section, the relevant configuration details are held in a section
"[logger_log01]". Similarly, a handler called "hand01" in the
"[handlers]" section will have its configuration held in a section
called "[handler_hand01]", while a formatter called "form01" in the
"[formatters]" section will have its configuration specified in a
section called "[formatter_form01]". The root logger configuration
must be specified in a section called "[logger_root]".

Nota:

  The "fileConfig()" API is older than the "dictConfig()" API and does
  not provide functionality to cover certain aspects of logging. For
  example, you cannot configure "Filter" objects, which provide for
  filtering of messages beyond simple integer levels, using
  "fileConfig()". If you need to have instances of "Filter" in your
  logging configuration, you will need to use "dictConfig()". Note
  that future enhancements to configuration functionality will be
  added to "dictConfig()", so it's worth considering transitioning to
  this newer API when it's convenient to do so.

Exemplos dessas seções no arquivo são fornecidos abaixo.

   [loggers]
   keys=root,log02,log03,log04,log05,log06,log07

   [handlers]
   keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09

   [formatters]
   keys=form01,form02,form03,form04,form05,form06,form07,form08,form09

O logger raiz deve especificar um nível e uma lista de manipuladores.
Um exemplo de seção de logger raiz é dado abaixo.

   [logger_root]
   level=NOTSET
   handlers=hand01

The "level" entry can be one of "DEBUG, INFO, WARNING, ERROR,
CRITICAL" or "NOTSET". For the root logger only, "NOTSET" means that
all messages will be logged. Level values are "eval()"uated in the
context of the "logging" package's namespace.

A entrada "handlers" é uma lista separada por vírgulas com os nomes
dos manipuladores, que devem aparecer na seção "[handlers]". Esses
nomes precisam aparecer na seção "[handlers]" e ter seções
correspondentes no arquivo de configuração.

Para loggers que não sejam o logger raiz, são necessárias algumas
informações adicionais. Isso é ilustrado pelo exemplo a seguir.

   [logger_parser]
   level=DEBUG
   handlers=hand01
   propagate=1
   qualname=compiler.parser

As entradas "level" e "handlers" são interpretadas da mesma forma que
o logger raiz, exceto que, se o nível de um logger não raiz for
especificado como "NOTSET", o sistema consulta os loggers situados
acima na hierarquia para determinar o nível efetivo do logger. O item
"propagate" é definido como 1 para indicar que as mensagens devem ser
propagadas para os manipuladores acima na hierarquia de loggers a
partir deste logger, ou 0 para indicar que as mensagens não são
propagadas para manipuladores acima na hierarquia. O item "qualname" é
o nome de canal hierárquico do logger, ou seja, o nome usado pela
aplicação para obter o logger.

As seções que especificam a configuração de manipuladores são
exemplificadas pelo seguinte.

   [handler_hand01]
   class=StreamHandler
   level=NOTSET
   formatter=form01
   args=(sys.stdout,)

A entrada "class" indica a classe do manipulador (conforme determinada
por "eval()" no espaço de nomes do pacote "logging"). O "level" é
interpretado da mesma forma que para loggers, e "NOTSET" é entendido
como “registrar tudo”.

A entrada "formatter" indica o nome da chave do formatador para esse
manipulador. Se estiver em branco, um formatador padrão
("logging._defaultFormatter") será usado. Se um nome for especificado,
ele deve aparecer na seção "[formatters]" e ter uma seção
correspondente no arquivo de configuração.

The "args" entry, when "eval()"uated in the context of the "logging"
package's namespace, is the list of arguments to the constructor for
the handler class. Refer to the constructors for the relevant
handlers, or to the examples below, to see how typical entries are
constructed. If not provided, it defaults to "()".

The optional "kwargs" entry, when "eval()"uated in the context of the
"logging" package's namespace, is the keyword argument dict to the
constructor for the handler class. If not provided, it defaults to
"{}".

   [handler_hand02]
   class=FileHandler
   level=DEBUG
   formatter=form02
   args=('python.log', 'w')

   [handler_hand03]
   class=handlers.SocketHandler
   level=INFO
   formatter=form03
   args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)

   [handler_hand04]
   class=handlers.DatagramHandler
   level=WARN
   formatter=form04
   args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)

   [handler_hand05]
   class=handlers.SysLogHandler
   level=ERROR
   formatter=form05
   args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)

   [handler_hand06]
   class=handlers.NTEventLogHandler
   level=CRITICAL
   formatter=form06
   args=('Python Application', '', 'Application')

   [handler_hand07]
   class=handlers.SMTPHandler
   level=WARN
   formatter=form07
   args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')
   kwargs={'timeout': 10.0}

   [handler_hand08]
   class=handlers.MemoryHandler
   level=NOTSET
   formatter=form08
   target=
   args=(10, ERROR)

   [handler_hand09]
   class=handlers.HTTPHandler
   level=NOTSET
   formatter=form09
   args=('localhost:9022', '/log', 'GET')
   kwargs={'secure': True}

As seções que especificam a configuração do formatador são
caracterizadas pelo seguinte.

   [formatter_form01]
   format=F1 %(asctime)s %(levelname)s %(message)s
   datefmt=
   style=%
   validate=True
   class=logging.Formatter

The arguments for the formatter configuration are the same as the keys
in the dictionary schema formatters section.

Nota:

  Devido ao uso de "eval()" conforme descrito acima, há riscos de
  segurança potenciais decorrentes do uso de "listen()" para enviar e
  receber configurações por meio de soquetes. Os riscos se limitam a
  situações em que vários usuários sem confiança mútua executam código
  na mesma máquina; consulte a documentação de "listen()" para mais
  informações.

Ver também:

  Módulo "logging"
     Referência da API para o módulo de logging.

  Módulo "logging.handlers"
     Tratadores úteis incluídos no módulo logging.
