Skip to content

Commit 5e60093

Browse files
authored
Merge pull request #1711 from navikt/datapakke-fritekst-avslagsvedtak
Datapakke for avslagsvedtak uten fritekst
2 parents 0759977 + 5e3ee75 commit 5e60093

File tree

9 files changed

+274
-0
lines changed

9 files changed

+274
-0
lines changed

Diff for: datapakker/README.md

+86
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,89 @@ Start en manuell cronjob (husk å slett dersom den feiler):
1919
```
2020
kubectl create job --namespace=supstonad --from=cronjobs/su-datapakke-soknad manuell-test-custom-name-here
2121
```
22+
23+
## How-to
24+
### Lage en ny datapakke
25+
26+
#### prerequisites
27+
1. legg inn `Google Cloud Platform` fra `myapps.microsoft.com`
28+
2. En i teamet må inn i BigQuery og gi deg tilgang til prosjektene.
29+
- Klikk på selecten øverst til venste
30+
- En Modal popper opp, klikk på mappen med et tannhjul ved siden av `new project`
31+
- finn fram `supstonad-dev` & `supstonad-prod`
32+
- klikk på knappen `add principal`
33+
- Legg in nav-mail som principal, og disse rollene (trenger kanskje ikke alle - men er disse vi har på dette tidspunktet);
34+
- `BigQuery Admin`
35+
- `BigQuery Data Editor`
36+
- `BigQuery Data Owner`
37+
- `BigQuery Data Viewer`
38+
- `Service Account Admin`
39+
- `Service Account Key Admin`
40+
- `Service Usage Admin`
41+
- `naisdeveloper` (for supstonad-prod)
42+
43+
#### Oppsett
44+
En datapakke har 3 essensielle deler - en database connection, og config for GCP/BigQuery, og en naisjob.
45+
Hovedpoenget med en datapakke er å hente fram data, og lagre det i en BigQuery tabell, for å muligens visualisere det i Metabase.
46+
47+
1. Lag en connection mot databasen
48+
2. kjør ønsket spørring mot databasen
49+
3. konfigurer GCP/BigQuery
50+
4. Lag en nais.yml & dockerfile for å kjøre jobben i nais
51+
52+
#### GCP
53+
1. Gå til `console.cloud.google.com`
54+
2. Velg `BigQuery` fra Quick access
55+
3. Velg `supstonad-dev` eller `supstonad-prod` fra selecten øverst til venstre
56+
4. klikk 3-dotter på ressursen i venstre menyen -> `create dataset`
57+
- `Dataset ID` skal være skal speile datasett navnet du satt i BigQuery configen i koden
58+
- location settes til `Region` & `europe-north1`
59+
- Klikk `create dataset`
60+
5. Klikk 3-dotter på datasettet du nettopp lagde -> `create table`
61+
- create table from `empty table`
62+
- `table` skal speile tabell navnet du satt i BigQuery configen i koden
63+
- Legg til ønskelig schema
64+
- eksempel `id` `string` `required`
65+
- klikk `create table`
66+
6. Det samme må nå gjøres for det andre miljøet
67+
68+
69+
### Visualisering av data fra BigQuery
70+
71+
#### NADA
72+
Før du kan visualisere dataen ved bruk av Metabase, må vi legge til datapakken vår i NADA.
73+
1. Gå til `data.intern.nav.no` (dev - `data.intern.dev.nav.no`)
74+
2. Finn fram til supstonad - eksempel på hvordan du kan finne fram
75+
- klikk på `Utforsk områder`
76+
- velg `Produkområde Pensjon` i selected øverst til venstre
77+
- velg `SU` fra menyen til venstre
78+
- Klikk på `Produkter` fanen øverst i midten
79+
- Klikk på `supstonad`
80+
- Gjerne utforsk hva vi allerede har
81+
3. Ved menyen til venstre, klikk `Legg til datasett`
82+
4. Fyll inn informasjon som ønsket
83+
- `Velg tabell eller view` lister opp bare prod-basen i BigQuery. Dersom du bare har lagt til dev på dette tidspunktet, må du gå tilbake, og legge til prod.
84+
- Klikk `Lagre`
85+
5. Legg til tilganger hvis den ikke er åpen for alle.
86+
6. sjekk at datasettet ser riktig ut
87+
7. Under overskiften, har du forskjellige links, trykk på `Legg til metabase` hvis du har ønske om å visualisere datasettet i Metabase
88+
89+
Mer info om NADA, etc kan finnes på `docs.knada.io`
90+
91+
92+
#### Metabase
93+
Hvis du vil visualisere dataen fra BigQuery, kan dette gjøres i Metabase. Datasettet må ha vært lagt til i NADA. Hvis ikke dette er gjort, må du gjøre det først.
94+
Tilgang til metabase kommer når du har lagt til GCP i `myapps.microsoft.com` (???)
95+
1. gå og logg inn til `metabase.intern.nav.no` (dev - `metabase.intern.dev.nav.no`)
96+
2. Åpne sidepanelet til venstre: PO Pensjon -> Team Supplerende Stønad
97+
3. Klikk på `new`
98+
- Her er det litt valg muligheter.
99+
- Dersom du er interessert i å lage en basic spørring mot datasettet vi la inn i NADA, velger du `Question`
100+
- Dersom du vil gruppere sammen questions, kan du velge `Dashboard`
101+
- Ved valg av `Question`
102+
1. Velg `Raw Data`
103+
2. skriv inn navnet på tabellen som du lagde i GCP
104+
3. Visaliser dataen som øsnkelig
105+
4. Klikk `Visualize`
106+
107+
Litt mer info om metabase kan finnes på `docs.knada.io/analyse/metabase`

