8000 JSON Module Support for Elixir 1.18 and CI Environment Updates by michelboaventura · Pull Request #264 · akoutmos/prom_ex · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

JSON Module Support for Elixir 1.18 and CI Environment Updates #264

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
elixir-version: "1.17.2"
otp-version: "27.0"
- name: Restore cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
deps
Expand Down Expand Up @@ -53,6 +53,7 @@ jobs:
matrix:
elixir:
- "1.17"
- "1.18"
otp:
- "26.0"
- "27.0"
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- PromEx now uses Elixir 1.18 default JSON module and falls back to Jason if it is not available.

## [1.11.0] - 2024-10-24

### Fixed
Expand Down
4 changes: 2 additions & 2 deletions example_applications/web_app/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ config :logger, :console,
format: "$time $metadata[$level] $message\n",
metadata: [:request_id]

# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason
# Use JSON falling back to Jason for JSON parsing in Phoenix
config :phoenix, :json_library, PromEx.JSON

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
Expand Down
6 changes: 3 additions & 3 deletions example_applications/web_app/stress_test.exs
DDB0
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ end
|> Finch.build(users_path)
|> Finch.request(StressTester)

all_users = Jason.decode!(body)
all_users = PromEx.JSON.decode!(body)

# Level up all the users slowly
all_users
Expand Down Expand Up @@ -78,7 +78,7 @@ task_2 =
age = Faker.random_between(18, 75)

data = %{first_name: first_name, last_name: last_name, age: age, points: 0}
payload = Jason.encode!(data)
payload = PromEx.JSON.encode!(data)

:post
|> Finch.build(users_path, [{"content-type", "application/json"}], payload)
Expand All @@ -98,7 +98,7 @@ Task.await_many([task_1, task_2], 60_000)
|> Finch.build(users_path)
|> Finch.request(StressTester)

all_users = Jason.decode!(body)
all_users = PromEx.JSON.decode!(body)

all_users
|> Enum.shuffle()
Expand Down
6 changes: 3 additions & 3 deletions lib/prom_ex/dashboard_renderer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,16 @@ defmodule PromEx.DashboardRenderer do
end

@doc """
This function will decode the JSON dashboard using `Jason`. If any errors occur during the decoding process,
the struct will be marked as having invalid JSON.
This function will decode the JSON dashboard using JSON if available and fallback to Jason. If any errors
occur during the decoding process, the struct will be marked as having invalid JSON.
"""
@spec decode_dashboard(__MODULE__.t()) :: __MODULE__.t()
def decode_dashboard(%__MODULE__{valid_file?: false} = dashboard_render) do
dashboard_render
end

def decode_dashboard(%__MODULE__{rendered_file: json_definition} = dashboard_render) do
case Jason.decode(json_definition) do
case PromEx.JSON.decode(json_definition) do
{:ok, decoded_dashboard} ->
%{dashboard_render | decoded_dashboard: decoded_dashboard, valid_json?: true}

Expand Down
2 changes: 1 addition & 1 deletion lib/prom_ex/dashboard_uploader.ex
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ defmodule PromEx.DashboardUploader do
end

defp upload_dashboard(dashboard_definition, grafana_conn, upload_opts, full_dashboard_path) do
dashboard_contents = Jason.encode!(dashboard_definition)
dashboard_contents = PromEx.JSON.encode!(dashboard_definition)

case GrafanaClient.upload_dashboard(grafana_conn, dashboard_contents, upload_opts) do
{:ok, _response_payload} ->
Expand Down
14 changes: 7 additions & 7 deletions lib/prom_ex/grafana_client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ defmodule PromEx.GrafanaClient do

dashboard_uid =
dashboard_contents
|> Jason.decode!()
|> PromEx.JSON.decode!()
|> Map.get("uid")

:get
Expand All @@ -94,7 +94,7 @@ defmodule PromEx.GrafanaClient do
headers = grafana_headers(:post, grafana_conn.authorization)

payload =
Jason.encode!(%{
PromEx.JSON.encode!(%{
uid: folder_uid,
title: title
})
Expand Down Expand Up @@ -136,7 +136,7 @@ defmodule PromEx.GrafanaClient do
overwrite: true
}
|> Map.merge(attrs)
|> Jason.encode!()
|> PromEx.JSON.encode!()

:put
|> Finch.build("#{grafana_conn.base_url}/api/folders/#{folder_uid}", headers, payload)
Expand Down Expand Up @@ -193,7 +193,7 @@ defmodule PromEx.GrafanaClient do
{:time_end, v} -> {:timeEnd, v}
{k, v} -> {k, v}
end)
|> Jason.encode!()
|> PromEx.JSON.encode!()

