- Add org-id resolution for [[id:...]] links by building ID locations database once before parallel export - Handle broken file links gracefully with org-export-with-broken-links - Fix race condition in parallel exports by pre-building ID cache - Fix Quartz config not being applied: cp was preserving nix store hash prefix in filename instead of using explicit destination filename - Continue pipeline even when some exports fail, reporting failures - Improve error handling and logging throughout export pipeline
110 lines
3.1 KiB
Elixir
110 lines
3.1 KiB
Elixir
defmodule OrgGarden.Telemetry do
|
|
@moduledoc """
|
|
Telemetry event definitions and logging handler.
|
|
|
|
## Events
|
|
|
|
The following telemetry events are emitted:
|
|
|
|
* `[:org_garden, :export, :start]` — Export of a single file started
|
|
- Metadata: `%{file: path}`
|
|
|
|
* `[:org_garden, :export, :stop]` — Export of a single file completed
|
|
- Measurements: `%{duration: native_time}`
|
|
- Metadata: `%{file: path}`
|
|
|
|
* `[:org_garden, :export, :exception]` — Export failed
|
|
- Measurements: `%{duration: native_time}`
|
|
- Metadata: `%{file: path, kind: kind, reason: reason}`
|
|
|
|
* `[:org_garden, :watcher, :file_processed]` — File change processed
|
|
- Metadata: `%{path: path, event: :created | :modified | :deleted}`
|
|
|
|
* `[:org_garden, :server, :start]` — Server started
|
|
- Metadata: `%{port: port}`
|
|
|
|
* `[:org_garden, :server, :stop]` — Server stopped
|
|
- Metadata: `%{reason: reason}`
|
|
|
|
## Usage
|
|
|
|
Attach a handler to log events:
|
|
|
|
OrgGarden.Telemetry.attach_logger()
|
|
|
|
Or use `:telemetry.attach/4` for custom handling.
|
|
"""
|
|
|
|
require Logger
|
|
|
|
@doc """
|
|
Attach a simple logging handler for telemetry events.
|
|
"""
|
|
def attach_logger do
|
|
events = [
|
|
[:org_garden, :export, :stop],
|
|
[:org_garden, :export, :exception],
|
|
[:org_garden, :watcher, :file_processed],
|
|
[:org_garden, :server, :start],
|
|
[:org_garden, :server, :stop]
|
|
]
|
|
|
|
:telemetry.attach_many(
|
|
"org-garden-logger",
|
|
events,
|
|
&handle_event/4,
|
|
nil
|
|
)
|
|
end
|
|
|
|
@doc """
|
|
Detach the logging handler.
|
|
"""
|
|
def detach_logger do
|
|
:telemetry.detach("org-garden-logger")
|
|
end
|
|
|
|
# -------------------------------------------------------------------
|
|
# Event handlers
|
|
# -------------------------------------------------------------------
|
|
|
|
defp handle_event([:org_garden, :export, :stop], measurements, metadata, _config) do
|
|
duration_ms = System.convert_time_unit(measurements.duration, :native, :millisecond)
|
|
Logger.debug("Export completed: #{metadata.file} (#{duration_ms}ms)")
|
|
end
|
|
|
|
defp handle_event([:org_garden, :export, :exception], _measurements, metadata, _config) do
|
|
Logger.error("Export failed: #{metadata.file}")
|
|
end
|
|
|
|
defp handle_event([:org_garden, :watcher, :file_processed], _measurements, metadata, _config) do
|
|
Logger.debug("Watcher processed: #{metadata.event} #{metadata.path}")
|
|
end
|
|
|
|
defp handle_event([:org_garden, :server, :start], _measurements, metadata, _config) do
|
|
Logger.info("Server started on port #{metadata.port}")
|
|
end
|
|
|
|
defp handle_event([:org_garden, :server, :stop], _measurements, metadata, _config) do
|
|
Logger.info("Server stopped: #{inspect(metadata.reason)}")
|
|
end
|
|
|
|
# -------------------------------------------------------------------
|
|
# Convenience functions for emitting events
|
|
# -------------------------------------------------------------------
|
|
|
|
@doc """
|
|
Wrap a function with export telemetry events.
|
|
"""
|
|
def span_export(file, fun) when is_function(fun, 0) do
|
|
:telemetry.span(
|
|
[:org_garden, :export],
|
|
%{file: file},
|
|
fn ->
|
|
result = fun.()
|
|
{result, %{file: file}}
|
|
end
|
|
)
|
|
end
|
|
end
|