Need more control over your charts?
Explore our guides on SQL queries and using dashboard variables for more advanced visualizations.
Visualizing data on a map can provide powerful insights into the geographical distribution of your users, traffic, or events. Whether you're tracking login locations, identifying regional performance issues, or analyzing market reach, map charts turn raw coordinates or IP addresses into an intuitive visual display.
You can create a map visualization in Dashboards using the Map chart type. This chart requires two key pieces of information:
The quickest way to create a map is with the Drag & drop query builder.
For more advanced control, you can use a SQL expression to perform GeoIP lookups yourself. This is especially useful when your IP data needs parsing or is stored within a larger JSON object.
Under the hood, we use a an IP dictionary. You can access it with the dictGetOrNull function.
The dictGetOrNull function retrieves geographic information based on an IP address. Here's the basic structure:
dictGetOrNull(
'default.ip_trie',
'latitude',
'8.8.4.4'::IPv4
)
This function takes three arguments:
1. The dictionary name: 'default.ip_trie'.
2. The attribute you want to retrieve, you can use 'latitude', 'longitude', 'city', 'country_code', 'timezone').
3. The IP address, converted to a supported format - either IPv4, IPv6, or FixedString(16).
The IP dictionary accepts IPv4, IPv6, or FixedString(16) types. Your log data might store IPs as strings, so you'll need to convert them first. Use these functions to parse and convert your IP data:
toIPv4OrNull(ip_string): Converts a string to an IPv4 address.toIPv6OrNull(ip_string): Converts a string to an IPv6 address.IPv6StringToNumOrNull(ip_string): Converts a string to a FixedString(16) representation, which works for both IPv4 and IPv6. This is often the most convenient option.Let's say your logs contain a client_ip field. The following query counts the number of logins from each city and plots them on a map.
SELECT
-- Extract latitude and longitude from the IP
dictGetOrNull('default.ip_trie', 'latitude', ip::IPv4) AS latitude,
dictGetOrNull('default.ip_trie', 'longitude', ip::IPv4) AS longitude,
-- Count the number of events for the value
countMerge(events_count) AS value,
-- Get the city name for the tooltip
any(dictGetOrNull('default.ip_trie', 'city', ip::IPv4)) AS city
FROM (
SELECT
-- Convert the IP string to a format the dictionary can use
toIPv4OrNull(request_ip) AS ip
FROM {{source}}
WHERE dt BETWEEN {{start_time}} AND {{end_time}}
AND ip IS NOT NULL
)
GROUP BY latitude, longitude
HAVING value > 0
When you run this query with the Map chart type selected, it will display a world map with circles representing the concentration of logins in different locations.
Explore our guides on SQL queries and using dashboard variables for more advanced visualizations.
Please let us know at hello@betterstack.com. We're happy to help! 🙏
We use cookies to authenticate users, improve the product user experience, and for personalized ads. Learn more.