:post
|> Finch.build("#{grafana_conn.base_url}/api/annotations", headers, payload)
Expand All @@ -204,7 +204,7 @@ defmodule PromEx.GrafanaClient do
defp handle_grafana_response(finch_response) do
case finch_response do
{:ok, %Finch.Response{status: status_code, body: body}} when status_code in [200, 201] ->
{:ok, Jason.decode!(body)}
{:ok, PromEx.JSON.decode!(body)}

{:ok, %Finch.Response{status: status_code} = response} ->
Logger.warning("Received a #{status_code} from Grafana because: #{inspect(response)}")
Expand Down Expand Up @@ -236,12 +236,12 @@ defmodule PromEx.GrafanaClient do
end

defp generate_payload(dashboard_definition, opts) do
dashboard = Jason.decode!(dashboard_definition)
dashboard = PromEx.JSON.decode!(dashboard_definition)

opts
|> Map.new()
|> Map.put(:dashboard, dashboard)
|> Jason.encode!()
|> PromEx.JSON.encode!()
end

defp lookup_status_code(status_code) do
Expand Down
21 changes: 21 additions & 0 deletions lib/prom_ex/json.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule PromEx.JSON do
@moduledoc false

# Delegates to JSON in Elixir v1.18+ or Jason for earlier versions

cond do
Code.ensure_loaded?(JSON) ->
defdelegate decode!(data), to: JSON
defdelegate decode(data), to: JSON
defdelegate encode!(data), to: JSON

Code.ensure_loaded?(Jason) ->
defdelegate decode!(data), to: Jason
defdelegate encode!(data), to: Jason

true ->
message = "Missing a compatible JSON library, add `:jason` to your deps."

IO.warn(message, Macro.Env.stacktrace(__ENV__))
end
end
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ defmodule PromEx.MixProject do
defp deps do
[
# Required dependencies
{:jason, "~> 1.4"},
{:jason, "~> 1.4", optional: true},
{:finch, "~> 0.18"},
{:telemetry, ">= 1.0.0"},
{:telemetry_poller, "~> 1.1"},
Expand Down
2 changes: 1 addition & 1 deletion test/prom_ex/dashboard_uploader_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ defmodule PromEx.DashboardUploaderTest do
{:ok, body, conn} = Plug.Conn.read_body(conn, [])

assert body
|> Jason.decode!()
|> PromEx.JSON.decode!()
|> get_in(["dashboard", "title"]) == "My really cool custom title"

Plug.Conn.resp(conn, 200, response_payload)
Expand Down
4 changes: 2 additions & 2 deletions test/prom_ex/grafana_client_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ defmodule PromEx.GrafanaClientTest do
Bypass.expect(bypass, "POST", "/api/annotations", fn conn ->
{:ok, body, conn} = Plug.Conn.read_body(conn, [])

details = Jason.decode!(body)
details = PromEx.JSON.decode!(body)
assert details["time"] == 1_640_995_200_000
assert details["tags"] == ["some", "tags"]
assert details["text"] == "message"
Expand Down Expand Up @@ -86,7 +86,7 @@ defmodule PromEx.GrafanaClientTest do
Bypass.expect(bypass, "POST", "/api/annotations", fn conn ->
{:ok, body, conn} = Plug.Conn.read_body(conn, [])

details = Jason.decode!(body)
details = PromEx.JSON.decode!(body)
assert details["dashboardId"] == 1
assert details["panelId"] == 2
assert details["time"] == 1_640_995_200_000
Expand Down
4 changes: 2 additions & 2 deletions test/support/test_app_router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ defmodule TestApp.PlugRouter do

plug PromEx.Plug, prom_ex_module: TestApp.PromEx, path: "/metrics"
plug Plug.Telemetry, event_prefix: [:testapp, :plug, :router]
plug Plug.Parsers, parsers: [:json], json_decoder: Jason
plug Plug.Parsers, parsers: [:json], json_decoder: PromEx.JSON
plug :match
plug :dispatch

get "/users/:id" do
conn
|> put_resp_content_type("application/json")
|> send_resp(200, Jason.encode!(%{"id" => conn.params["id"]}))
|> send_resp(200, PromEx.JSON.encode!(%{"id" => conn.params["id"]}))
|> halt()
end

Expand Down
0