Diff for: datapakker/fritekstAvslag/Dockerfile

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM ghcr.io/navikt/baseimages/temurin:21
2+
3+
COPY init-scripts/* /init-scripts/
4+
COPY datapakker/fritkestAvslag/build/libs/*.jar ./
5+
6+
ENV JAVA_OPTS="-XX:MaxRAMPercentage=75 \
7+
-XX:+HeapDumpOnOutOfMemoryError \
8+
-XX:HeapDumpPath=/oom-dump.hprof"
9+
RUN echo 'java -XX:MaxRAMPercentage=75 -XX:+PrintFlagsFinal -version | grep -Ei "maxheapsize|maxram"' > /init-scripts/0-dump-memory-config.sh

Diff for: datapakker/fritekstAvslag/build.gradle.kts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
dependencies {
2+
implementation(platform("com.google.cloud:libraries-bom:26.33.0"))
3+
implementation("com.google.cloud:google-cloud-bigquery")
4+
implementation(project(":common:domain"))
5+
implementation(project(":common:infrastructure"))
6+
}

Diff for: datapakker/fritekstAvslag/nais-dev.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"secret_env": "dev",
3+
"cluster": "preprod",
4+
"env": {
5+
"GCP_PROJECT": "supstonad-dev-0e48",
6+
"VAULT_MOUNTPATH": "postgresql/preprod-fss/",
7+
"DATABASE_NAME": "supstonad-db-15-dev",
8+
"DATABASE_JDBC_URL": "jdbc:postgresql://b27dbvl030.preprod.local:5432/supstonad-db-15-dev"
9+
}
10+
}

Diff for: datapakker/fritekstAvslag/nais-prod.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"secret_env": "prod",
3+
"cluster": "prod",
4+
"env": {
5+
"GCP_PROJECT": "supstonad-prod-9599",
6+
"VAULT_MOUNTPATH": "postgresql/prod-fss/",
7+
"DATABASE_NAME": "supstonad-db-15-prod",
8+
"DATABASE_JDBC_URL": "jdbc:postgresql://A01DBVL036.adeo.no:5432/supstonad-db-15-prod"
9+
}
10+
}

Diff for: datapakker/fritekstAvslag/nais.yml

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
apiVersion: nais.io/v1
2+
kind: Naisjob
3+
metadata:
4+
labels:
5+
team: supstonad
6+
name: su-datapakke-fritekstAvslag
7+
namespace: supstonad
8+
spec:
9+
# Run every 1st day of the month at 00:15
10+
schedule: '15 0 1 * *'
11+
image: {{ image }}
12+
concurrencyPolicy: Replace
13+
vault:
14+
enabled: true
15+
paths:
16+
- mountPath: /var/run/secrets/nais.io/vault
17+
kvPath: /secret/supstonad/{{ secret_env }}
18+
webproxy: true
19+
env:
20+
{{#each env}}
21+
- name: {{@key}}
22+
value: "{{this}}"
23+
{{/each}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package no.nav.su.se.bakover.datapakker.fritekstAvslag
2+
3+
import com.google.auth.oauth2.GoogleCredentials
4+
import com.google.cloud.bigquery.BigQuery
5+
import com.google.cloud.bigquery.BigQueryOptions
6+
import com.google.cloud.bigquery.FormatOptions
7+
import com.google.cloud.bigquery.JobId
8+
import com.google.cloud.bigquery.JobStatistics
9+
import com.google.cloud.bigquery.QueryJobConfiguration
10+
import com.google.cloud.bigquery.TableId
11+
import com.google.cloud.bigquery.WriteChannelConfiguration
12+
import no.nav.su.se.bakover.database.Postgres
13+
import no.nav.su.se.bakover.database.VaultPostgres
14+
import org.slf4j.LoggerFactory
15+
import java.io.File
16+
import java.io.FileInputStream
17+
import java.io.InputStream
18+
import java.nio.channels.Channels
19+
import java.time.YearMonth
20+
import java.util.UUID
21+
import javax.sql.DataSource
22+
23+
private val logger = LoggerFactory.getLogger("DatapakkerFritekstAvslag")
24+
private const val LOCATION = "europe-north1"
25+
26+
fun main() {
27+
val databaseUrl = System.getenv("DATABASE_JDBC_URL")
28+
val antallAvslagsvedtakUtenFritekst = VaultPostgres(
29+
jdbcUrl = databaseUrl,
30+
vaultMountPath = System.getenv("VAULT_MOUNTPATH"),
31+
databaseName = System.getenv("DATABASE_NAME"),
32+
).getDatasource(Postgres.Role.ReadOnly).let {
33+
logger.info("Startet database med url: $databaseUrl")
34+
it.use { hentAntallAvslagsvedtakUtenFritekst(it) }
35+
}
36+
37+
deleteAllAndWriteToBigQuery(antallAvslagsvedtakUtenFritekst = antallAvslagsvedtakUtenFritekst)
38+
}
39+
40+
fun hentAntallAvslagsvedtakUtenFritekst(datasource: DataSource): List<AvslagsvedtakUtenFritekst> {
41+
return datasource.connection.let {
42+
it.use {
43+
it.prepareStatement(
44+
"""
45+
select count(d.generertdokumentjson), to_char(date_trunc('month', v.opprettet), 'YYYY-MM') as grupperingsdato
46+
from vedtak v
47+
join dokument d on v.id = d.vedtakid
48+
where length(trim(d.generertdokumentjson ->> 'fritekst')) < 1
49+
and v.vedtaktype = 'AVSLAG'
50+
group by grupperingsdato;
51+
""".trimIndent(),
52+
).executeQuery().let {
53+
val result = mutableListOf<AvslagsvedtakUtenFritekst>()
54+
55+
while (it.next()) {
56+
result.add(
57+
AvslagsvedtakUtenFritekst(
58+
antall = it.getInt("count"),
59+
forMånedÅr = YearMonth.parse(it.getString("grupperingsdato")),
60+
),
61+
)
62+
}
63+
64+
result.toList()
65+
}
66+
}
67+
}
68+
}
69+
70+
fun deleteAllAndWriteToBigQuery(
71+
jsonKey: InputStream = FileInputStream(File("/var/run/secrets/nais.io/vault/bigquery")),
72+
project: String = System.getenv("GCP_PROJECT"),
73+
dataset: String = "avslagsvedtak",
74+
table: String = "antallAvslagsvedtakUtenFritekst",
75+
antallAvslagsvedtakUtenFritekst: List<AvslagsvedtakUtenFritekst>,
76+
) {
77+
val credentials = GoogleCredentials.fromStream(jsonKey)
78+
79+
val bq = BigQueryOptions
80+
.newBuilder()
81+
.setCredentials(credentials)
82+
.setLocation(LOCATION)
83+
.setProjectId(project)
84+
.build().service
85+
86+
deleteAll(bq)
87+
88+
val jobId = JobId.newBuilder().setLocation(LOCATION).setJob(UUID.randomUUID().toString()).build()
89+
90+
val configuration = WriteChannelConfiguration.newBuilder(
91+
TableId.of(project, dataset, table),
92+
).setFormatOptions(FormatOptions.csv()).build()
93+
94+
val job = bq.writer(jobId, configuration).let {
95+
it.use { channel ->
96+
Channels.newOutputStream(channel).use { os ->
97+
os.write(antallAvslagsvedtakUtenFritekst.toCSV().toByteArray())
98+
}
99+
}
100+
it.job.waitFor()
101+
}
102+
103+
logger.info("job statistikk: ${job.getStatistics<JobStatistics.LoadStatistics>()}")
104+
}
105+
106+
fun deleteAll(
107+
bq: BigQuery,
108+
dataset: String = "avslagsvedtak",
109+
table: String = "antallAvslagsvedtakUtenFritekst",
110+
) {
111+
val query = QueryJobConfiguration.newBuilder(
112+
"DELETE FROM `$dataset.$table` WHERE true",
113+
).setUseLegacySql(false).build()
114+
115+
val result = bq.query(query)
116+
logger.info("slettet antall linjer ${result.totalRows}")
117+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package no.nav.su.se.bakover.datapakker.fritekstAvslag
2+
3+
import java.time.YearMonth
4+
5+
data class AvslagsvedtakUtenFritekst(
6+
val antall: Int,
7+
val forMånedÅr: YearMonth,
8+
)
9+
10+
fun List<AvslagsvedtakUtenFritekst>.toCSV(): String = this.joinToString(separator = "\n") {
11+
"${it.antall},${it.forMånedÅr}"
12+
}

Diff for: settings.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ include("common:infrastructure:cxf")
2121
include("common:presentation")
2222
include("database")
2323
include("datapakker:soknad")
24+
include("datapakker:fritekstAvslag")
2425
include("dokument:application")
2526
include("dokument:domain")
2627
include("dokument:infrastructure")

0 commit comments

Comments
 (0)