Yauaa (Yet Another UserAgent Analyzer)

repository·main·Indexed 21 days ago

https://github.com/nielsbasjes/yauaa

A high-performance Java library for parsing User-Agent strings and Client Hints to extract detailed device, browser, and operating system attributes. It supports Java, Scala, and Kotlin, and provides User Defined Functions (UDFs) for systems like NiFi and Elasticsearch. Yauaa utilizes an ANTLR4-based tree parsing approach and a confidence-based matcher system to resolve attribute conflicts.

Tokens
42K
Snippets
97
Records
137
Agent score
72%

What's inside Yauaa

  1. Overview of Yauaa

    main

    Yauaa (Yet Another UserAgent Analyzer) is a Java library designed to parse and analyze User-Agent strings and, where available, User-Agent Client Hints. It extracts a wide range of relevant attributes from these strings to provide detailed device, browser, and application information.

    Key features:

    • Supports Java, Scala, and Kotlin.
    • Provides ready-to-use User Defined Functions (UDFs) for various processing systems (e.g., NiFi, Elasticsearch).
    • Capable of detecting robots, browsers, apps, hacking tools, and more.
  2. Overview of Yauaa: Yet Another UserAgent Analyzer

    main

    Yauaa is a Java library designed to parse and analyze User-Agent strings and, where available, User-Agent Client Hints. Its primary goal is to extract as many relevant device and browser attributes as possible from these strings.

    Key features include:

    • Support for Java, Scala, and Kotlin.
    • Ready-to-use User Defined Functions (UDFs) for various data processing systems.
    • Ability to extract detailed metadata from complex User-Agent headers.
  3. Understand Yauaa performance characteristics

    main

    Yauaa's performance varies based on the complexity and length of the UserAgent string being analyzed.

    • Raw Analysis Speed: Typically ranges from 500 to 4,000 UserAgents per second (averaging ~2,000 per second or ~0.5ms per analysis).
    • Cached Analysis Speed: Yauaa uses an internal LRU (Least Recently Used) cache. If a UserAgent has been seen before, retrieval speed is significantly faster, exceeding 1,000,000 per second (< 1 microsecond).
    • Memory Footprint: The engine requires approximately 220MiB of RAM just for the core engine, excluding any additional caching overhead.
  4. Limitations regarding Client Hints in LogParser UDF

    main
    The Yauaa LogParser UDF cannot support User-Agent Client Hints. This is because the LogParser architecture is designed to dissect a single field into multiple pieces, whereas Client Hints involve multiple distinct fields that cannot be combined into the single-field dissection model used by this UDF.
  5. Understand User-Agent manipulations and '??' version reports

    main

    Yauaa may report ?? for certain version fields (e.g., OperatingSystemNameVersion: 'Windows NT ??'). This is often not a bug, but a result of intentional User-Agent reduction/manipulation by browser engines like Chromium.

    When browsers remove specific information from the User-Agent header to prevent fingerprinting, Yauaa detects these documented manipulations and may overrule the literal values in the header to avoid providing false information. If the information is no longer present in the User-Agent string, Yauaa cannot invent it.

  6. Handle immutable instances in Apache Beam

    main
    Apache Beam requires DoFn instances to be immutable; they must not modify the provided instance but instead return a new one. UserAgentAnalysisDoFn provides a clone() method that handles this via a serialization round-trip. If your specific record class allows for a more efficient cloning mechanism, you should override the clone() method to improve performance.
  7. What data Yauaa extracts from User-Agents

    main

    Yauaa extracts a comprehensive set of fields from a provided User-Agent string and, when available, from Client Hints. The extracted data is categorized into several logical groups:

    • Device: Includes Class (e.g., Phone), Name, and Brand.
    • Operating System: Includes Class (e.g., Mobile), Name, Version, Name Version, and Version Build.
    • Layout Engine: Includes Class (e.g., Browser), Name, Version, Version Major, Name Version, and Name Version Major.
    • Agent: Includes Class (e.g., Browser), Name, Version, Version Major, Name Version, and Name Version Major.

    This allows for granular analysis of the hardware, software environment, and the specific browser agent being used.

    User-Agent: Mozilla/5.0 (Linux; Android 7.0; Nexus 6 Build/NBD90Z) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36
    
    Extracted Fields Example:
    - Device Class: Phone
    - Device Name: Google Nexus 6
    - Operating System Name: Android
    - Agent Name: Chrome
    ... (and many more)
  8. How Yauaa parses UserAgents

    main

    Unlike many analyzers that rely on ordered lists of regular expressions, Yauaa uses a two-step approach to handle the complexity and 'lying' nature of UserAgent strings:

    1. Tree Parsing: An ANTLR4-based parser converts the UserAgent string into a structured tree. This handles >99% of real-world traffic. If a string cannot be parsed, it is typically due to manual invalidation (hacker/malformed strings).
    2. Matcher Execution: A collection of matchers walks the parsed tree. A matcher triggers if specific patterns are found in the tree. Each matcher provides a value and a confidence level (ranging from 0 to 10,000,000) for specific attributes.

    Conflict Resolution: If multiple matchers attempt to set the same attribute, the one with the highest confidence level wins.

  9. Understand the performance and resource trade-offs of Yauaa

    main

    Yauaa uses a performance optimization where it walks the parsed tree once and fires findings into a precomputed hashmap that points to applicable matcher actions. This design results in the following characteristics:

    • Matching Speed: Relatively fast, even with hundreds of matchers.
    • Startup Time: Relatively slow due to precomputation.
    • Memory Footprint: High, due to the large number of matchers, the size of the precomputed hashmap, and the cache of parsed UserAgents.
  10. Use flattened path expressions to target tree nodes

    main

    When writing require or extract patterns, you use 'breadcrumb' style paths to navigate the parsed User-Agent tree.

    For a User-Agent like: foo/1.0 ( one ; two three; four ) bar/2.0 (five;six seven)

    Common path patterns include:

    • agent.(1)product.(1).name: Targets the name of the first product.
    • agent.(1)product.(1).version: Targets the version of the first product.
    • agent.(1)product.(1).comments.(1).entry: Targets the first entry in the first comment block.
    • agent.(1)product[1-1]: Uses index-based notation for specific segments (e.g., the first part of a product string).

    Note: Most paths are automatically trimmed of whitespace during parsing.

    agent.(1)product.(1)name="foo"
    agent.(1)product.(1)version="1.0"
    agent.(1)product.(1)comments.(1)entry="one"
  11. Understand the User-Agent parse tree model

    main

    Yauaa models User-Agents based on RFC-2616. The string is parsed into a tree of nodes:

    • agent: The root node representing the whole string.
    • product: The primary components of the string. Each product can have multiple versions and comments.
    • version: The version information associated with a product.
    • comments: A block of text (often in parentheses) containing one or more entries separated by semicolons (;).
    • entry: Individual pieces of information within a comment block.

    Nodes are indexed numerically (e.g., (1), (2)) within their parent context to allow precise path expressions.

  12. How Yauaa matchers and rules work

    main

    Yauaa classifies User-Agent strings by parsing them into a tree structure and matching that tree against a set of Matchers.

    The Matching Process

    1. Parsing: The User-Agent string is parsed into a tree using Antlr4.
    2. Matching: The tree is evaluated against Matchers. A Matcher only succeeds if ALL patterns defined in its require section result in a non-null value.
    3. Extraction & Weighting: For successful matchers, the extract section defines field/value combinations. Each extraction includes a numerical confidence (weight).
    4. Conflict Resolution: If multiple matchers attempt to set the same field, the value with the highest weight wins. Because of this weighting system, the order of matchers in the configuration files does not matter.

    Matcher Components

    A matcher consists of three main parts:

    • require: A list of patterns that must be present (non-null) for the matcher to trigger. Includes the IsNull operator for negative checks.
    • extract: A list of instructions to populate fields. Format: FieldName : Confidence : Extract pattern.
    • options: Configuration flags like verbose, init, or only.
    - matcher:
        require:
        - 'Require pattern'
        extract:
        - 'FieldName : Confidence : Extract pattern'
        options:
        - 'verbose'